Is there a way to move objects smoothly without using Update function?

I have button script which contains event, and this event is triggered when a player steps on it. The door-opening function is subscribed to this event. I want the door to open smoothly after the event is triggered. If this function is placed in Update it opens smoothly, but from a function i could either open it a little, or teleport it immediatly to target position, both of which are not great. I don’t want to use Update for this, because the door is needed to open only once, and after that Update will do operations which are no longer needed. So I’m interested whether it possible and how to implement this smooth opening using only events.

Here is button script:

[SerializeField]
private SpriteRenderer spriteRenderer;
[SerializeField]
private Sprite pressedSprite;
[SerializeField]
private DoorMove door_move;
public delegate void OnButtonPressed();
public event OnButtonPressed On_button_pressed;
private  bool wasTriggered=false;
// Start is called before the first frame update
void Start()
{
    On_button_pressed += door_move.MoveDoor;
}

private void OnTriggerEnter2D(Collider2D collision)
{
    if (collision.gameObject.CompareTag("Player") && wasTriggered==false)
    {
        spriteRenderer.sprite = pressedSprite;
        On_button_pressed();
        wasTriggered=true;
    }
}

And the door script:

[SerializeField]
private int MoveY = 2, MoveX = 0;
Vector2 TarPos;
[Range(1f, 8f)]
public int step = 1;

void Start()
{
    TarPos = new Vector2(transform.position.x + MoveX, transform.position.y + MoveY);
}

public void MoveDoor()
{
    if ((Vector2)transform.position != TarPos)
    {
        Vector3 SmoothPos = Vector3.MoveTowards(transform.position, TarPos, step * Time.fixedDeltaTime);
        transform.position = SmoothPos;
    }
}

Any advice would be appreciated

Either use a coroutine, or just disable the component when the door doesn’t need to move so Update doesn’t run.

You should also consider NOT hand-coding it but rather be using a simple animation to open doors. There’s plenty of tutorials to show this.

Just use animations, this is what they are intended for.

Otherwise, this works for any continuous smooth movement:

Smoothing movement between any two particular values:

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: SmoothMovement.cs · GitHub

Another approach would be to use a tweening package such as LeanTween, DOTween or iTween.

OR… again, just make a simple canned animation… No code needed!

I looked up what is a coroutine and changed the code a bit.

Changes in button script:

 [SerializeField]
private DoorMove[] door_move;  // Made it an array

void Start()
{
    for (int i = 0; i < door_move.Length; i++)
    {
        On_button_pressed += door_move[i].StartOpeningDoor;
        // So it could open multiple doors at once.
    }  
}

Changes in Door script:

IEnumerator MoveDoor()
{
    while (true)
    {
        if ((Vector2)transform.position != TarPos)
        {
            Vector3 SmoothPos = Vector3.MoveTowards(transform.position, TarPos, step * Time.fixedDeltaTime);
            transform.position = SmoothPos;
        }
        else
        {
            yield break;
        }
        yield return null;
    }
}
public void StartOpeningDoor()
{
    StartCoroutine("MoveDoor");
}

Here how it looks:
9409004--1317449--door gif.gif

As you can see I plan to use this “door” not only as a door but also as some kind of retractable platform. The coroutine solution works perfectly, so thanks for advice!

Do you mean that I should make an animation, where the door gradually appears(or disappears) and then disable(or enable) the collider of it?

Just be careful because the “animator” is a performance black hole for simple animations if you start using it all over the place, and “legacy animation” has issues Unity refuses to fix because it’s legacy.

If you only need a handful at a time though, it’s fine.

It sounds like perhaps you haven’t done any animations yet? They’re really powerful, save you a metric buttload of ugly code, especially ugly coroutine code. You could slide the door, fade the door, explode the door, make the door turn into a wisp of smoke, etc.

Coroutines are fine but in my opinion, coroutines are NOT suitable for doors. The reason is that if your game design ever allows a close to occur before the open is finished, you will start two coroutines that will fight each other. It might end up okay, or not, or only sometimes fail.

If you have it working, move ahead I suppose, but I would not recommend that solution. I stand by my recommendations in my first post above. There’s a reason I post that.

Coroutines in a nutshell:

https://discussions.unity.com/t/825667/6

https://discussions.unity.com/t/749264/9

Splitting up larger tasks in coroutines:

https://discussions.unity.com/t/840656/2

Coroutines are NOT always an appropriate solution: know when to use them!

“Why not simply stop having so many coroutines ffs.” - orionsyndrome on Unity3D forums

https://discussions.unity.com/t/857304/4

https://discussions.unity.com/t/849607/7

Our very own Bunny83 has also provided a Coroutine Crash Course:

https://discussions.unity.com/t/coroutines-ienumerator-not-working-as-expected/237287/3

Yeah, that was my thought too when I saw this thread, but PrimeTween since it’s faster and doesn’t allocate.

https://assetstore.unity.com/packages/tools/animation/primetween-high-performance-animations-and-sequences-252960
https://github.com/KyryloKuzyk/PrimeTween/discussions/10