I’m working on a Unity 3D project where I have various objects moving along tracks in the scene. I want to implement a feature where, when the player’s physics-based vehicle is about to collide with one of these objects, the respective object is replaced with a variant containing Rigidbody and Collider components to realistically react to the collision. However, I’d like to achieve this replacement only shortly before the actual collision occurs, without using a trigger system.
Could someone please guide me on how to accomplish this?
Here is an example of Midtown Madness that probably does what I am looking for:
Not a pro, but I think your best strategy would be to use Physics.OverlapSphere to get all objects within range, and check for colliders that way. Not sure if this is performant but it would do what you want and would be a good starting point to make better solutions off of.
Thank you. I appreciate your effort in trying to help me. Unfortunately I can’t use Physics.OverlapSphere as my non-physical objects don’t even have colliders on them. They aren’t even MonoBehaviour instances.
I could use some manual alternative instead, though. My moving objects are stored in some kind of spatial hash grid, so I could find the closest objects to my player and each object has an oriented bounding box that I could use to calculate possible future overlaps in relation to their velocities.
However, I am wondering, if there is a better alternative. The best thing I can imagine is to provide the objects that are close to the player with “fake” colliders that are identical to the colliders of the physical objects they can be replaced with but the actual replacement with a rigidbody version only happens when the “fake” colliders register a collision. The solving phase of the physics engine would then have to treat the collisions as collisions between dynamic objects instead of as collisions between a static object and a dynamic object (the player).
However, I’m beginning to fear that this is not possible in Unity.
You seem to want Rigidbodies and Colliders but are not using them so I have to ask, why? Note that you can turn-off collisions on any Rigidbody using Unity - Scripting API: Rigidbody.detectCollisions
You say you’re not using MonoBehaviours so are you saying none of the traffic are GameObjects but just rendered instances with some large dataset behind it?
If you already have a broadphase (spatial hash) that can detect potentially overlapping pairs but you don’t have a narrowphase to detect the actual collisions then, as long as you don’t have too many of these, you could create a dedicated UnityScene with its own LocalPhysics world. In that you can have two proxy GameObjects (and appropriate physics components each representing the vehicles) either created as/when you need to check or they exist there and you simply position them for each check. You can then run PhysicsScene.Simulate on it to detect/solve the collisions. You can then read the poses and transfer them back to the main scene Transform poses.
Alternately do the above but instead, just add them to the main scene and just manually simulate them as/when you need.
Because I have more than 1000 objects moving on spline based lanes. Their movement logic is quite simple and the corresponding algorithm will guarantee that they won’t collide with each other, so rigidbodies and colliders for them would be a huge and unnecessary overhead.
Yes, I am using Instanced Geometry to render them and the StructuredBuffer containing all of their transformation matrices is constructed out of a list of instances of a VehicleUnit class which more or less just stores a position and a rotation.
I actually already took a look into DOTS but decided against it for now as I would have to relearn a lot, e.g. how is serializing done with the ECS. Performancewise I don’t seem to need it yet either as I have about 200 frames per second. Of course that might change but then I am willing to switch. Last but not least, I am still trying to make my algorithms work properly on a single core so multi-core solutions have to wait for now.
It looks as if I found a way to do what I was looking for (the one in the middle):
It got more sophisticated than I anticipated though. My solution runs Unity’s physics simulation manually. However, before simulating a physics step in my main scene that contains real physical objects and non-physical ones, I simulate the step in a separate LocalPhysics scene (as suggested by MelvMay) that contains only physical objects, i.e. non-physical objects of the main scene have physical counterparts in the LocalPhysics scene. If a collision occurs in the LocalPhysics scene I replace the related non-physical objects in the main scene with physical objects (also in the main scene).
Note: The “Ground Truth” in the video represents a real collision between two physical vehicles without tricks.
private void FixedUpdate()
{
RunCollisionPrediction(Time.fixedDeltaTime); // simulate in LocalPhysics scene
Physics.Simulate(Time.fixedDeltaTime); // simulate in main scene
}