Reputation: 801
I have a ships wheel the player is able to rotate. I currently record the angle change, which is added to a total angle. I can then work out how many times the ship wheel has been turned. This all works fine.
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;
}
However, I'd also like to record the average angle change over time. Then I would be able to get an accurate idea as to wether the wheel is rotating left or right.
I have tried something simple like this
if (angleChange < 0)
{
// Going Left
}
else if (angleChange > 0)
{
// Going Right
} else
{
// Not moving
}
In practice however, if the player is rotating the wheel very, very slowly the angle difference on the occasional frame is 0 and recorded as 'not moving'.
I believe the solution would be to find the average angle change over a short time so I tried to Lerp the angle to 0 over time.
newAngleDifference = Mathf.Lerp(angleChange, 0, Time.deltaTime * 0.2f);
This didn't work, it gives me the same feedback as I'm just using 'angleChange' which can be 0 anyway.
Thanks!
Jim
Upvotes: 2
Views: 906
Reputation: 801
In the end I used a Lerp to get the average.
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;
}
Upvotes: 1
Reputation: 125315
You don't need to average anything to detect the direction of the wheel. Simply use old and new variable to find which direction the wheel is going.
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;
}
Upvotes: 1