I created a project a while back where buttons in the UI of the app started programmed animations. I had a landscape model that I scaled in the Y axis to morph it from a 2D map into a 3D map and vise versa. I also blended between textures. I did this by triggering coroutines when a UI button was presses. But the problem was that each coroutine had to finish running before the opposite one could run. So when the player choose to morph the map into 3D and then clicked again to morph it back into 2D before the first morphing was complete I ran into problem. The first coroutine simply kept playing until it was finished, and then the other one kicked in, but that made a jump in time and everything became very jerky. I tried using StopSoroutine() but that didn’t work. In the end I worked around it by only showing the reverse-button after the coroutine had finished.

But that’s not what I want this time in my new project. I want all my lerps to be able to change direction at any time. So if the lerp has reached 75% (goring from 0.0 to 1.0) when a new button is pressed I simply want to update the lerp values so that it changes direction but uses the current value as start value, so it now goes from 0.75 down to 0.0 again.

Can this be done with coroutines, or is it better to just do it inside the Update method and control it with if statements and changing the values on the fly?

The reason I looked into coroutines was because I thought it would give better performance. If the lerp is in the Update method then Unity has to check every frame if the lerp is currently active or not. I’m not sure how expensive an if statement check is though? But morphing the landscape isn’t something that the player does very often, hence my idea was simply that rather then checking every frame if the lerp is running, simply off-load it to a separate coroutine and trigger that only when it’s needed.

Any advice on how to make this work and be performance gently for mobile devices? :slight_smile:

Cheers!

I wouldn’t use Coroutines for this. You can simply disable the component whenever the value isn’t changing.

Here’s some code, using a property that detects if the value changes, so that you only trigger the mechanics when it does change.

I’ve added a UI Text and a UI Slider for testing purposes.

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class LerpBackAndForth : MonoBehaviour
{
	public Text uiText;
	public Slider uiSlider;
	public float minValue;
	public float maxValue = 1f;
	public float speed = 1f;

	private float _lerpValue;
	private bool _forward;

	private float _value ;
	public float Value
	{
		get { return _value ; }
		set
		{
			if (value != _value)
			{
				_value = value ;
				// TODO : add your mechanics here
				uiText.text = _value.ToString();
				uiSlider.value = _value;
			}
		}
	}

	void Start ()
	{
		uiSlider.maxValue = maxValue;
		enabled = false; // component disabled upon start
	}
	
	void Update ()
	{
		_lerpValue += (_forward ? speed : -speed) * Time.deltaTime;
		Value = Mathf.Lerp(minValue, maxValue, _lerpValue);

		if (_lerpValue <= 0)
		{
			_lerpValue = 0;
			enabled = false;
		}
		else if (_lerpValue >=1)
		{
			_lerpValue = 1;
			enabled = false;
		}
	}

	public void Animate (bool forward = true)
	{
		_forward = forward;
		enabled = true;
	}

	public void Reverse ()
	{
		Animate (!_forward);
	}
}