Search Unity

Bug Kinematic objects not colliding

Discussion in 'Physics' started by zoreoo, Dec 27, 2023.

  1. zoreoo

    zoreoo

    Joined:
    Dec 23, 2023
    Posts:
    3
    Hi. I have a very simple game: a fish controlled by the position of the mouse cursor, and a shark that follows it. This part has been implemented using transform.LookAt(), transform.position, and transform.forward.

    Now I need some way to detect the collision of the shark and fish, but I don't want any other physics. So I made both of their rigidbodies kinematic. I have the project settings set to "enable all contact pairs" as well.

    However, collisions still aren't being detected.

    I find the manual quite vague and unhelpful in all of this, considering it makes it sound like kinematic objects are the right thing for what I need. Any help is greatly appreciated.
     
  2. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,438
    You can use Rigidbody in a kinematic sense, and have two kinematic Rigidbody objects detect each other, but you will need to move your objects using the Rigidbody.MovePosition/MoveRotation functions in FixedUpdate, instead of using the Transform.position/rotation properties directly. You already did set your physics to "All Contact Pairs" which is also necessary.

    In this diagram, you're trying to "Move by Transform" but you should switch to "Move by Kinematic Rigidbody."

    moving-objects.png
     
    Last edited: Dec 28, 2023
  3. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    Great diagram! However, I don't think the section "Move Rigidbody by Velocity" is correct. Modifying Rigidbody.velocity means overriding the results of the physics solver, so it may cause unexpected reactions in the Rigidbody, especially when dealing with collisions and external forces (i.e. gravity).

    The most consistent way of modifying the velocity of a Rigidbody is using AddForce with ForceMode.VelocityChange. You calculate your target velocity and apply it to the Rigidbody as the difference between the target and current velocity, like this:
    Code (CSharp):
    1. rb.AddForce(targetVelocity - rb.velocity, ForceMode.VelocityChange);
     
    halley likes this.
  4. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,438
    It absolutely does, you are correct. It's just a really common branch of the way people seem to do things, which works in constrained applications. I might make the ForceMode.VelocityChange a third lobe in the "Move Rigidbody by Forces" area, and add a Con note to the "Move Rigidbody by Velocity" area.
     
  5. zoreoo

    zoreoo

    Joined:
    Dec 23, 2023
    Posts:
    3
    Thanks so much for your reply. I will be saving a picture of that diagram.

    To be clear, does this mean I must use MoveRotation() instead of LookAt() in order to have consistent results? And can I still use transform.forward?
     
    Last edited: Dec 28, 2023
  6. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,899
    Yes, rotations need to done via the physics API as well.
     
    zoreoo likes this.
  7. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,438
    You can calculate the rotation with Quaternion.LookRotation(), then apply that rotation with Rigidbody.MoveRotation(). Or if you want to turn more slowly toward that, you can calculate the ideal rotation with Quaternion.LookRotation(), then calculate a step in the right direction with Quaternion.RotateTowards(), and apply the intermediate with Rigidbody.MoveRotation() each FixedUpdate().
     
    zoreoo and spiney199 like this.
  8. zoreoo

    zoreoo

    Joined:
    Dec 23, 2023
    Posts:
    3
    Thank you -- I got everything working.

    One last thing: The manual says, "If a Rigidbody is kinematic (that is, it receives no physics-based forces), you can apply any collider to it [no runtime error]." This was under a section on convex and concave collider geometry. I was originally using mesh colliders, but the collisions did not register if they were not convex. My question is: what, then, is the use of non-convex mesh colliders? This question is more educational than anything since I can just use capsule colliders with no issue.
     
  9. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,438
    Non-convex colliders can be hit by Raycast methods, but moving objects with Rigidbody will require convex colliders. Mesh terrains are a good example where you really need the support of non-convex colliders, and most kinematic style character controllers (including CharacterController's weird capsule quasi-collider) can easily find the ground or obstacles with raycasts.

    You can use multiple colliders to represent your object, including any combination of simple shapes and convex meshes, and all colliders on children objects are considered part of a single rigid assembly all forwarding their collisions or triggers to the Rigidbody in the root. For any assembly that is not rigid, as in has moving child parts, you can decompose them into separate peer parts and Rigidbody-to-Rigidbody relationships with Joints.
     
    zoreoo likes this.