-
Notifications
You must be signed in to change notification settings - Fork 4
AngularTransformDrive gets stuck when its current rotation is outside DriveLimit range #267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
so yeah it looks like changing the min/max limit to something underneath your existing limit causes an issue. Partially because of the rotation multiplier as your work around is addressing But also because the pseudo rotation is way higher than the new limit. So looks like your workaround is basically setting the rotation multiplier to be within the limit again, but will this also set the pseudorotation to the correct value? |
No, the workaround above does not set the psudorotation to the correct value. It was a temp fix to at least get the rotation multiplier within acceptable values and getting the drive unstuck. I made a slightly improved version of my reflection workaround that now updates the psudorotation to the limit when it detects new limits is exceeded. New workaround that fix drive limit getting stuck and updates its psudorotation // Reflection to get inner values of angular drive
private static FieldInfo _fRotationMultiplier = AngularFieldInfo("rotationMultiplier");
private static FieldInfo _fCurrentPseudoRotation = AngularFieldInfo("currentPseudoRotation");
private static FieldInfo _fPreviousPseudoRotation = AngularFieldInfo("previousPseudoRotation");
private static FieldInfo _fCurrentActualRotation = AngularFieldInfo("currentActualRotation");
private static FieldInfo _fPreviousActualRotation = AngularFieldInfo("previousActualRotation");
private static MethodInfo _mGetSimpleEulerAngles = AngularMethodInfo("GetSimpleEulerAngles");
private static MethodInfo _mGetDriveTransform = AngularMethodInfo("GetDriveTransform");
private const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
private static FieldInfo AngularFieldInfo(string fieldName) => typeof(AngularDrive).GetField(fieldName, flags);
private static MethodInfo AngularMethodInfo(string methodName) => typeof(AngularDrive).GetMethod(methodName, flags);
public void SetMinMaxLimitWithCrudeFix(Vector2 minMax)
{
angularFacade.DriveLimit = new FloatRange(minMax);
var simpleEulerAngles = (Vector3) _mGetSimpleEulerAngles.Invoke(angularFacade.Drive, null);
var rotationMultiplier = (float) _fRotationMultiplier.GetValue(angularFacade.Drive);
var currentPseudoRotation = simpleEulerAngles[(int) angularFacade.DriveAxis] + (rotationMultiplier * 360f);
var currentLimit = angularFacade.DriveLimit;
if (currentLimit.Contains(currentPseudoRotation))
return;
// Limits has been exceeded, update angle to current min or max limit
var limitExceeded = currentLimit.maximum;
if (currentPseudoRotation < currentLimit.minimum)
limitExceeded = currentLimit.minimum;
SetAngleNow(limitExceeded);
}
public void SetAngleNow(float targetAngle)
{
// Reset drive first, (Mostly to stop velocity)
angularFacade.Drive.ResetDrive();
// Ensure new angle is withing current limits
var limit = angularFacade.DriveLimit;
targetAngle = targetAngle.Clamp(limit.minimum, limit.maximum);
var driveAxis = angularFacade.DriveAxis;
var axis = Vector3.zero;
if (driveAxis == DriveAxis.Axis.XAxis)
axis = Vector3.right;
else if (driveAxis == DriveAxis.Axis.YAxis)
axis = Vector3.up;
else
axis = Vector3.forward;
// Update drive transform so it is now at correct local rotation for axis
var driveTransform = (Transform) _mGetDriveTransform.Invoke(angularFacade.Drive, null);
driveTransform.localRotation= Quaternion.AngleAxis(targetAngle, axis);
// Updates psudo rotation values
_fCurrentPseudoRotation.SetValue(angularFacade.Drive, targetAngle);
_fPreviousPseudoRotation.SetValue(angularFacade.Drive, targetAngle);
// Calculate and set new rotation multiplier
_fRotationMultiplier.SetValue(angularFacade.Drive, Mathf.Floor(targetAngle / 360f));
// Recalculate values for ActualRotation
var simpleEulerAngles = (Vector3) _mGetSimpleEulerAngles.Invoke(angularFacade.Drive, null);
_fCurrentActualRotation.SetValue(angularFacade.Drive, simpleEulerAngles);
_fPreviousActualRotation.SetValue(angularFacade.Drive, simpleEulerAngles);
} |
Environment
Unity 2021.3
"io.extendreality.tilia.interactions.controllables.unity": "2.10.21",
"io.extendreality.tilia.interactions.interactables.unity": "2.16.6",
Steps to reproduce
1: Create standard VRTK environment with interactor
2: Create an AngularTransformDrive and set its DriveLimit max to 800 (Above 720)
3: Create script that will set AngularDriveFacade SetDriveLimitMaximum to 300 (Below 360)
4: Play Game
5: Grab and rotate cube so it reaches maximum 800.
6: Invoke script so DriveLimit max is set to 300.
7: Try to grab and rotate cube again.
Expected behavior
Cube should still be able to be rotated within min/max DriveLimit range.
Current behavior
Cube is stuck, unable to be rotated,
Other:
My crude workaround to set DriveLimit without it getting stuck.
The text was updated successfully, but these errors were encountered: