Search Unity

  1. We are migrating the Unity Forums to Unity Discussions by the end of July. Read our announcement for more information and let us know if you have any questions.
    Dismiss Notice
  2. Dismiss Notice

Bug Rigidbody not colliding if use gravity is turned off

Discussion in 'Physics' started by docFarto, Jul 28, 2023.

  1. docFarto

    docFarto

    Joined:
    Mar 28, 2022
    Posts:
    2
    So I am very confused by this, but when I turn off gravity OnCollisionEnter on my target object does not trigger.
    I have a very simple example script:
    Code (CSharp):
    1.     private void OnCollisionEnter(Collision collision)
    2.     {
    3.         Debug.Log("collided");
    4.     }
    The target has a sphere collider and a rigidbody

    In my game you shoot a bullet (that has a sphere collider on and no rigidbody) that has this code:
    Code (CSharp):
    1.     public void FixedUpdate() {
    2.             transform.Translate(transform.forward * Time.smoothDeltaTime * speed, Space.World);
    3.     }
    I have all the transforms frozen on the target object, I am only using the rigidbody to check for a collision via code.
    It works every time when Use Gravity is checked. But when I uncheck Use Gravity, it only triggers the collision every third time or so, I have tried changing the Collision detection to Dynamic or continuous Dynamic, but that doesn't change anything.
    I am looking in the scene view and they clearly collide, the speed of the bullet is also at 1 and very slow.
    I have tried with isKinematic checked and unchecked and to no avail.

    Does anyone have any ideas how Use Gravity might be affecting my collision detection? Any thoughts would be helpful.

    I have tried to attach a picture of what I am think should work, the colTest script is the first script I have posted in the thread.
     

    Attached Files:

  2. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    1,117
    Moving objects need to have a rigidbody on them and should be moved with physics functions like Rigidbody.AddForce. Enabling gravity makes your object more active and so it checks for collisions against static objects more frequently. But if you wait longer you may find that the bullet never triggers a collision at all because the rigidbody has gone to sleep and has stopped checking for collisions completely. Why check for collisions if nothing is moving?.

    To the physics engine transform.Translate doesn't register as moving.. transform.anything doesn't register as moving.
     
  3. docFarto

    docFarto

    Joined:
    Mar 28, 2022
    Posts:
    2
    Oh that makes sense, I never thought of that before, thank you
     
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,700
    A collider without a Rigidbody is Static (non-moving). This is all it means.

    You don't need a Rigidbody for collisions to happen at all. The actual reason is that Static do not contact other Static because why should they; they should never move. This is why it's often stated, simplistically, that you need a Rigidbody. Adding a Rigidbody makes it Dynamic. Dynamic contact Static. If your projectile were Static and your player was Dynamic then it would contact it because the player would contact the static projectile.

    It's all about the three body types:
    1. Dynamic
    2. Kinematic
    3. Static
    Here's the overview in the manual which details this: https://docs.unity3d.com/Manual/CollidersOverview.html
     
  5. leative

    leative

    Joined:
    Feb 5, 2024
    Posts:
    19
    I understand the differences in the types of colliders and their intended use. But what if I want to mix up kinematic (moved directly by tranform) and dynamic (moved by forces) objects and want both to collide with, let's say, the walls of my level. As they are not moving, the walls have to be static. So they possess no Rigidbody component. If I want the wall collider to detect my kinematic objects I need to make it a Trigger and call OnTriggerEnter on the kinematic objects. However, if I want my dynamic objects to bounce off the wall correctly, the walls may not be Triggers.

    How would you proceed in such a case? Deploy two collider components on the wall?
     
  6. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    1,117
    That'll work. But if you also want the dynamic objects to be detected by the trigger then be sure to make the trigger collider a little bigger or the other wall collider may deflect a fast moving or small dynamic object before it manages to intersect and register with the trigger collider.
     
    leative likes this.
  7. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    8,417
    Kinematic rigidbodies should still be moved via the Rigidbody API, just using MovePosition/Rotation instead, and will still respect collisions.
     
  8. leative

    leative

    Joined:
    Feb 5, 2024
    Posts:
    19
    Fair point, however, the wording of the manual leaves the impression that you could also work with, for example, Transform.Translation:
    Is there still a benefit of using MovePosition if you know the object should not partake in physics at all? The API just mentions that MovePosition applys interpolation. Which should not be relevant at all when a non-physics object is moved by using Update(). I often read that interpolation will allow more accurate collision detection but I get the feeling that this is a widely spread misconception. In my understanding, it is merely a cosmetic gimmick lowering jitter (which should not be an issue if we are not using physics for movement in the first place) but has nothing to do with the "interpolation" performed by the various collision detection algorithms.

    At this point, let me mention my intial setup which brought me here, as it also answers more directly the OP's question:
    I implemented a static (sort of) character object and walls as dynamic rigidbodies. My reasoning was that I didn't want the character to partake in physics but merely capture the collisions provided by OnCollisionEnter. Using Transform.Translate in the Update() of the character, the collisions work flawless even for high velocities of 300 units/s if I either manually WakeUp() the rigidbody of the wall or enable gravity on it. So, regarding collisions, the problem is not the way of moving the object but the ability of rigidbodies to deactivate their physics calculation if there is no movement. Apparently, activating gravity even wakes up rigidbodies for which position and rotation are frozen.

    All in all, after reading a lot of documentation and forum threads on that topic, it is still confusing. People often seem to follow best practices they heard of without really understanding the why. I wish I could...

    Disclaimer: I just started to learn Unity a few weeks ago. Feel free to challenge the above considerations.
     
  9. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,700
    Here's your problem. You are defining "physics" as meaning something that has a collision response or moves via its own velocity which is wrong. Physics is when you use anything from the physics engine. In the manual (etc), take "Physics" to mean the physics engine.

    When you change the Transform, NOTHING in the physics engine is updated until the simulation runs. Test it yourself, change the Transform and look at the Rigidbody.position.

    I'm not going to write any more about this synchronisation because it's been written about to death on these forums but you should understand that changing a Transform ONLY changes a transform. Systems only know about this change when they run.

    The physics system doesn't run per-frame by default (it runs at a fixed-step for stability independent of frame-rate) so interpolation is to smooth out movement between those lower-frequency simulation steps into the variable frame-rate for rendering purposes only. The Rigidbody(2D) is the authority on the position/rotation and writes to the Transform. It should not have to be reading from the Transform but devs do it regardless, often from misunderstanding. Interpolation runs per-frame and writes to the Transform from the previous Rigidbody position/rotation to the current Rigidbody position/rotation i.e. it's a historic movement. If you read from the Transform, this isn't the actual position of the Rigidbody, it's cosmetic smooth movement and you'll get a position/rotation somewhere between the old pose and the current one i.e. it'll be wrong. You should always reference the Rigidbody pose.

    In the opposing way that interpolation is historic, extrapolation is future movement prediction.

    The only way to match the Rigidbody pose to be the same as the Transform pose is to run the simulation per-frame OR directly modify the Rigidbody position/rotation which isn't recommended.

    In all cases of movement, you should be using the Rigidbody API. We see this all the time, deciding when to use the Transform and getting confused over when it should be used. The rule is clear, use the Rigidbody API i.e. MovePosition/MoveRotation for Kinematic and forces/velocity for Dynamic. Anything else is made to work because we have to but it is not how it's meant to work and comes with problems including no interpolation, tunnelling (in some cases) etc.

    If you just want to teleport things from position to position then go ahead but then you have to live with the fact that this isn't how the physics engine wants to work so you'll get what you get from it.

    NOTE: I will add that you should've created your own post rather than hijacking this thread.
     
  10. leative

    leative

    Joined:
    Feb 5, 2024
    Posts:
    19
    Maybe I should have worded it objects with non-physics-based movement but apart from that I am aware of the different time-steps used by frame updates and physics updates and at least roughly understand the synchronization. I think my point was, that even if an object is part of the physics engine (in the sense of containing a rigidbody), movement could also be done on the transform which is not part of the physics engine. However,...

    ...this put a different light on the situation. Although it's completely logical, I wasn't aware of that fact. I thought transform and rigidbody would reference the same position and the physics calculation would sort of magically happen on some other coordinates. Thanks for this very fundamental clarification!

    Sorry, I didn't intend to. Part of my post is an answer to the original question and part of it a response to a comment. Somehow hard to factor that out into a separate question without losing context.
     
    MelvMay likes this.