Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How to make an object to follow other object which is following another?...

Discussion in 'Scripting' started by strongbox3d, Feb 20, 2018.

  1. strongbox3d

    strongbox3d

    Joined:
    May 8, 2012
    Posts:
    860
    Hello guys,

    I hope someone is able to help me with this:

    I have 3 object: Obj1, Obj2, Obj3.

    Obj1 is moving in Update Method, Obj2 follows Obj1 in LateUpdate Method(for achieving smooth follow).

    Obj3 has to follow Obj2, but Obj3 is always behind in time, since Obj2 is moving in LateUpdate already.

    How one goes about achieving a smooth follow in this situation? So to avoid Obj3 to fall behind Obj2.

    I have tried moving the "Follow" Method of the Obj2 to the Update Method, but then Obj3 in LateUpdate follows smoothly Obj2, but Obj2 falls behind and has a jerky movement following Obj1.

    Any help is very much appreciated

    Regards,
    Carlos
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,513
    Don't use LateUpdate to order one object to another object. Since you inherently only get 2 states from this.

    You need to use an update queue where each object updates in a precedence order you define.

    Or, you buffer your update. Instead of updating your position immediately which creates staggering issue. Instead update stored/buffered position variable that is updated after you know everyone has calculated there stuff:

    Code (csharp):
    1.  
    2. public class LeaderScript : MonoBehaviour
    3. {
    4.  
    5.     Vector3 _nextPos;
    6.  
    7.     void Update()
    8.     {
    9.         _nextPos = //do motion
    10.     }
    11.  
    12.     void LateUpdate()
    13.     {
    14.         this.transform.position = _nextPos;
    15.     }
    16.  
    17. }
    18.  
    19. public class FollowScript : MonoBehaviour
    20. {
    21.  
    22.     [Tooltip("The Target we want to follow.")]
    23.     public Transform Target;
    24.  
    25.     private Vector3 _nextPos;
    26.  
    27.     void Update()
    28.     {
    29.         var targPos = Target.position;
    30.         _nextPos = CalculateNextPos(targPos);
    31.     }
    32.  
    33.     void LateUpdate()
    34.     {
    35.         this.transform.position = _nextPos;
    36.     }
    37.  
    38.     private Vector3 CalculateNextPos(Vector3 targPos)
    39.     {
    40.         //return the position we should be at to 'follow' the target
    41.     }
    42.  
    43. }
    44.  
    Note, that because position isn't set until LateUpdate all FollowScript's will base it's motion off of the position before it's been updated (you could use other updates than Late, it just has to happen AFTER all Update calls... LateUpdate being the easiest for this demonstration).

    So basically as long as every one in the 'follow chain' (obj1, obj2, obj3... objN) all calculate their next position in Update, but update their position in LateUpdate. They're never calculating off the 'next' position of who they follow (which is staggered), but off the last position (which was calculated last frame so therefore clean and ordered).
     
    Last edited: Feb 20, 2018
  3. strongbox3d

    strongbox3d

    Joined:
    May 8, 2012
    Posts:
    860
    Thank you so much lordofduct! Great explanation, that just helps me a lot! I appreciate your prompt and accurated response.

    Regards,
    Carlos
     
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,513
    Note, you can flip this buffer around as well.

    I would actually suggest doing it this way. Because if you flip the order, it means that your LeaderScript doesn't have to also buffer. It can just act like usual. The only one that should really be buffering is the FollowScript. You know... less overhead that way:

    Code (csharp):
    1.  
    2. public class LeaderScript : MonoBehaviour
    3. {
    4.    
    5.     void Update()
    6.     {
    7.         this.transform.position = //do normal motion
    8.     }
    9.    
    10. }
    11.  
    12. public class FollowScript : MonoBehaviour
    13. {
    14.    
    15.     [Tooltip("The Target we want to follow.")]
    16.     public Transform Target;
    17.    
    18.     private Vector3 _lastTargetPos;
    19.    
    20.     void Start()
    21.     {
    22.         _lastTargetPos = Target.position;
    23.     }
    24.    
    25.     void Update()
    26.     {
    27.         this.transform.position = CalculateNextPos(_lastTargetPos);
    28.     }
    29.    
    30.     void LateUpdate()
    31.     {
    32.         _lastTargetPos = Target.position;
    33.     }
    34.    
    35.     private Vector3 CalculateNextPos(Vector3 targPos)
    36.     {
    37.         //return the position we should be at to 'follow' the target
    38.     }
    39.  
    40. }