Search Unity

Question Continuous movement script not working

Discussion in 'Scripting' started by tysongrunter, Mar 29, 2023.

  1. tysongrunter

    tysongrunter

    Joined:
    Mar 25, 2023
    Posts:
    19
    Okay, I have set up a script that allows an object to move between two positions and rotations, from point A to point B, and from point B to point A. I am using an event to trigger that, but for some reason, it's not working. Here's my code:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class ChangeTransforms : MonoBehaviour
    6. {
    7.     //holds the object's starting position
    8.     [SerializeField]
    9.     private Transform sPos;
    10.     //holds the object's finishing position
    11.     [SerializeField]
    12.     private Transform fPos;
    13.     //holds the object's move speed
    14.     [SerializeField]
    15.     private float speed;
    16.     //holds the object's rotation speed
    17.     [SerializeField]
    18.     private float rotationSpeed;
    19.  
    20.     //sets the position and rotation to the start upon starting
    21.     private void Awake()
    22.     {
    23.         this.transform.SetPositionAndRotation(sPos.position, sPos.rotation);
    24.     }
    25.  
    26.     //goes from starting position to finishing position
    27.     public void GoToFinish()
    28.     {
    29.         var step = speed * Time.deltaTime;
    30.         var rotStep = rotationSpeed * Time.deltaTime;
    31.         this.transform.position = Vector3.MoveTowards(this.transform.position, fPos.position, step);
    32.         this.transform.rotation = Quaternion.RotateTowards(this.transform.rotation, fPos.rotation, rotStep);
    33.         //checks if the position of the object and its destination are approximately equal
    34.         if(Vector3.Distance(this.transform.position, fPos.position) < 0.001f)
    35.         {
    36.             this.transform.position = fPos.position;
    37.         }
    38.     }
    39.  
    40.     //goes from finishing position to starting position
    41.     public void GoToStart()
    42.     {
    43.         var step = speed * Time.deltaTime;
    44.         var rotStep = rotationSpeed * Time.deltaTime;
    45.         this.transform.position = Vector3.MoveTowards(this.transform.position, sPos.position, step);
    46.         this.transform.rotation = Quaternion.RotateTowards(this.transform.rotation, sPos.rotation, rotStep);
    47.         //checks if the position of the object and its destination are approximately equal
    48.         if (Vector3.Distance(this.transform.position, sPos.position) < 0.001f)
    49.         {
    50.             this.transform.position = sPos.position;
    51.         }
    52.     }
    53. }
    What am I doing wrong here? What would I need to change?
     
  2. AndyBarnard

    AndyBarnard

    Unity Technologies

    Joined:
    Nov 12, 2019
    Posts:
    14
    The approach you have written in your GoToFinish and GoToStart methods will gradually move towards the target by no more than your step - this is what MoveTowards API does. So each time you call this method, it moves a little bit closer to the target. Therefore, you need to call this repeatedly each frame to move gradually each frame until you reach your target. I'm guessing somewhat from your description, but it's sounds possible that you could just be calling these methods once from your event trigger.

    A common approach would be to do this inside a MonoBehaviour's Update function, as the example in the documentation does. For example, you can place your interpolation code inside the MonoBehaviour's Update function, which is called every frame by Unity. An alternative could be to trigger a Coroutine that will repeatedly call this until it reaches the target. It depends exactly what your use-case is for which is best.

    If you take the Update approach, instead of explicitly interpolating towards the start or finish transform, you can simply interpolate towards a single target transform. Your event trigger can then just change the target transform to the 'start transform' or the 'finish transform' and your object will interpolate to it. A bonus of this approach is that if you interrupt your interpolation halfway through, it will naturally begin interpolating from its current position to the new target.

    Hope that helps!
     
    Bunny83 likes this.
  3. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,004
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    Why not just use a tweener package like DOTween or LeanTween?

    Otherwise, if you insist on doing it in code, you can do it a lot simpler like this:

    Smoothing movement between any two particular values:

    https://forum.unity.com/threads/beginner-need-help-with-smoothdamp.988959/#post-6430100

    You have currentQuantity and desiredQuantity.
    - only set desiredQuantity
    - the code always moves currentQuantity towards desiredQuantity
    - read currentQuantity for the smoothed value

    Works for floats, Vectors, Colors, Quaternions, anything continuous or lerp-able.

    The code: https://gist.github.com/kurtdekker/fb3c33ec6911a1d9bfcb23e9f62adac4