I have list of translations and rotations for a gameobject with timeframe.
Example (translation):
Point 1: (X1, Y1, Z1) Current Time T1
Point 2: (X2, Y2, Z2) Current Time T2
Point 3: (X3, Y3, Z3) Current Time T3
...
In this case, I need a coroutine with Lerp from Point 1 to 2 with (T2-T1) seconds. After, from Point 2 to 3 with T3-T2 seconds... The point is, each movement should wait the completion of previous one. The delta time between points is roughly 0.1 seconds.
How should I do it? In addition, I also have the rotations (Rx1-n,Ry1-n,Rz1-n) similar to translations.
The movement can be done in a simple Coroutine like
// Moves a given object from A to B within given duration
IEnumerator MoveWithinSeconds(Transform obj, Vector3 from, Vector3 to, float duration)
{
var timePassed = 0f;
while(timePassed < duration)
{
// will always be a factor between 0 and 1
var factor = timePassed / duration;
// optional ease-in and ease-out
// factor = Mathf.SmoothStep(0,1,factor);
// linear interpolate the position
obj.position = Vector3.Lerp(from, to, factor);
// increase timePassed by time since last frame
// using Min to avoid overshooting
timePassed += Mathf.Min(Time.deltaTime, duration - timePassed);
// "pause" the routine here, render the frame
// and continue from here in the next one
yield return null;
}
// just to be sure apply the target position in the end
obj.position = target;
}
and then simply iterate your elements from another Coroutine like
// the object you want to move
public Transform obj;
// your waypoints class with position and time stamp
public List<WAYPOINT>() waypoints;
IEnumerator MovementRoutine()
{
// if 0 or only 1 waypoint then it makes no sense to go on
if(waypoints.Count <= 1) yield break;
// pick the first item
var fromPoint = waypoints[0];
// since you already have the first start the iteration with the second item
for(var i = 1; i < waypoints.Count; i++)
{
var toPoint = waypoints[i];
var fromPosition = fromPoint.position;
var toPosition = toPoint.position;
var duration = toPoint.time - fromPoint.time;
// this executes and at the same time waits(yields) until the MoveWithinSeconds routine finished
yield return MoveWithinSeconds(obj, fromPosition, toPosition, duration);
// update fromPoint for the next step
fromPoint = toPoint;
}
}
Same can be done for rotations. Note however that rotating in eulerspace by only XYZ is a bit tricky in some conditions. You should probably rather store and use Quaternion with XYZW.
Note: This will work well as long as your frame-rate is high enough / the delta time big enough. The problem is that yield return
postpones the following code at least 1 frame. So in cases where the delta time becomes smaller then the frame-rate it will not work as expected.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.