I’m using OverlapSphere to get all my actors in certain range near a point.
But this function seems not to update immediately. I did some operations such as moving actors’ position(including their gameobjects) in one FixedUpdate, which made the actor out of the detect range, but when I use this function after the moving operation again, I just get the same results as I get before moving.
So I tested it through IDE’s Immediate Window:
Before Moving:
And the NonAlloc version gives the same wrong result.
Does this function work based on a collider’s snapshot that only updates every FixedUpdate?
If it is a feature but not a bug, which is the most efficient way to collect all actors near a certain point? The only way I have tried was traversing all the actors to calculate their offset.magnitude to the point. It works but seems a little dumb and unefficient.
There are no “snapshots”. It should be obvious that physics only updates when the simulation runs. The simulation runs by default during the FixedUpdate but can be run whenever you like.
Which really sounds like you’re changing the Transform and NOT the physics body. Changing a Transform does not update physics instantly; It ONLY changes the Transform. Even Renderers don’t know about it, they just read it per-frame when they render.
When the physics runs it’ll also read and sync transform changes but you should NOT do this anyway. If it moves in physics, use a Rigidbody and use its API to move; there are plenty of ways to do it because that is the role of the Rigidbody i.e. to move and update the Transform with the latest body pose.
If you need this per-frame then run physics per-frame if you can do that in your project.
Thank you. Now I know how this function works.
But in fact my actors do not use physics component.My goal is to have a function as convenient as the OverlapSphere which can return a List when I input a point and distance.I added colliders to my actors just for using OverlapSphere.
Now this function cant work as expected so there is no need to use physics.
But I still want to know if there is a more efficient way to reach this goal.The only way I have tried was traversing all the actors to calculate their offset.magnitude to the point. It works but seems a little dumb and unefficient.
So I would push even more that you invest in an appropriate spatial acceleration structure as mentioned above. Querying a dedicated structure would be more efficient, especially because you can store all sorts of custom data at that location without having to make return trips to the engine to ask for components etc.
Minor point: regardless of how else you go about optimising this process, avoid using ‘magnitude’ to check if an object is within a certain range. Instead, calculate the square of the threshold distance in advance and then compare it with ‘sqrMagnitude’.
Avoiding square roots has long been good practice, but just in case I did a quick profiler test and found the following:
Assuming you don’t need the magnitude for something else when the threshold check passes:
Using sqrMagnitude vs magnitude is approximately twice as fast.
If you DO need the magnitude for something else when the threshold check passes:
This is slower but more accurate:
float dsqr = offsets[i].sqrMagnitude;
if (dsqr < 10000)
{
float d = Mathf.Sqrt(dsqr);
// do something with d
}
This is faster, presumably because Unity is avoiding a square root internally with some kind of approximation:
float dsqr = offsets[i].sqrMagnitude;
if (dsqr < 10000)
{
float d = offsets[i].magnitude;
// do something with d
}