0
\$\begingroup\$
public void LetsGO()
{
    elapsedTime += Time.deltaTime;
    float percentageComplete = elapsedTime / desiredTime;

    transform.position = Vector3.Lerp(startPos, MoveHere, Mathf.SmoothStep(0,1, percentageComplete));
}

This works when I put in Update. But the thing is, I want this object to move the moment a specific action has been triggered. But it literally moves only one frame each time a specific action has been initiated from TriggerEnter2D. Is there a way to make it perform the full movement after it's been triggered?

This is the action that's been called via Unity Event.

public void ChangeArena(int ChangedTime)
{
    DangerTouched += ChangedTime;
    if (DangerTouched > 3)
    {
        NewPlatform?.Invoke();
    }
}

private void OnCollisionEnter2D(Collision2D collision)
{
    if (collision.gameObject.tag == "First")
    {
        AddScore(1);
    }

    if (collision.gameObject.tag == "DangerFirst")
    {
        ChangeArena(1);
    }
}
\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

I am not a fan of coroutines, because they make it hard to reason what actually goes on in the code. I prefer to use a pattern like this:

public class MoveOnTrigger : MonoBehaviour {
     
     private bool isGoing;
     private float elapsedTime;
     public float desiredTime;

     void Update() {
           if (isGoing) {
               elapsedTime += Time.deltaTime;
               float percentageComplete = elapsedTime / desiredTime;
               transform.position = Vector3.Lerp(startPos, MoveHere, Mathf.SmoothStep(0,1, percentageComplete));

               if (percentageComplete >= 1.0f) {
                   isGoing = false;
               }
           }

     }

     public void LetsGo() {
          elapsedTime = 0f;
          isGoing = true;
     }
}

The gist is that you do your movement in Update, but have a bool variable (isGoing in this case) which prevents that code from running. When the triggering event happens, you set that variable to true, and the movement begins.

Also note that this code allows you to repeat the action from the beginning by calling LetsGo() again. This is achieved by resetting elapsedTime back to 0.

\$\endgroup\$
2
  • \$\begingroup\$ thank you! it worked! but im curious, why if(percentageComplete >= 1f) ? sorry I don't get this part. \$\endgroup\$ Jun 27 at 5:04
  • \$\begingroup\$ @ShihsShihis This sets the flag isGoing back to false when the move is finished. So the code doesn't keep executing pointlessly. \$\endgroup\$
    – Philipp
    Jun 27 at 7:23
1
\$\begingroup\$

Sounds like what you are looking for is Coroutines. Basically, you would write whatever code you want to execute in a function that returns IEnumerator, like this:

public IEnumerator LetsGO()
{
    elapsedTime = 0;
    float percentageComplete = elapsedTime / desiredTime;
    while(percentageComplete<1){
        transform.position = Vector3.Lerp(startPos, MoveHere, Mathf.SmoothStep(0,1, percentageComplete));
        elapsedTime += Time.deltaTime;
        yield return null;
    }
}

and then call this from wherever you want (in this case, I guess that would be the OnCollision callback). An important thing to note is that to start the coroutine you do not just do LetsGo(), but instead StartCoroutine(LetsGo()). There is a bit more to coroutines, and they are a very handy tool, so I would recoment giving the manual page I linked a read.

\$\endgroup\$
1
  • \$\begingroup\$ sorry i cant use Coroutine because it wont accept in UnityEvent :( ty btw so much \$\endgroup\$ Jun 27 at 3:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .