如何扩展在 C# 和 Unity 中使用二次插值创建的曲线?
How to extend the curve created using quadratic interpolation in C# & Unity?
我正在尝试使用二次插值法向玩家的位置扔石头。岩石只是沿着曲线移动。然而,如果玩家移动,石头就会开始循环并回到原来的位置。一旦它到达曲线的末端,我就停止了跟随曲线的岩石,并向岩石的刚体施加力,但它只在特定的例子中起作用。我想知道是否有一种方法可以延长曲线,使岩石撞击地面并使用我已有的代码自行破坏。我正在使用的代码如下。提前致谢。代码如下。
二次插值码(每帧运行)
private void FollowQuadraticPath()
{
interpolateAmount = (interpolateAmount + Time.deltaTime) % 1f;
pointAB.transform.position = Vector3.Lerp(transformerPosition, throwHeightPosition, interpolateAmount);
pointBC.transform.position = Vector3.Lerp(throwHeightPosition, playerPosition, interpolateAmount);
transform.position = Vector3.Lerp(pointAB.transform.position, pointBC.transform.position, interpolateAmount);
}
伤害
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.GetComponent<PlayerHealth>())
{
Destroy(pointABInstance);
Destroy(pointBCInstance);
collision.gameObject.GetComponent<PlayerHealth>().DealDamage(damage);
Destroy(gameObject);
}
else
{
Destroy(pointABInstance);
Destroy(pointBCInstance);
Destroy(gameObject);
}
}
这就是我想要发生的事情。假装玩家已经移动,岩石将继续并击中经过玩家点的地面。
相反,再次假装玩家不在那里,物体在到达地面之前被摧毁
编辑:检查我使用的解决方案的答案评论
我猜你在 Update
中使用 FollowQuadraticPath()
所以发生的事情是你总是将它与播放器的 当前更新 位置一起使用。
相反,我会使用 Coroutine。 Coroutine 有点像一个临时的 Update 方法,所以它有一个明确的开始和结束,你可以让局部变量在例程 运行ning 的所有帧中持续存在,并做一些类似
的事情
private IEnumerator FollowQuadraticPath()
{
// Cash the target positions ONCE so they are not updated later
var startAB = TransformerPosition;
var targetAB = throwHeightPosition;
var targetBC = playerPosition;
// Iterates until 1 second has passed
// linearly increasing interpolateAmount from 0 to 1
for(var interpolateAmount = 0f; interpolateAmount < 1f; interpolateAmount += Time.deltaTime)
{
pointAB.transform.position = Vector3.Lerp(startAB, targetAB, interpolateAmount);
pointBC.transform.position = Vector3.Lerp(targetAB, targetBC, interpolateAmount);
transform.position = Vector3.Lerp(pointAB.transform.position, pointBC.transform.position, interpolateAmount);
// Tells Unity to "pause" the routine here, render this frame
// and continue from here in the next frame
yield return null;
}
// Destroy if it reaches the original player position
Destroy (gameObject);
}
你 运行 这个 ONCE 例如在
private void Start ()
{
StartCorouine(FollowQuadraticPath());
}
或Start
也可以是例程本身,如
private IEnumerator Start()
{
var startAB = TransformerPosition;
var targetAB = throwHeightPosition;
.....
}
您不必担心终止例程,因为它要么到达原始玩家位置然后被摧毁,要么它之前撞到地面并被摧毁。在任何一种情况下,协程也会自动消失。
不过我不太明白的是,为什么您要为此进行 2 个额外的转换。为什么不简单地只用 Vector3
本身来计算
var ab = Vector3.Lerp(startAB, targetAB, interpolateAmount);
var bc = Vector3.Lerp(targetAB, targetBC, interpolateAmount);
transform.position = Vector3.Lerp(ab, bc, interpolateAmount);
我正在尝试使用二次插值法向玩家的位置扔石头。岩石只是沿着曲线移动。然而,如果玩家移动,石头就会开始循环并回到原来的位置。一旦它到达曲线的末端,我就停止了跟随曲线的岩石,并向岩石的刚体施加力,但它只在特定的例子中起作用。我想知道是否有一种方法可以延长曲线,使岩石撞击地面并使用我已有的代码自行破坏。我正在使用的代码如下。提前致谢。代码如下。
二次插值码(每帧运行)
private void FollowQuadraticPath()
{
interpolateAmount = (interpolateAmount + Time.deltaTime) % 1f;
pointAB.transform.position = Vector3.Lerp(transformerPosition, throwHeightPosition, interpolateAmount);
pointBC.transform.position = Vector3.Lerp(throwHeightPosition, playerPosition, interpolateAmount);
transform.position = Vector3.Lerp(pointAB.transform.position, pointBC.transform.position, interpolateAmount);
}
伤害
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.GetComponent<PlayerHealth>())
{
Destroy(pointABInstance);
Destroy(pointBCInstance);
collision.gameObject.GetComponent<PlayerHealth>().DealDamage(damage);
Destroy(gameObject);
}
else
{
Destroy(pointABInstance);
Destroy(pointBCInstance);
Destroy(gameObject);
}
}
这就是我想要发生的事情。假装玩家已经移动,岩石将继续并击中经过玩家点的地面。
相反,再次假装玩家不在那里,物体在到达地面之前被摧毁
编辑:检查我使用的解决方案的答案评论
我猜你在 Update
中使用 FollowQuadraticPath()
所以发生的事情是你总是将它与播放器的 当前更新 位置一起使用。
相反,我会使用 Coroutine。 Coroutine 有点像一个临时的 Update 方法,所以它有一个明确的开始和结束,你可以让局部变量在例程 运行ning 的所有帧中持续存在,并做一些类似
的事情private IEnumerator FollowQuadraticPath()
{
// Cash the target positions ONCE so they are not updated later
var startAB = TransformerPosition;
var targetAB = throwHeightPosition;
var targetBC = playerPosition;
// Iterates until 1 second has passed
// linearly increasing interpolateAmount from 0 to 1
for(var interpolateAmount = 0f; interpolateAmount < 1f; interpolateAmount += Time.deltaTime)
{
pointAB.transform.position = Vector3.Lerp(startAB, targetAB, interpolateAmount);
pointBC.transform.position = Vector3.Lerp(targetAB, targetBC, interpolateAmount);
transform.position = Vector3.Lerp(pointAB.transform.position, pointBC.transform.position, interpolateAmount);
// Tells Unity to "pause" the routine here, render this frame
// and continue from here in the next frame
yield return null;
}
// Destroy if it reaches the original player position
Destroy (gameObject);
}
你 运行 这个 ONCE 例如在
private void Start ()
{
StartCorouine(FollowQuadraticPath());
}
或Start
也可以是例程本身,如
private IEnumerator Start()
{
var startAB = TransformerPosition;
var targetAB = throwHeightPosition;
.....
}
您不必担心终止例程,因为它要么到达原始玩家位置然后被摧毁,要么它之前撞到地面并被摧毁。在任何一种情况下,协程也会自动消失。
不过我不太明白的是,为什么您要为此进行 2 个额外的转换。为什么不简单地只用 Vector3
本身来计算
var ab = Vector3.Lerp(startAB, targetAB, interpolateAmount);
var bc = Vector3.Lerp(targetAB, targetBC, interpolateAmount);
transform.position = Vector3.Lerp(ab, bc, interpolateAmount);