c# - Unity Lerp in seconds - 点列表
问题描述
我有一个带有时间框架的游戏对象的翻译和旋转列表。
示例(翻译):
Point 1: (X1, Y1, Z1) Current Time T1
Point 2: (X2, Y2, Z2) Current Time T2
Point 3: (X3, Y3, Z3) Current Time T3
...
在这种情况下,我需要一个与 Lerp 从点 1 到 2 的协程,时间为 (T2-T1) 秒。之后,从第 2 点到第 3 点,用 T3-T2 秒……关键是,每个动作都应该等待前一个动作的完成。点之间的增量时间大约为 0.1 秒。
我该怎么做?此外,我还有类似于平移的旋转 (Rx1-n,Ry1-n,Rz1-n)。
解决方案
移动可以在一个简单的协程中完成,比如
// 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;
}
然后简单地从另一个协程迭代你的元素,比如
// 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;
}
}
旋转也可以这样做。但是请注意,在某些情况下,仅通过 XYZ 在欧拉空间中旋转有点棘手。您可能更应该将四元数与 XYZW 一起存储和使用。
注意:只要您的帧速率足够高/增量时间足够大,这将运行良好。问题在于yield return
将以下代码至少推迟 1 帧。因此,在增量时间变得小于帧速率的情况下,它将无法按预期工作。
推荐阅读
- joomla - 无法让 addScriptDeclaration() 在模块内工作
- spring-boot - 为单元测试生成 javax.validation.ConstraintViolationException
- c# - Unity 角色资产在多人游戏中不起作用
- node.js - Hue API 远程基本认证
- c# - 如何检索频道中的不和谐用户列表
- blueprism - 计算最后一个工作日
- python - 获取ValueError:尝试粘贴时透明蒙版错误,图像和蒙版相同
- php - 如何使用 ImageMagick 实现这种模糊的文本轮廓效果?
- javascript - 从日期选择器更改为日期时间选择器
- java - Java程序未从命令行读取环境变量集