The conventional pathing system for the salmon uses a vector field which they move through in real time, dynamically determining where they will move next by affecting the velocity. Since the physics computations are very processor intensive, it can become quite cumbersome on the device running it, since there are usually several hundred moving objects at a time.
My solution is to take a two-pronged approach: first, take advantage of the fact that the path is a state function- that is, given the same start location, the fish will always end up at the same end location- second, use Unity’s data-oriented stack to simplify Physics computations since we are using the same entity multiple times.
Given the first fact, we can easily pre-compute the path of the fish while the user is reading through the summary screen between rounds while the game is not actively running. This allows us to save computing power and avoid unnecessary framerate reductions. We can store the values into a separate data structure (a dictionary with times as the key and positions as the value). We only need keyframes, since, using similar principles to animation, we can let the computer do the heavy lifting and simply interpolate between keyframes if we have a time between them. Then, for every fish we can simply make a function call to access the dictionary with the current run time and place the fish at the proper location.
Secondly, using Unity’s new Data Oriented Technology Stack and Entity Component System, we can represent the fish as a series of values, with each data type stored together sequentially in memory to take advantage of Spatial Locality of Reference- lookup time in memory is exponentially quicker when the data you are using is close to the value you just read. It also allows us to multithread the computation, since the values can be pulled by type and physics computations done together instead of repeating the same process multiple times.
With this, we can grab ONLY the individual components we need for physics calculations, such as the current position, the heading (rotation), and the velocity to determine where to move next, as opposed to the standard Object-Oriented Programming method of pulling and caching the full class object.
This significantly speeds up computation and allows us to be efficient with our cache memory, making the most of our processors and letting us use several thousand entities.