RigidBody.MovePosition到达目的地也不会停下来
RigidBody.MovePosition won't stop even after reaching the destination
我正在创建一个不断从 A 点移动到 B 点的电梯。
我不能只使用 transform.position ( location here * speed here etc)
,因为我有一个带有 Rigidbody
的播放器,如果使用它,每当我在电梯上时,我的播放器就会闪烁。我还尝试在玩家在电梯上时为玩家设置父级(并在它跳跃时取消其父级等),这修复了闪烁,但它在玩家的跳跃机制上有些错误。
最后的手段是使用 Rigidbody
到我的电梯并使用此代码移动它:
private void FixedUpdate()
{
Vector2 l_mypos = new Vector2(transform.position.x, transform.position.y);
Vector2 l_target = new Vector2(_targetPoint.position.x, _targetPoint.position.y);
if (l_mypos != l_target)
{
MoveElevator(l_target);
Debug.Log(l_mypos + " - " + l_target);
}
else
Debug.Log("reached");
}
private void MoveElevator(Vector2 toTarget)
{
Vector2 direction = (toTarget - (Vector2)transform.position).normalized;
_elevatorRB.MovePosition((Vector2)transform.position + direction * _speed * Time.deltaTime);
}
这会使电梯朝给定的方向移动,但是它没有达到 "reached" 条件。我在那里放置了一个 debug.log 以查看 mpos
和 target
以查看差异。它以 0, 10, 0 - 0, 10, 0
结尾,这意味着我的目标和电梯的位置已经相同。但是没有达到else条件,电梯一直在B点闪烁
Vector2
的 ==
operator 使用 0.00001
的估计来实现相等。
然而,您很可能在
中超出了目标
(Vector2)transform.position + direction * _speed * Time.deltaTime
因为你的最终速度speed * Time.deltaTime
肯定大于0.00001
。 (除了你的 speed
小于 0.0006
我怀疑。)
您在 Debug.Log
中看到的值是 Vector3.ToString
的结果,它使用人类可读的四舍五入值而不显示实际的 float
值!来自 source code
public override string ToString()
{
return ToString(null, CultureInfo.InvariantCulture.NumberFormat);
}
public string ToString(string format)
{
return ToString(format, CultureInfo.InvariantCulture.NumberFormat);
}
public string ToString(string format, IFormatProvider formatProvider)
{
if (string.IsNullOrEmpty(format)) format = "F1"; // <- !! HERE !!
return UnityString.Format("({0}, {1}, {2})", x.ToString(format, formatProvider), y.ToString(format, formatProvider), z.ToString(format, formatProvider));
}
您应该使用 Vector2.MoveTowards
来避免这种过度。
Vector3.MoveTowards
的 API 实际上解释得比 Vector2.MoveTowards
更好
Calculate a position between the points specified by current
and target
, moving no farther than the distance specified by maxDistanceDelta
.
Use the MoveTowards
member to move an object at the current
position toward the target
position. By updating an object’s position each frame using the position calculated by this function, you can move it towards the target smoothly. Control the speed of movement with the maxDistanceDelta
parameter. If the current
position is already closer to the target
than maxDistanceDelta
, the value returned is equal to target
; the new position does not overshoot target. To make sure that object speed is independent of frame rate, multiply the maxDistanceDelta
value by Time.deltaTime
private void FixedUpdate()
{
// Vector3 and Vector2 have implicit operators allowing to use
// both types exchangeably.
// In order actively to convert them you can simply typecast between them
var l_mypos = (Vector2) transform.position;
var l_target = (Vector2) _targetPoint.position;
if (l_mypos != l_target)
{
MoveElevator(l_target);
Debug.Log(l_mypos + " - " + l_target);
}
else
{
Debug.Log("reached");
}
}
private void MoveElevator(Vector2 toTarget)
{
var pos = Vector2.MoveTowards(transform.position, toTarget, _speed * Time.deltaTime);
_elevatorRB.MovePosition(pos);
}
我正在创建一个不断从 A 点移动到 B 点的电梯。
我不能只使用 transform.position ( location here * speed here etc)
,因为我有一个带有 Rigidbody
的播放器,如果使用它,每当我在电梯上时,我的播放器就会闪烁。我还尝试在玩家在电梯上时为玩家设置父级(并在它跳跃时取消其父级等),这修复了闪烁,但它在玩家的跳跃机制上有些错误。
最后的手段是使用 Rigidbody
到我的电梯并使用此代码移动它:
private void FixedUpdate()
{
Vector2 l_mypos = new Vector2(transform.position.x, transform.position.y);
Vector2 l_target = new Vector2(_targetPoint.position.x, _targetPoint.position.y);
if (l_mypos != l_target)
{
MoveElevator(l_target);
Debug.Log(l_mypos + " - " + l_target);
}
else
Debug.Log("reached");
}
private void MoveElevator(Vector2 toTarget)
{
Vector2 direction = (toTarget - (Vector2)transform.position).normalized;
_elevatorRB.MovePosition((Vector2)transform.position + direction * _speed * Time.deltaTime);
}
这会使电梯朝给定的方向移动,但是它没有达到 "reached" 条件。我在那里放置了一个 debug.log 以查看 mpos
和 target
以查看差异。它以 0, 10, 0 - 0, 10, 0
结尾,这意味着我的目标和电梯的位置已经相同。但是没有达到else条件,电梯一直在B点闪烁
Vector2
的 ==
operator 使用 0.00001
的估计来实现相等。
然而,您很可能在
中超出了目标(Vector2)transform.position + direction * _speed * Time.deltaTime
因为你的最终速度speed * Time.deltaTime
肯定大于0.00001
。 (除了你的 speed
小于 0.0006
我怀疑。)
您在 Debug.Log
中看到的值是 Vector3.ToString
的结果,它使用人类可读的四舍五入值而不显示实际的 float
值!来自 source code
public override string ToString()
{
return ToString(null, CultureInfo.InvariantCulture.NumberFormat);
}
public string ToString(string format)
{
return ToString(format, CultureInfo.InvariantCulture.NumberFormat);
}
public string ToString(string format, IFormatProvider formatProvider)
{
if (string.IsNullOrEmpty(format)) format = "F1"; // <- !! HERE !!
return UnityString.Format("({0}, {1}, {2})", x.ToString(format, formatProvider), y.ToString(format, formatProvider), z.ToString(format, formatProvider));
}
您应该使用 Vector2.MoveTowards
来避免这种过度。
Vector3.MoveTowards
的 API 实际上解释得比 Vector2.MoveTowards
Calculate a position between the points specified by
current
andtarget
, moving no farther than the distance specified bymaxDistanceDelta
.Use the
MoveTowards
member to move an object at thecurrent
position toward thetarget
position. By updating an object’s position each frame using the position calculated by this function, you can move it towards the target smoothly. Control the speed of movement with themaxDistanceDelta
parameter. If thecurrent
position is already closer to thetarget
thanmaxDistanceDelta
, the value returned is equal totarget
; the new position does not overshoot target. To make sure that object speed is independent of frame rate, multiply themaxDistanceDelta
value byTime.deltaTime
private void FixedUpdate()
{
// Vector3 and Vector2 have implicit operators allowing to use
// both types exchangeably.
// In order actively to convert them you can simply typecast between them
var l_mypos = (Vector2) transform.position;
var l_target = (Vector2) _targetPoint.position;
if (l_mypos != l_target)
{
MoveElevator(l_target);
Debug.Log(l_mypos + " - " + l_target);
}
else
{
Debug.Log("reached");
}
}
private void MoveElevator(Vector2 toTarget)
{
var pos = Vector2.MoveTowards(transform.position, toTarget, _speed * Time.deltaTime);
_elevatorRB.MovePosition(pos);
}