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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question Why is Rigidbody.MovePosition not smooth?

Discussion in 'Physics' started by CatDadJynx, Jun 20, 2021.

  1. CatDadJynx

    CatDadJynx

    Joined:
    Apr 16, 2020
    Posts:
    249
    Hello, I have an object which follows my player around... using MoveTowards this works just fine, but I forgot since my object has a collider attached I need to add a rigidbody... however, when I try using Rigidbody.MovePosition, my companion object snaps in place. Ive tried turning on Interpolation but there is no difference. Anyone have any suggestions? Been trying to figure this out for over a month now. Thanks

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public class Hover4 : MonoBehaviour
    6. {
    7.     public GameObject companionAnchor;
    8.     private Rigidbody rb;
    9.  
    10.     void Start()
    11.     {
    12.         companionAnchor = GameObject.Find("companionAnchor");
    13.         rb = GetComponent<Rigidbody>();
    14.     }
    15.  
    16.     void FixedUpdate()
    17.     {
    18.         float dist = Vector3.Distance(transform.position, companionAnchor.transform.position);
    19.  
    20.         if (dist >= 3.0f)
    21.         {
    22.             rb.MovePosition(companionAnchor.transform.position);
    23.         }
    24.     }
    25. }
     
    Last edited: Jun 20, 2021
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,778
    Because you're only updating it when the distance is larger than 3 units away so it waits until that happens then moves to where it current is. MovePosition doesn't say move to that position slowly (note there isn't any speed arguments etc); it happens at once during the next simulation step.
     
    adamgolden likes this.
  3. CatDadJynx

    CatDadJynx

    Joined:
    Apr 16, 2020
    Posts:
    249
    Thats because im trying to add a slight delay so it lags behind a little bit before it starts moving. I thought it was supposed to move smoothly with interpolation enabled though (since the manual says this):

    "Rigidbody.MovePosition moves a Rigidbody and complies with the interpolation settings. When Rigidbody interpolation is enabled, Rigidbody.MovePosition creates a smooth transition between frames."

    I also didnt think MovePosition teleported since it says:

    "Teleporting a Rigidbody from one position to another uses Rigidbody.position instead of MovePosition."

    So how do i move it smoothly?
     
    Last edited: Jun 20, 2021
  4. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    The problem is your logic is saying "move using velocity to here" with MovePosition sometimes, not all the time. If you want it to move smoothly to the next position, code it so. Feed in a position that moves slower.

    rb.MovePosition(someSmoothedTarget);

    Note: this will still need interpolation enabled on the rigidbody if you're moving it every frame. The problem is you are not moving it every frame. So there is nothing to interpolate.

    Don't confuse interpolation on the rigidbody with "move smoothly anywhere at any speed" because it is designed to interpolate between fixed update steps which typically run less than your actual update steps.

    It is not a general-purpose magical lerp.

    the "Move" part of MovePosition means it is calculating the destination to INSTANTLY move to (with optional interpolation between a single frame). That optional interpolation will only visibly show if you're using MovePosition to a different position every FixedUpdate, which you are not.


    This is likely MovePosition's calculation for velocity, which it applies in one frame (because it calculates a single frame velocity, it is still moving inside the physics engine and will still collide along the way, unlike transform position changes):

    (end - start) / Time.fixedDeltaTime


    So just make a smoothdamped Vector3 or something that you feed in or calculate the velocity yourself, perhaps with a suitable clamp so it doesn't move instantly to the target in one frame.
     
    Sheertunic499 likes this.
  5. CatDadJynx

    CatDadJynx

    Joined:
    Apr 16, 2020
    Posts:
    249
    Oh alright, so you basically still need to do the interpolation yourself then. Thanks!
     
  6. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    It is not interpolation but regular movement, what you describe. MovePosition *will* interpolate. But as you are moving it directly to the destination, what did you expect?
     
  7. CatDadJynx

    CatDadJynx

    Joined:
    Apr 16, 2020
    Posts:
    249
    Oh alright, makes sense. I got it working just by doing something similar as my transform.position = MoveTowards code, I just subsituted transform.position with newPos = MoveTowards then put newPos inside rigibody.MovePosition. Like this:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public class Hover : MonoBehaviour
    6. {
    7.     public GameObject companionAnchor;
    8.  
    9.     public float moveSpeed;
    10.  
    11.     private Rigidbody rb;
    12.     private Vector3 newPos;
    13.  
    14.     void Start()
    15.     {
    16.         companionAnchor = GameObject.Find("companionAnchor");
    17.         rb = GetComponent<Rigidbody>();
    18.     }
    19.  
    20.     void FixedUpdate()
    21.     {
    22.         float dist = Vector3.Distance(companionAnchor.transform.position, transform.position);
    23.  
    24.         float tempSpeed = moveSpeed;
    25.  
    26.         if (dist >= 3.0f)  // vary this min distance if you like
    27.         {
    28.             // gives a linear bonus if the agent gets too far from its goal
    29.             tempSpeed += (dist - 3) * 9.0f;  // vary this function if you like
    30.         }
    31.  
    32.         if (dist >= 2.0f)
    33.         {
    34.             newPos = Vector3.MoveTowards(transform.position, companionAnchor.transform.position, tempSpeed * Time.deltaTime);
    35.             rb.MovePosition(newPos);
    36.         }
    37.     }
    38. }
     
    Darkforge317, hstoqnov and SimDevs like this.