Comments and answers for "Slow down in the same time over different distances"
http://answers.unity.com/questions/1255755/slow-down-in-the-same-time-over-different-distance.html
The latest comments and answers for the question "Slow down in the same time over different distances"Comment by Griffo
http://answers.unity.com/comments/1256605/view.html
@b1gry4n
I'have it working as I want it to now, so thanks again for your help, although I've used Unity for many of year there is always something new to learn ..
I've converted you comment to an answer and accepted it.Sat, 15 Oct 2016 07:20:18 GMTGriffoComment by b1gry4n on b1gry4n's comment
http://answers.unity.com/comments/1256463/view.html
Like I said earlier, If you want time to slow down/speed up, you will need to change speed. Distance is the constant here. You have a set distance at all times, so the speed of the bot needs to dynamically change based off the distance it is traveling if you want him to cover varying distances in the same amount of time. If you want him to reach the end of the path in the same amount of time regardless of the distance between them, a very far distance = higher speeds. A very short distance = lower speeds.
The reason the slowdown/speedup seems inconsistent is because the bot is traveling the same speed. It is actually very consistent, the bot appears to be slowing/speeding up much faster because it is traversing the path at a constant speed. make the distance short and slow the maxspeed, you will see it slows and speeds up.Fri, 14 Oct 2016 21:19:53 GMTb1gry4nComment by Griffo
http://answers.unity.com/comments/1256118/view.html
@b1gry4n Hi,
O$$anonymous$$ I'm liking the animation curve but I see a problem, I'm going with one like in your [LIN$$anonymous$$][1]
The problem as you can see in this [VIDEO][2] is the acceleration and deceleration is not constant when the distance is changed, is there a way to keep the ends constant no mater the length of the flightpath?
Or would I have to move the second and third points of the cure at runtime depending on the length of the flightpath?
Thanks.
[1]: http://i.imgur.com/2m6DuiH.jpg
[2]: https://www.youtube.com/watch?v=3bAB3PrTkuo&feature=youtu.beFri, 14 Oct 2016 08:00:46 GMTGriffoComment by Griffo
http://answers.unity.com/comments/1256067/view.html
@b1gry4n
Thank you very much for taking the time to explain all this in detail, I really do appreciate it.
Now thanks to you I have a better understanding of the power of using animation curves, that could just be what I'm looking for.
Thats my job for today, to nail this flightpath control, I'll keep you updated ..Fri, 14 Oct 2016 05:18:15 GMTGriffoComment by b1gry4n on b1gry4n's answer
http://answers.unity.com/comments/1255961/view.html
using UnityEngine;
using System.Collections;
public class Traverse : $$anonymous$$onoBehaviour {
public Transform target;
public AnimationCurve curve;
public float maxSpeed = 1;
public float currentSpeed;
public float totalDistance;
public float remainingDistance;
Vector3 originalStart;
void Start()
{
target.position = new Vector3(transform.position.x, transform.position.y, transform.position.z + 20);
originalStart = transform.position;
totalDistance = Vector3.Distance(transform.position, target.position);
curve = new AnimationCurve();
curve.Add$$anonymous$$ey(new $$anonymous$$eyframe(0.0f, 0.01f));
curve.Add$$anonymous$$ey(new $$anonymous$$eyframe(0.5f, 1f));
curve.Add$$anonymous$$ey(new $$anonymous$$eyframe(1.0f, 0.0f));
}
void Update()
{
remainingDistance = Vector3.Distance(transform.position, target.position);
if (remainingDistance <= 0.1f)
{
Reset();
return;
}
currentSpeed = curve.Evaluate(1.0f - (remainingDistance / totalDistance)) * maxSpeed;
transform.LookAt(target);
transform.Translate(Vector3.forward * currentSpeed);
}
void Reset()
{
transform.position = originalStart;
}
}
You can change the "maxspeed" value to whatever you want. This would simulate your bot changing speeds throughout its time on the bezier curve. No mater the maxspeed, it will start slow, speed up, and stop slow. Also, while in play mode, mess around with the animation curve itself and look at how it changes the objects speed as it traverses the "path"
If you wanted to get really fancy, you could add keys to a runtime generated animation curve (similar to what I have done in the example) for each node of your bezier curve. Say you have 20 nodes in your curve, you would add 20 keys. The key time would be the currentNode/totalNodes and the key value could be based on the distance between the nodes. If you did it this way, you could control the speed of the object at each node in the curve.Thu, 13 Oct 2016 21:50:24 GMTb1gry4nAnswer by b1gry4n
http://answers.unity.com/answers/1256604/view.html
*The code snippet above will give the inverse value. Below I modify it to make reading the curve easier.*
Say your total distance of the bezier is 20 units. as you traverse the curve, your position (or distance from the end) in the curve will start to get smaller. It will start at 20 and as you move closer to the end it will be 19, 18, 15, 10, 5, etc. The remaining distance is something you will need to continuously track as you traverse the curve.
For the sake of continuity and clearly reading the animation curve, lets do it like this:
remainingDistance / totalDistance = a value between 0.0 and 1.0.
20/20 = 1
15/20 = .75
10/20 = .5
So now, if we say:
1.0f - (remainingDistance / totalDistance)
we will get the inverse of what we just did. this isnt necessary but it makes reading the animation curve a little easier from left to right. Evaluating the curve with this value will return a modified value based on that curve.
If you were to create a curve like this: http://i.imgur.com/D5EjEck.jpg
you could evaluate the curve with:
animCurve.Evaluate(1.0f - (remainingDistance/totalDistance))
For purposes of explanation, lets say you were 3/4ths the way through your bezier curve. That means if the total distance was 20, your remaining distance would be 5.
1.0f - (5/20) = 0.75f
Now look at the image i linked. At the bottom follow the value over to 0.75, follow it up until it reaches the curve. The returned value will be about 0.62f. Now we take the received value and multiply it by our max speed.
animCurve.Evaluate(1.0f - (distanceRemaining/totalDistance)) * maxSpeed
If the max speed at that time is 100, that means at this point in the curve we are traveling at a top speed of 62. As you can see, as you evaluate along the curve, the fastest you would be moving throughout the entire distance is halfway at 0.5. You can adjust this curve to be how you want. Something like this is what you want I am guessing : http://i.imgur.com/2m6DuiH.jpg
This will automatically slow down and speed up depending on the point you are in the curve. The speed of the character would not matter as you could slow down/speed up and evaluate.
float finalSpeed = animCurve.Evaluate(1.0f - (remainingDistance/totalDistance)) * currentSpeed;
One thing to keep in mind is that if you set the beginning of the curve at a time of 0.0 and a value of 0.0, the returned value will be 0.0. Youll need to set the beginning of the curve to atleast 0.01 or do a check. if(returnedValue == 0) returnedValue = 0.01f
I have created a little demo script. I am creating the curve in the script, but you would want to hand tweak the curve to your desire.
SETUP: create 2 spheres. Place the script on one of the spheres and drag the other sphere into the "target" slot of the script. Press play. Notice how it starts slow, speeds up, and slows towards the end.Thu, 13 Oct 2016 21:36:37 GMTb1gry4nComment by Griffo
http://answers.unity.com/comments/1255871/view.html
@b1gry4n Animation curves never used them.
I'm a bit confused you say **divide the remaining distance by the max distance and you will get a value between 0.0 and 1.0** but in you code snippet you have ..
float speed = slowDownCurve.Evaluate(currentDistance/maxDistance) * initialSpeed
I've done the two ..
var floatSpeed_0 : float = slowDownCurve.Evaluate(currentDistance/flighpointsOverallDistance) * 6;
var floatSpeed_1 : float = slowDownCurve.Evaluate(flighpointsLeftDistance/flighpointsOverallDistance) * 6;
And below is the output ..
![alt text][1]
[1]: /storage/temp/80070-screen-shot-2016-10-13-at-173943.png
but I can't see how floatSpeed_0 or floatSpeed_1 would be used in a animation curve to decrease the speed!Thu, 13 Oct 2016 16:49:39 GMTGriffoComment by b1gry4n on b1gry4n's comment
http://answers.unity.com/comments/1255852/view.html
$$anonymous$$ore on the animation curve idea. You could control the start up and slow down with a single curve. Sample the current position in the entire path and evaluate the animation curve. Your curve would end up looking like a bell curve representing the speed of the bot over the course of the entire bezier curve
if youre able to get the last 5 nodes in a path, you surely are able to get a % traveled in the path. animCurve.Evaluate(currentNode/maxnodes)Thu, 13 Oct 2016 16:02:15 GMTb1gry4nComment by Griffo
http://answers.unity.com/comments/1255835/view.html
@b1gry4b thanks for all this information ..
First let me say that when the bot first flies along the path he slowly accelerates up from 0 up to a speed of 6 or 10 over a period of time (say 3 seconds) depending if the next waypoint, (the end of this bezier curve and the start of the next one) is either higher or lower than him, so if higher a speed of 6 (effect of climbing) and if lower a speed of 10 (effect of descending).
So where does that leave your answer? As he does not fly along at a constant speed.
And I also forgot to say that at a random time a coroutine is called where he will slow down to a speed of 1 slowly rotate to face the player and throw a grenade, then rotate and accelerate back up to speed.
So I think it's not that simple anymore :(
I still think the way I must go is finding the solution to the slow down say over 3 seconds over the last 8 flight positions, or more if needed, as all the rest of the flight works great, just the last bit, the slow down.
Really appreciate your help ..
**EDIT .. Just seen you edit about the animation curve, I'll look into that ..**Thu, 13 Oct 2016 15:34:25 GMTGriffoComment by b1gry4n on b1gry4n's comment
http://answers.unity.com/comments/1255804/view.html
O$$anonymous$$ so, you need to know the point in the path that the player is on. Since you are using a bezier curve, the distance between the 2 points will not work as that is the shortest path between the points. You need to calculate the bezier curve distance. In short...you need to calculate the entire length, including the bezier arcs, in the distance value
When you know length of the slow down and the current point that the player is on, what I would do is evaluate an animation curve. https://docs.unity3d.com/ScriptReference/AnimationCurve.Evaluate.html
divide the remaining distance by the max distance and you will get a value between 0.0 and 1.0. Using the animation curve you can evaluate it and multiply that value by your initial speed. Using the curve you can have your player start the path fast and gradually slow down using the curve.
float speed = slowDownCurve.Evaluate(currentDistance/maxDistance) * initialSpeed
If you have never used an animation curve before, you want the start of the curve to be a value of 1.0 (the left side) and the right side you want to be a value of 0.0. This curve is representing your speed along the path. It should look something like this:
http://i.imgur.com/DtEjDwP.jpg
**OLD STUFF BELOW I had written before I came up with the animation curve idea... you can read it if you want**
*Lets break apart what youre trying to do...
as an example, lets work only in one coordinate...
0----------------------------------------10 //(this is the path it starts at x = 0 and goes to x = 10)
First you need to calculate the initial speed. If you want to travel a great distance in 2 seconds, you need to be moving faster than if you want to travel a very small distance in 2 seconds. The initial speed is calculated by distance/time and would be calculated when you reached the yellow node. You cant plug in speed and distance and expect to cover varying distances over the same time, it doesnt add up. You either need to modify the speed or modify the time.
Lets say I want to cross those 10 units in 0.2 seconds. That means my initial speed is 50 units per second. When we reach the "10" we want to be traveling 0 units per second. In this example, at the 0 point, the player is traveling 50 units a second.
----1-------------------------------------10
now we are at the 1 point in the path, our speed is now
initialSpeed - (initialSpeed * (C/L))
where L represents the length of the bezier arc (10) and C represents our current position (or remaining distance in the bezier path)... (1). So in this example we would now be traveling at 9/10 of 50, or 45. so we are computing, in our example...
currentSpeed = 50 - (50 * (1/10))*Thu, 13 Oct 2016 14:31:56 GMTb1gry4nComment by b1gry4n on b1gry4n's comment
http://answers.unity.com/comments/1255786/view.html
Nevermind, I am wrong. One second let me try to wrap my head around this. I completely understand what you are trying to do, the above script simply slows the character down over X time.Thu, 13 Oct 2016 13:47:09 GMTb1gry4nComment by Griffo on Griffo's comment
http://answers.unity.com/comments/1255781/view.html
@b1gry4n Thanks for the answer, results are showing on a long bezier curve the bot slows down before the end and on a short bezier curve the bot does not seem to slow down, comes to a sudden halt.Thu, 13 Oct 2016 13:18:02 GMTGriffoComment by b1gry4n
http://answers.unity.com/comments/1255760/view.html
function lerpSpeed(desiredSpeed : float, overTime : float)
{
var elapsedTime : float = 0;
incomingFlightSpeed = flightPathScript.flightSpeed;
while (elapsedTime < overTime )
{
flightPathScript.flightSpeed = $$anonymous$$athf.Lerp(incomingFlightSpeed, desiredSpeed, (elapsedTime / overTime));
elapsedTime += Time.deltaTime;
yield;
}
}Thu, 13 Oct 2016 11:42:33 GMTb1gry4n