ExtendRealityLtd / ExtendRealityLtd/Tilia.Interactions.Controllables.Unity

AngularTransformDrive gets stuck when its current rotation is outside DriveLimit range

Open
#267 2 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
C#
Stars
9
Forks
3
PR merge metrics
No merged PRs in 30d

Description

### 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.

```cs
// Workaround for Controllables that can be stuck when rotationMultiplier is not within current DriveLimit restrictions
public void SetMinMaxLimitWithCrudeFix(Vector2 minMax)
{
var angularFacade = GetComponent();
angularFacade.DriveLimit = new FloatRange(minMax);

MethodInfo _mGetSimpleEulerAngels = typeof(AngularDrive).GetMethod("GetSimpleEulerAngles",
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);

FieldInfo _fRotationMultiplier = typeof(AngularDrive).GetField("rotationMultiplier",
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);

var simpleEulerAngels = (Vector3) _mGetSimpleEulerAngels.Invoke(angularFacade.Drive, null);
var rotationMultiplier = (float) _fRotationMultiplier.GetValue(angularFacade.Drive);
var currentPseudoRotation = simpleEulerAngels[(int) angularFacade.DriveAxis] + (rotationMultiplier * 360f);
var currentLimit = angularFacade.DriveLimit;

if (currentLimit.Contains(currentPseudoRotation))
return; // All good, within limits.

var limitExceeded = currentLimit.maximum;
if (currentPseudoRotation < currentLimit.minimum)
limitExceeded = currentLimit.minimum;

// Set rotationMultiplier to be closest step within range of DriveLimit
var diff = currentPseudoRotation - limitExceeded;
var subtractMultiplier = (int) (diff / 360f);
rotationMultiplier = rotationMultiplier - subtractMultiplier;

// Very bad additional workaround:
// Need to overshoot RotationMultiplier by one since I have to fight
// AngularDrive.CalculateRotationMultiplier() that re-applies a rotation step next Process()
rotationMultiplier += subtractMultiplier < 0 ? 1 : -1;

// This workaround does not update current angle to be at the new limit, only that the rotationMultipiler is in valid range.
_fRotationMultiplier.SetValue(angularFacade.Drive, rotationMultiplier);
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.