找到旋转的差异,作为随时间统一的平均值 c#
Finding the difference in rotation, as an average over time unity c#
我有一个玩家可以旋转的船轮。我目前记录角度变化,它被添加到一个总角度。然后我可以计算出船轮转动了多少次。这一切都很好。
void Update()
{
//Record Amount of Wheel Turns
currentAngle = wheelRectTransform.transform.rotation.eulerAngles.z;
angleChange = Mathf.DeltaAngle(currentAngle, previousAngle);
if ((Mathf.Abs(angle + angleChange) / 360) <= wheelTurnsUntilRudderAtMaxAngle)
{
angle += angleChange;
}
totalWheelTurns = angle / 360;
shipStats.RudderAngle = totalWheelTurns / wheelTurnsUntilRudderAtMaxAngle;
previousAngle = currentAngle;
}
不过,我也想记录一下平均角度随时间的变化。然后我就可以准确地知道轮子是向左还是向右旋转。
我试过像这样简单的东西
if (angleChange < 0)
{
// Going Left
}
else if (angleChange > 0)
{
// Going Right
} else
{
// Not moving
}
然而在实践中,如果玩家旋转轮子的速度非常非常慢,则偶尔帧上的角度差为 0 并记录为 'not moving'。
我相信解决方案是找到短时间内的平均角度变化,因此我尝试将角度随时间 Lerp 到 0。
newAngleDifference = Mathf.Lerp(angleChange, 0, Time.deltaTime * 0.2f);
这没有用,它给我的反馈和我刚刚使用的 'angleChange' 一样,无论如何都可以是 0。
谢谢!
吉姆
您不需要平均任何东西来检测车轮的方向。只需使用旧变量和新变量来查找车轮的行驶方向。
void Start()
{
StartCoroutine(wheelDIRCalculator(_wheelTransform));
}
bool continueWheelCalculation = false;
IEnumerator wheelDIRCalculator(Transform wheelTransform)
{
yield return null;
continueWheelCalculation = true;
float oldZAngle = 0;
float newZAngle = 0;
bool isIdle = false;
oldZAngle = Mathf.Abs(wheelTransform.rotation.eulerAngles.z);
while (continueWheelCalculation)
{
//Get new rotation
newZAngle = Mathf.Abs(wheelTransform.rotation.eulerAngles.z);
if (oldZAngle < newZAngle)
{
isIdle = false;
oldZAngle = newZAngle;
Debug.Log("Left");
//Do something
}
else if (oldZAngle > newZAngle)
{
isIdle = false;
oldZAngle = newZAngle;
Debug.Log("Right");
//Do something
}
else if (!isIdle)
{
isIdle = true;
oldZAngle = newZAngle;
Debug.Log("Idle");
//Do something
}
yield return null;
}
}
void stopWheelDIRCalculator()
{
continueWheelCalculation = false;
}
最后我用了Lerp求平均值。
public enum WheelDirection { Left, Right, Still }
[Header("Average Wheel Direction")]
public float lerpTime = 0.5f; // How many seconds average over
private WheelDirection wheelDirection;
private float wheelDeltaX;
private float wheelDirectionInterpolated;
private float currentLerpTime;
void Update()
{
// Get DeltaX of objects rotation
// I'm interested in the Z axis, but you could change this to x/y
float currentAngle = transform.rotation.eulerAngles.z;
wheelDeltaX = (currentAngle - previousAngle);
// Reduce the Lerp percentage
currentLerpTime += Time.deltaTime;
if (currentLerpTime > lerpTime)
{
currentLerpTime = lerpTime;
}
float perc = currentLerpTime / lerpTime;
// Lerp!
wheelDirectionInterpolated = (Mathf.Lerp(wheelDirectionInterpolated, wheelDeltaX, perc));
// Wheel has finished rotating, so reset the Lerp
if (wheelDirectionInterpolated == 0) currentLerpTime = 0;
// Store Direction in an Enum
if (wheelDirectionInterpolated > 0) wheelDirection = WheelDirection.Left;
if (wheelDirectionInterpolated < 0) wheelDirection = WheelDirection.Right;
if (wheelDirectionInterpolated == 0) wheelDirection = WheelDirection.Still;
//This should always be at the end
previousAngle = currentAngle;
}
我有一个玩家可以旋转的船轮。我目前记录角度变化,它被添加到一个总角度。然后我可以计算出船轮转动了多少次。这一切都很好。
void Update()
{
//Record Amount of Wheel Turns
currentAngle = wheelRectTransform.transform.rotation.eulerAngles.z;
angleChange = Mathf.DeltaAngle(currentAngle, previousAngle);
if ((Mathf.Abs(angle + angleChange) / 360) <= wheelTurnsUntilRudderAtMaxAngle)
{
angle += angleChange;
}
totalWheelTurns = angle / 360;
shipStats.RudderAngle = totalWheelTurns / wheelTurnsUntilRudderAtMaxAngle;
previousAngle = currentAngle;
}
不过,我也想记录一下平均角度随时间的变化。然后我就可以准确地知道轮子是向左还是向右旋转。
我试过像这样简单的东西
if (angleChange < 0)
{
// Going Left
}
else if (angleChange > 0)
{
// Going Right
} else
{
// Not moving
}
然而在实践中,如果玩家旋转轮子的速度非常非常慢,则偶尔帧上的角度差为 0 并记录为 'not moving'。
我相信解决方案是找到短时间内的平均角度变化,因此我尝试将角度随时间 Lerp 到 0。
newAngleDifference = Mathf.Lerp(angleChange, 0, Time.deltaTime * 0.2f);
这没有用,它给我的反馈和我刚刚使用的 'angleChange' 一样,无论如何都可以是 0。
谢谢!
吉姆
您不需要平均任何东西来检测车轮的方向。只需使用旧变量和新变量来查找车轮的行驶方向。
void Start()
{
StartCoroutine(wheelDIRCalculator(_wheelTransform));
}
bool continueWheelCalculation = false;
IEnumerator wheelDIRCalculator(Transform wheelTransform)
{
yield return null;
continueWheelCalculation = true;
float oldZAngle = 0;
float newZAngle = 0;
bool isIdle = false;
oldZAngle = Mathf.Abs(wheelTransform.rotation.eulerAngles.z);
while (continueWheelCalculation)
{
//Get new rotation
newZAngle = Mathf.Abs(wheelTransform.rotation.eulerAngles.z);
if (oldZAngle < newZAngle)
{
isIdle = false;
oldZAngle = newZAngle;
Debug.Log("Left");
//Do something
}
else if (oldZAngle > newZAngle)
{
isIdle = false;
oldZAngle = newZAngle;
Debug.Log("Right");
//Do something
}
else if (!isIdle)
{
isIdle = true;
oldZAngle = newZAngle;
Debug.Log("Idle");
//Do something
}
yield return null;
}
}
void stopWheelDIRCalculator()
{
continueWheelCalculation = false;
}
最后我用了Lerp求平均值。
public enum WheelDirection { Left, Right, Still }
[Header("Average Wheel Direction")]
public float lerpTime = 0.5f; // How many seconds average over
private WheelDirection wheelDirection;
private float wheelDeltaX;
private float wheelDirectionInterpolated;
private float currentLerpTime;
void Update()
{
// Get DeltaX of objects rotation
// I'm interested in the Z axis, but you could change this to x/y
float currentAngle = transform.rotation.eulerAngles.z;
wheelDeltaX = (currentAngle - previousAngle);
// Reduce the Lerp percentage
currentLerpTime += Time.deltaTime;
if (currentLerpTime > lerpTime)
{
currentLerpTime = lerpTime;
}
float perc = currentLerpTime / lerpTime;
// Lerp!
wheelDirectionInterpolated = (Mathf.Lerp(wheelDirectionInterpolated, wheelDeltaX, perc));
// Wheel has finished rotating, so reset the Lerp
if (wheelDirectionInterpolated == 0) currentLerpTime = 0;
// Store Direction in an Enum
if (wheelDirectionInterpolated > 0) wheelDirection = WheelDirection.Left;
if (wheelDirectionInterpolated < 0) wheelDirection = WheelDirection.Right;
if (wheelDirectionInterpolated == 0) wheelDirection = WheelDirection.Still;
//This should always be at the end
previousAngle = currentAngle;
}