How one does implement scalar/vector space fields in unity?

Let’s say I want to track some value which is a function of 3d coordinates (x,y,z). Im having object affected by field, and sources creating fields around themselfs.

What I Have now is sources are modifying field value of related object:

Object affected by field is having this component:

public class Affected : MonoBehaviour {
	
	public float value;
	
	void Start () {
		value= 1;
	}
	
	void Update () {
	}
}

While spherical field source is having this component:

public class FieldSource : MonoBehaviour {
	
	public float radius = 5;
	public AnimationCurve fieldForce;

	void Start () {
	
	}
	
	void Update () {	
		var hitColliders = Physics.OverlapSphere(transform.position,radius * 1.2f);

		foreach(var collider in hitColliders){
			GameObject go = collider.gameObject;
			Affected aff = go.GetComponent<Affected>();

			if(aff != null){
				float distance = Vector3.Distance(go.transform.position, transform.position);
				if(distance < radius){
					float x = distance / radius;
					float y = timeScaleCurve.Evaluate(x);
					aff.value = y;
				} else {
					aff.value = 1;	
				}
			}
		}
	}
}

This approach is not really efficient, but at the moment I didn’t thought of anything better.

As you can see, source object are modyfing value of affected component. Unfortunately this approach doesn’t allow me to query world for field value in arbitrary point. Or at least it is not effective.

My question is: Does Unity support 3d value fields (like magnetic, gravitional fields etc) and allow easy querrying for a field value?

Unity does not include any built-in functionality to implement forcefields, but it provides plenty of tools to set it up.

I would set up a system something like this:

  • Each field source has a function that computes the field a at a given point.
  • Create a Manager that gathers up all the field sources in the scene.
  • Have affected objects query the manager to get the net force on their position.

public class FieldSource : MonoBehavior {

     public float effectiveRadius;
     //Have a check so that we can avoid calculating negligible fields

     public Vector3 position;

     public Vector3 CalculateFieldAtPoint ( Vector3 point ) {
          //Figure out the field at the given position.
     }
}

public class FieldManager : MonoBehavior {

     private static FieldSource[] fieldSources;
     private static FieldSource[] FieldSources {
         get {
              if(fieldSources == null)
                    fieldSources= (FieldSource[])FindObjectsOfType(typeof(FieldSource));
              return fieldSources;
         }
     }

     public static Vector3 CalculateFieldAtPoint (Vector3 point) {
          var output = Vector3.zero;
          foreach ( var fieldSource in FieldSources) {
              if( (point - fieldSource.position).sqrMagnitude <= fieldSource.effectiveRadius * fieldSource.effectiveRadius) {
                  output += fieldSource.CalculateFieldAtPoint (point);
              }
           }
           return output;
     }
}

public class Affected : MonoBehaviour {
     public void Update {
          rigidbody.AddForce ( FieldManager.CalculateFieldAtPoint( transform.position);
     }
}