Easing functions that run in a update function ???
Ok so I am currently lerping my camera to the destination in order to get the smooth movement I want.
At the moment it starts out going fast and then slows down because thats how lerp works
{x+= (target-x) * 0.1f }
The problem is that I want to have the camera start out slow and move faster as the distance gets bigger and then slow down as it gets closer to the character.
Ive looked into easing functions (http://sol.gfxile.net/interpolation/) but they all seem to have a fixed start and end point and I cant figure out how to adapt the functions to work continuously within a update function like lerp does.
So does someone have any ideas ?
Thanks for your time.
*Edit* I should add that I am interested in using smoothstep.
At the moment it starts out going fast and then slows down because thats how lerp works
{x+= (target-x) * 0.1f }
The problem is that I want to have the camera start out slow and move faster as the distance gets bigger and then slow down as it gets closer to the character.
Ive looked into easing functions (http://sol.gfxile.net/interpolation/) but they all seem to have a fixed start and end point and I cant figure out how to adapt the functions to work continuously within a update function like lerp does.
So does someone have any ideas ?
Thanks for your time.
*Edit* I should add that I am interested in using smoothstep.
Comments
And then instead of just using that value to move the camera, Lerp a movement variable from zero (or whatever value) to that value (and then use the new, twice lerped, value to move the camera).
Depending on how you implement it, it might feel a bit wobbly. But it really depends on how much tweaking you do and what you use it for.
In any case, hope that helps.
Constant time is easy: Just lerp the end point for your tweening equation.
Constant speed is a bit harder. You need to work work with speed and acceleration. Smooth Damp kinda does this but is a bit fiddly to work so I tend to just roll my own. The hardest part is knowing how much to slow down by so that you don't overshoot the target. Without invoking Calculus, I'd probably blend between this acceleration and switch over to your lerp as you get closer to the target. This might wobble like evan said and would take some tweaking.
Edit: Didn't know about DOTween. Glad to see they've fixed lots of the stuff I didn't' like about HOTween.
It's basically just the standard tween math structured nicely. Fairly trivial to grab the source and rebuild for Unity.
Then you can draw your own easing function in the inspector.
@BlackShipsFilltheSky I am going to try this out and see what happens, thanks.
@SUGBOERIE I kinda tried this but I was unsure how it would work as both the characters and the camera is moving every frame. So how would I get a 0..1 range ?
I get static tweening which works in something like a for loop, but what I am struggling to wrap my head around is ways of doing "dynaming tweening" where the start point and the end point is constantly moving. Also most tweening functions seem to work with a time variable t that tells the function how far along the tween it is. But because the tweening functions start and end point is constantly changing the t variable is constantly being reset because its effectively a new curve.
I also tried some stuff with acceleration and velocity but I could not think of a way to prevent overshooting the target.
Thinking about it more Evans solution will probably be the best in terms of producing actual results easily, but it would be cool if I could learn a bit more about tweening and that sort of thing.
Personally, I'd keep track of the camera's normalised progress along the path as a separate variable between 0 and 1, which I'd increment each tick according to whatever acceleration curve I wanted (a (1+sin(x))/2 curve might be pretty good here, for example). I'd then recalculate the vector between the start and end points every frame, then calculate the camera's new position by using the new start point as a base, and adding the new inter-point vector multiplied by the progress variable. In pseudocode: newCameraPoint = startPointThisFrame + (startToEndVector * tweenProgress). As @BlackShipsFilltheSky says above, this would very likely result in some really weird motion, depending on how much the start and end points move during the interpolation, and you'll have to implement some sort of acceleration scaling when you increment tweenProgress to ensure that short distances are traversed faster than longer distances. You'll just have to feel it out and tweak as you go. :P
EDIT: This, of course, assumes a single predefined, uninterrupted movement between two points (for instance, once-off camera switches between two characters). If you're looking for some sort of continuously moving camera with variable acceleration (for instance, a tracking camera for one character in a platformer that lags when they start moving and decelerates when they stop) then things will have to be done quite a bit differently. It'll help to know the context of the camera behaviour.
*Edit* after testing it some more it doesn't exactly work like I wanted it too work because what happens is if the character telleports 100 x units forward and the camera is on 0 x the first lerp will take it a tenth of the way there on the first frame so thats a x of 10 then the second one will also take it a tenth of the way there which is 1. So on the 1st frame it moves one unit forward.
If the characters teleported say 500 units forward it would then move 5 units on the 1st frame. This is not what I had in mind. I would like it to start out smooth and accelerate and then decelerate.
IE
would be the same as
If someone knows a way to do smoothstep in a update loop it would be great. I also found this :https://chicounity3d.wordpress.com/2014/05/23/how-to-lerp-like-a-pro/ But its intended for a static end point and start point.
i.e. Instead of jumping position, we're actually lerping a velocity. And instead of the velocity jumping, we lerp an acceleration. At which point I believe it's about solving what the acceleration should be, which afaik is a spring damping problem for what the "ideal" damping is at any time for the spring to come comfortably to rest.
...which is something I last did 8 years ago and can't remember. :D
A velocity-based system would probably look a bit like the following pseudo-code:
Where you can mess with someFactor, acceleration and minimumVelocity to change how it works. Good starting values might be:
someFactor = 5
acceleration = 3 (?? Not sure about this, experiment with it)
minimumVelocity = 0.2
With those settings, if something is less than 5 times the distance it'd cover in the current frame from your target, it accelerates. If it's closer than that, it decelerates. You could make acceleration and deceleration relative to specific distances from the target and "smooth them out" that way, but that's left up to you... Also, this was written super-fast so it could very easily be full of derp.
You can easily "reset" the camera to move slowly by setting currentVelocity to 0 :)
@Gazza_N 's method started fast and then slowed down like a lerp (not sure if I did something wrong here ?)
After doing @dislekcia 's method it felt to weird to me. Like it feels too delayed. In my head the camera behaved differently than reality. Nothing wrong with the code but the start slow, speed up, slow down method isn't great for platformer camera's;
I am also disapointed that there is no easy way to use those easing functions in a dynamic way, but thinking about it more the acceleration/velocity way is better suited to moving end points.
I think I am going to settle on smoothdamp (http://docs.unity3d.com/ScriptReference/Mathf.SmoothDamp.html). Its what feels best to me.
Thanks again for the code and time.
I like to treat the time property as a normalized value , then have your start and end values be 0 and 1 respectively and your duration be 1.
The result been you plug in a percentage and get back an interpolated percentage. This can be used to feed the "t" of a Unity Lerp function or as a Scalar in some or other multiplication logic etc..
I have used this before on some camera coding where the "time value" was derived from a distance calculation.