Move an object according to a vector field (flow arrows placed in the scene)

I have an object that I want to get moved in a direction that is controlled by flow arrows placed in the scene. The arrows could just be game objects that push in their Z direction by an amount corresponding to their Z scale.

This could be used for moving an object floating in a water stream, an air stream, or for defining weird custom gravity.

Maybe the object should be moved by only the arrow that is closest at any given time, or maybe by a blend (interpolation) of the closest arrows around the object.

A) How do I efficiently find the one closest arrow?

B) How do I efficiently find the closest arrows around the object (neighbors) and interpolate between their directions such the the closest ones have most effect?

The problem is really two different issues:

1) Find the closest arrows efficiently.
2) (Only needed for B) Interpolate between the closest arrows.

You have solve 1) in a number of different ways.

  • If you only have a small number of arrows in the scene (say, less than 30) it may be fastest to just store them all in a list, and iterate through them all to find the closest.

  • If you know there will never be more than X units between arrows, you can use a collider with radius X to find the arrows within that radius. You can then iterate through those and find the closest one(s).

  • If you have many arrows and they are placed close together in some places and far apart in other places, the above methods may not work efficiently. You can try instead to give all the arrows colliders and make sure the colliders overlap. This lets you use small colliders where the arrows are packed closely and large colliders where they are far apart. You then know in each frame which arrow colliders your object is inside.

  • Another option is to do some pre-processing at design time to make computations more efficient at runtime. You could have a 3d array of Vector3s that divides your game space into "cells". You can make an editor script that calculates the appropriate flow vector for each of the cells, based on one of the above methods. At runtime you then don't need to use the actual arrows - instead you can make a cheap look-up in the array to find the flow vector for the cell your object is currently in. You can also use trilinear interpolation to interpolate the flow vector smoothly.

There are more ways this can be done, but the above should provide a good starting point.

As for solving issue 2), that is a problem of multivariate interpolation in a non-uniform grid.

  • A simple interpolation method is Inverse Distance Weighting, which weights the data points (arrow vectors in this case) according to the inverse of the distance to them.

There are many other methods. Look for research in "Scattered Data Interpolation" to learn more.