Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Resolved Non-physics object replacement based on proximity to physics object

Discussion in 'Physics' started by BrightBit, Feb 22, 2024.

  1. BrightBit

    BrightBit

    Joined:
    Jan 22, 2013
    Posts:
    270
    Hello everyone,

    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:



    Thank you in advance for your help!
     
  2. Duck_With_Grape

    Duck_With_Grape

    Joined:
    Sep 6, 2021
    Posts:
    30
    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.
     
  3. BrightBit

    BrightBit

    Joined:
    Jan 22, 2013
    Posts:
    270
    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. :|
     
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,589
    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 https://docs.unity3d.com/ScriptReference/Rigidbody-detectCollisions.html

    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?
     
  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,589
    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.
     
  6. BrightBit

    BrightBit

    Joined:
    Jan 22, 2013
    Posts:
    270
    Hi MelvMay,

    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<float4x4> 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.

    The result looks like this:



    Note: The vehicles currently still run into each other at intersections. I am working on that. :)

    That sounds very interesting. I did not know that. I will definitely take a deeper look into it. Thank you very much! :)
     
    Last edited: Feb 23, 2024
    MelvMay likes this.
  7. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,589
    If you want to do this at scale i.e. do a lot more multicore work then using DOTS 3D physics would be much better in this regard.
     
    BrightBit likes this.
  8. BrightBit

    BrightBit

    Joined:
    Jan 22, 2013
    Posts:
    270
    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. :)
     
    MelvMay likes this.
  9. bobadi

    bobadi

    Joined:
    Jan 3, 2019
    Posts:
    689
    you can try using mesh bounds. but then you'll need a list of meshfilters in the scene. without colliders probably there's nothing else you can use.

    but then I think simple position check would do, don't have to wait until it gets so close that they would collide.
     
    Last edited: Feb 24, 2024
  10. BrightBit

    BrightBit

    Joined:
    Jan 22, 2013
    Posts:
    270
    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.

    Code (CSharp):
    1. private void FixedUpdate()
    2. {
    3.     RunCollisionPrediction(Time.fixedDeltaTime); // simulate in LocalPhysics scene
    4.     Physics.Simulate(Time.fixedDeltaTime); // simulate in main scene
    5. }
    Thank you all for your help and feedback!
     
    Last edited: Feb 27, 2024