I have tiles on a board that need to go from whatever distance they are from 5, to 5.
e.g. 1 goes through 2, then through 3 until 5.
3 goes through 4 and 5.
Currently it looks like the following bit of code.
IEnumerator Merge ()
{
float timeStamp = Time.time;
float lerpTime = 0.5f / maxDistance;
while (currentDistance > 0)
{
timeStamp = Time.time;
while (Time.time < timeStamp + lerpTime)
{
float t = (Time.time - timeStamp) / lerpTime;
//here I iterate through all the units with a matching distance.
//Lerp from their current to next position
}
currentDistance--;
}
}
The problem is that this is really linear and I’d like to ease it. Something along the lines of
float t = (Time.time - timeStamp) / lerpTime;
t = Mathf.Sin (0.5f * Mathf.PI * t);
I can’t just toss this into my while loop since it’ll ease every segments individually. I’d like to ease the whole thing. E.g, 1 to 2 would be much faster than 4 to 5. I can’t figure this out by myself. Any ideas?
Ease from start to finish, once, if that makes any sense.
A path is defined for each tiles before the coroutine is called so that the tiles know where to navigate. In the image in my previous post, the path for “1” would be 2, 3, 4 and then it ends at 5.
Basically, I’d need to be able to navigate through all these waypoints, following one single smoothing curve.
Perhaps I’m not clear enough. Right now, my interpolation routine covers the movement on a segment basis. E.G. Below, the routine is called once for the movement covering from (0, 3) to (0, 2), and then another time for (0, 2) to (1, 2), and so on until it reaches (1, 0). It’s easy for me to smooth the movement between each segments.
What I’m trying to accomplish is to smooth the movement over all the segments as a whole, not individually.
I just think your whole Merge function is too complicated. I am not sure how you are calling the move function but if it is in the Update function then it should be as simple as to just feed the Time.time value into Mathf.Sin as the Vector3.Lerp step.
IEnumerator Merge ()
{
//maxDistance is an int that represents the furthest distance away from the final target
float mergeTime = 0.5f / maxDistance;
//Args that will be fed to iTween
Hashtable args = new Hashtable();
args.Add("time", mergeTime);
args.Add("position", Vector3.zero);
while (maxDistance > 0)
{
//Creates a list with the units who's distance is matching the distance iterator
List<Unit> movingUnits = distanceDictionary.Where(pair => pair.Value == maxDistance)
.Select(pair => pair.Key)
.ToList();
//Iterates through the moving units and orders them to their new position
for (int i = 0; i < movingUnits.Count; i++)
{
//Following 2 lines of code are basically fetching the world position this unit needs to reach
Unit target = paths [movingUnits [i]] [maxDistance - 1];
Vector3 temp = (Vector3) UnitsManager.Instance.GetRealPosition (target.gridPosition);
args ["position"] = temp;
iTween.MoveTo (movingUnits [i].gameObject, args);
}
//Waits for the duration of the movement
yield return new WaitForSeconds (mergeTime);
//Destroys the units that just moved. In my case it makes sense since they're overlapping with
//the unit that was the next in the path and that's not visible to the user
for (int i = movingUnits.Count - 1; i >= 0; i--)
{
movingUnits [i].DestroyUnit ();
}
maxDistance--;
}
}
iTween.MoveTo(movingUnits*.gameObject, args);* with this one: moveTime = Time.time; Vector3.Lerp(movingUnits_.gameObject,args[“position”],Mathf.Sin(Time.time - moveTime)*args[“time”]);_ Hopefully my reasoning is ok, basically what this should do is even though you are iterating through all the move functions you can use the Math.Sin() and as time passes the value of Mathf.Sin should go up before going back down aka easing out. moveTime should be set prior to each objects movement and not before each objects movement iteration. That’s what I am thinking at least…
I could lerp from the start position to the final position over the total period of time, and then apply smoothing, that would smooth the movement overall as intended, but then my units wouldn’t follow their paths and they’d go directly to the end point.
No you lerp between your positions like you did before but since the TIME flows normally in the coroutine it is only going to get higher, therefore the speed/step will grow with time no matter which iteration you are in.
How would I move my units based on that? If it was linear, I could do something like
float tClone = t - (1 - (distanceRemaining/totalDistance)) * totalDistance);
and I would know to call my units movement iterations every “totalDuration/waypointsCount” since it’s constant.
How does it work with a smoothed curve? Like, how do I know when I should call my next movement iteration? Obviously the duration between the first and the second call should be different than the duration between the second-to-last and the last call, given the nature of the smoothing.
Edit : Added game gif. Figured this would provide a bit more information. Currently the movement (when the tiles turn white) is linear, and I’m trying to smooth it as a whole.
Sorry, it should have been Vector3.MoveTowards. The Mathf.Sin function is going to affect the “step” value meaning that it will start slow, ramp up to top of the sine curve then slow back down.