Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Rigidbody.MovePosition and Rigidbody.MoveRotation seem to be conflicting

Discussion in 'Scripting' started by DCTShinobi, Jun 29, 2023.

  1. DCTShinobi

    DCTShinobi

    Joined:
    Jun 23, 2014
    Posts:
    51
    I'm trying to script movement of starfighters, and I'm wanting to keep tight control over how they move, so I'm using MovePosition and MoveRotation with a rigidbody instead of AddForce and AddTorque.

    I've created a very basic simulation of momentum/drift using MovePosition, and it seems to be working well for my purposes. I tested it by manually changing the transform's rotation values in the inspector (and also transform.Rotate for immediate changes of direction). It all worked.

    But then I started adding controls to rotate the ship by using Rigidbody.MoveRotation. And it works... when the ship is stationary. The ship will rotate in place. But as soon as the ship moves, it stops rotation. It's as though Rigidbody.MovePosition overrides the MoveRotation.

    After minimizing the code to just the movement and rotation, I believe I found the culprit. For the MovePosition, I'm basing it on transform.position (my momentum/drift simulation depends on it).


    Code (CSharp):
    1.         Vector3 currentVector = transform.forward * 1 * Time.fixedDeltaTime;
    2.         rb.MovePosition(transform.position += currentVector);
    So when I added the MoveRotion functionality, it would not rotate when the ship was moving, but it would rotate when the ship was stopped. It didn't matter if I based it on the rigidbody's rotation or the transform's. However, I found that the rotation would work fine when the ship was moving if I based MovePosition on rigidbody.position.

    Code (CSharp):
    1.         Vector3 currentVector = transform.forward * 1 * Time.fixedDeltaTime;
    2.         rb.MovePosition(rb.position += currentVector);
    So here is the basic code I have:

    Code (CSharp):
    1.     void FixedUpdate()
    2.     {
    3.         // Doesn't matter which order
    4.         RotateShip();
    5.         MoveShip();
    6.     }
    7.  
    8.     void RotateShip()
    9.     {
    10.         Quaternion rotationAmount = Quaternion.Euler(Vector3.up);
    11.         rb.MoveRotation(rb.rotation * rotationAmount);
    12.     }
    13.  
    14.     void MoveShip()
    15.     {
    16.         Vector3 currentVector = transform.forward * 1 * Time.fixedDeltaTime;
    17.  
    18.         // Works
    19.         rb.MovePosition(rb.position += currentVector);
    20.  
    21.         // Does not work
    22.         rb.MovePosition(transform.position += currentVector);
    23.     }
    I'm curious to know whether it is best to move/rotate based on the transform's position/rotation or the rigidbody's position/rotation. Does it really matter? If so, why? Do I need to rewrite my momentum/drift code so that it will work based on the rigidbody's position instead of the transform's?

    Thank you! :)
     
  2. Adrian

    Adrian

    Joined:
    Apr 5, 2008
    Posts:
    1,051
    Rigidbody.position
    is more update-to-date than
    Transform.position
    , since the latter is only updated after the next physics update.

    I'm not sure what exactly is happening in your case but it appears the MovePosition and MoveRotation are interfering with each other. Accessing
    Rigidbody.position
    in-between the two could force some internal state to be updated and make it work. Note that from 2022.1 there's Rigidbody.Move, which is intended for when you want to both move and rotate at the same time.

    But those methods are really only for interpolation. Using them, like setting
    Transform.position
    directly, effectively overrides the physics and collisions / interactions with other rigidbodies can become unrealistic / not work properly. If you want to use these methods, you should set the rigidbody to kinematic. If you want something to properly interact with other rigidbodies and colliders, AddForce/AddTorque are the way to go.
     
  3. DCTShinobi

    DCTShinobi

    Joined:
    Jun 23, 2014
    Posts:
    51
    Ah, thank you, I didn't know about Rigidbody.Move. I was able to alter my script to get things working, but I may just use it instead. And yes, I'll have to try to find a way to get the physics interactions to work acceptably with this method... because I really don't know how to maintain exact control over desired speeds with AddForce. I'm going for a control scheme similar to the old X-Wing and TIE Fighter games, so I don't really want too realistic of physics forces to control the ships. I only really care about collisions.

    Thank you again! :-D