i am trying to lerp between 2 float values with a smooth start and a smooth end, i have tried mathf.lerp and smoothstep, smoothstep seems to start off faster and then go really slow at the end and mathf lerp also only seems to slow at the end and not gradually speed up at the start
You cannot use Time.deltaTime in a lerp.
You’re mixing units [frame/second] with something that is essentially just a unitless ratio (%).
You need to convert/rephrase your lerp into units that are bound to time and work with that.
The easiest way to achieve this would be to define what is the absolute time interval you’re working with.
Let’s say totalTime is 2 seconds.
Then you get your unitless ratio if you get your currentTime / totalTime, and synchronize some other value against this.
// public and settable from inspector
public float startScore = 0f;
public float endScore = 100f;
// settable from inspector
[SerializeField] [Range(0.001f, 5f)] float totalLerpTime = 2f;
[SerializeField] bool animate = false;
// private
float _currentTime = 0f;
void Update() {
if(animate) {
float ratio = Mathf.Min(1f, _currentTime / totalLerpTime);
score = Mathf.SmoothStep(startScore, endScore, ratio);
Debug.Log(score);
animate = ratio < 1f;
if(animate) _currentTime += Time.deltaTime;
}
}
// usable from inspector
public void Reset() {
_currentTime = 0f;
animate = false;
}
// usable from code
public void Run(float time) {
Reset();
totalLerpTime = time;
animate = true;
}
void Update() {
if(animate) { // process the passage of time
// compute the ratio
var ratio = _currentTime / totalLerpTime;
// check the ratio (we don't want to overshoot 100%)
if(ratio > 1f) ratio = 1f;
// actual job (syncing and interpolating the other value)
score = Mathf.SmoothStep(startScore, endScore, ratio);
Debug.Log(score);
// getting ready for the next step
if(ratio < 1f) { // we're not there yet
_currentTime += Time.deltaTime;
} else { // we're there
animate = false;
}
}
}
i am using the orionsyndrome script but there still dont seem to be much smoothing at start and end, it only seems to start to slowdon when the score reaches 99 can it be made to gradually speed upto about a quarter then slow down in the last quarter
In general, animation tweening is a large topic, I could also give you many functions to customize this behavior to your heart’s content, but this would (probably) only confuse you, and it all boils down to only two things anyway, using AnimationCurve to manually draw the desired slowdowns and speedups, or getting a fully-featured tweening library as recommended before by mgear and Alvarezmd90
Also depending how many of these you wish to run at the same time, I’d propose setting enabled to false, instead of using animate variable. This is a better way of ensuring Update won’t be called at all, if it’s not needed.
I.e.
public class MyTweeningTest : MonoBehaviour {
public float startScore = 0f;
public float endScore = 100f;
// private but inspectable
[SerializeField] AnimationCurve curve;
[SerializeField] [Range(0.001f, 5f)] float totalTime = 2f;
// private
float _time = 0f;
void Awake() {
Reset();
}
void Update() {
float ratio = Mathf.Min(1f, _time / totalTime);
float score = Mathf.Lerp(startScore, endScore, curve.Evaluate(ratio));
Debug.Log(score);
enabled = ratio < 1f;
if(enabled) _time += Time.deltaTime;
}
// usable from inspector
public void Reset() {
_time = 0f;
enabled = false;
}
// usable from code
public void RunFor(float time) {
Reset();
totalTime = time;
enabled = true;
}
public void RunAtSpeed(float speed) {
RunFor(Mathf.Abs(endScore - startScore) / speed);
}
}
I have a small problem now, i have the following code that when run in update is fine but i will need to use it in a function so i need a while loop, but it is making unity freeze, can anyone show me the right way to use the while loop with the code i have below, thank you
The ‘return’… is it inside the while loop? It doesn’t seem to be the case as far as I can tell.
You ALWAYS require to break out of a loop, otherwise crashes will occur 100%.
Ah you basically switched Update into your own function. Well, you can’t do that.
You see, Unity will internally call Update each frame, and this is how that script of mine works. You can’t do that with your own functions.
Well you can, but you’d still end up calling them from within Update, it’s the main thing that gets called from the underlying Unity engine, and the only reliable way to update your game in sync with the engine itself.
The question is what about Update you find non-intuitive so that you have to call your own method ‘Runner’ from Start?