Search Unity

MoveRotation and clipping on walls

Discussion in 'Physics' started by leandroeidi, Jul 31, 2020.

  1. leandroeidi

    leandroeidi

    Joined:
    Dec 22, 2017
    Posts:
    3
    Hello, everybody. I'd appreciate if somebody can shed a light in this problem.

    I'm creating a program where the user will be able to move and rotate a rectangular object by touch controls (dragging the white square planes, in the image).

    When just moving the object, everything works as intended. The collision is fine and the object doesn't get inside the walls.

    However, when rotating in a tight space, the object gets inside the walls. Can anyone explain how to fix this?
    When rotating in a wide space, when the object collides with a wall, it just slides a little away from the wall, as expected. So judging by this, and just moving (by changing RigidBody.velocity) also working, I'd guess I set the colliders correctly. Only tight spaces when rotating are the problem.

    Unity version: 2020.1.0f1
    2019.4.3f1 also has the problem.

    Code (CSharp):
    1. Rigidbody playerRigid = player.gameObject.GetComponent<Rigidbody>();
    2. Quaternion deltaRotation = Quaternion.Euler(new Vector3(0, angle, 0) * Time.deltaTime);
    3. playerRigid.MoveRotation(playerRigid.rotation * deltaRotation);
    I'm calling it inside
    void FixedUpdate()

    At first I did it with transform.rotation, and the problem already happened. Then I read that using RigidBody.MoveRotation should fix it, but it didn't. And now I don't know how to proceed...
     

    Attached Files:

  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,508
    MovePosition will forcefully move the body to the new position. At the same time the Physics engine will be trying to enforce the collisions. As both you and the physics engine are giving contradictory commands ("move" and "react to collisions") then the results will be highly unreliable. Most times your motion commands will override the reactions to collisions.

    The correct way of moving a rigidbody and reacting to collisions at the same time is using Rigidbody.AddForce exclusively. For example, if you want to impose a velocity you can apply a delta-velocity from the actual velocity:
    Code (CSharp):
    1. rigidbody.AddForce (wantedVelocity - rigidbody.velocity, ForceMode.VelocityChange);
    The above imposes a velocity (wantedVelocity) but allows the physics engine to react to collisions properly. For example, the rigidbody will stop against a blocking wall even if the AddForce command keeps trying to impose the velocity.
     
    rothpletz5 likes this.
  3. leandroeidi

    leandroeidi

    Joined:
    Dec 22, 2017
    Posts:
    3
    Thanks for the answer, but my problem is not with moving the object, but with rotating it.

    Maybe you're thinking that the problem is occurring when moving and rotating at the same time, but if I don't touch the "move square control" and only use the "rotate square control", only the rotating code is executed. And the problem happens.

    I tried using AddTorque, and AddRelativeTorque, but the problem persists. My test code is below.

    Code (CSharp):
    1. Rigidbody playerRigid = player.gameObject.GetComponent<Rigidbody>();
    2. Vector3 rotationTorque = new Vector3(0, 1f * Time.fixedDeltaTime, 0);
    3. playerRigid.AddTorque(rotationTorque, ForceMode.Acceleration);
    I tried with ForceMode.Acceleration and ForceMode.VelocityChange, both with problems, and couldn't make ForceMode.Force work for some reason.

    I hoped the physics system would be enough, but I'm losing hope. I think I'll start trying to make a more manual approach, detecting collision with the walls and depending on what walls and the coordinates of the collisions, stop the object from rotating clockwise or counterclockwise.
     
  4. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,508
    Addtorque is the proper way to go, that's for sure.

    Don't multiply the value by any delta time. Torques, accelerations and velocities are time-independent magnitudes in this context.

    I haven't tested, but I'd try an approach like this:
    Code (csharp):
    1. rigidbody.AddTorque (wantedAngularVelocity - rigidbody.angularVelocity, ForceMode.VelocityChange);
    Angular velocity is a Vector3 where each component is the velocity of rotation around each axis in rad/s.

    Also, I'd try setting the Collision Detection mode in the Rigidbody to Continuous Dynamic or Continuous Speculative.
     
  5. leandroeidi

    leandroeidi

    Joined:
    Dec 22, 2017
    Posts:
    3
    I think I found out the error.
    During my tests, I used the following command:
    Code (CSharp):
    1. player.gameObject.GetComponent<Rigidbody>().freezeRotation = true;
    And I forgot to delete it. WIthout it, AddTorque works as expected.

    Thanks for your answers!
     
    Edy likes this.