- Home /
Hinge Motor Stuck After Hitting Limits
I have a door in my scene with the following structure:
-DoorObject -Frame -DoorOuter -DoorInner
DoorObject is just the container, it has a box collider setup as a trigger for interaction. Frame is just part of the mesh I imported as the door frame, containing just MeshFilter and Renderer. DoorOuter is where I've setup my HingeJoint and Rigidbody, DoorInner is the geometry and collider containing MeshFilter, MeshRenderer and MeshCollider(Convex=true, IsTrigger=false).
Hinge seems to be working fine, I can walk into it and push the door around on its hinge. I've added limits so the door opens one way and can spin to almost hitting the next interior wall(Like a real door). Hinge/Rigidbody properties are as such:
Rigidbody:
Drag: 0.5
Angular Drag: 0.5
Use Gravity: false
Kinematic: false
Interpolate: none
Collision Detection: Discrete
Constraints: all unchecked
HingeJoint:
Connected body: none
Axis stuff is fine, and anchor stuff is autoconfigured, this all seems fine
Use Spring: no
Use Motor: no(Changed at runtime)
- Use Limits: yes
Min: 0
Max: 170
Min Bounce: 0
Max Bounce: 0
Break Force: infinity
Break Torque: infinity
Enable Collision: no
Enable preprocessing: yes
I have a script on the door for handling certain interactions. Side A is the side that can be pushed, if you were on side B, you would pull the door to open it. So from Side A, when the door is closed, you can just open it by pushing into it, once open, an interaction is available to close this door. Pressing the button to close the door from Side A does the following:
public void Close() { JointMotor motor = _hinge.motor; motor.force = 50; motor.targetVelocity = 100f; _hinge.motor = motor; }
Seems pretty simple, and this works, it will close the door and disables the motor once it closes using some logic in the door's update script:
private void Update() { if (_hinge.useMotor) { if(_hinge.motor.force > 0f) { if(_door.localEulerAngles.y < 91f) { Debug.Log ("Was closing, turn off motor"); _hinge.useMotor = false; } } else { if(_door.localEulerAngles.y > 150f) { Debug.Log ("Was opening, turn off motor"); _hinge.useMotor = false; } } } }
I know there's some magic numbers there, when the local y angle is approximately 90, the door is closed, and the max limit is set to around 180 on the hinge so it doesn't open through the wall, so when opening it kills the motor at 150, momentum will carry the door to its upper limit.
So, sorry for long explanation, wanted to be very clear, the problem:
When I push the door open from Side A, then hit the interaction to close the door, the motor turns on and it closes the door(I can even see the useMotor checkbox the inspector check on when closing and check off when done), then disables the motor once closed, then I can repeat this process. HOWEVER, when I push open the door hard enough and let it hit its upper limit, then the interaction does nothing, the door stays stuck on its upper limit. STRANGER YET, when stuck in this manner, the interaction still shows in the inspector that the useMotor is turned on, but does nothing - and weirdest of all, when stuck, if I check off the useMotor in the inspector, the door closes as if it was on a motor(This may just be a runtime issue with the hinge/motor and the inspector not reflecting values correctly, but I still found it very odd).
Hope this isn't TLDR, please let me know if any additional details are required, and thank you in advance for any assistance.
Answer by t36k · Mar 26, 2017 at 05:53 PM
I have a similar set up except in 2D. I have an object with a hinge joint and I flip it back and forth between its limits using the motor. And like you when my hinge joint hits the upper or lower angle limits in some cases it was getting stuck.
What I ended up doing was giving the limits some buffer. And instead of using the limit state provided by the hinge joint like this:
private void Update()
{
if (joint.limitState == JointLimitState2D.LowerLimit ||
joint.limitState == JointLimitState2D.UpperLimit)
{
startSpeed *= -1;
SetMotorSpeed(startSpeed);
}
}
I opted to look at the joint angle and do my own comparison with a buffer of 5 degrees:
private void Update()
{
if (joint.jointAngle <= joint.limits.min + 5f &&
joint.motor.motorSpeed < 0f)
{
startSpeed *= -1;
SetMotorSpeed(startSpeed);
}
else if (joint.jointAngle >= joint.limits.max - 5f &&
joint.motor.motorSpeed > 0f)
{
startSpeed *= -1;
SetMotorSpeed(startSpeed);
}
}
private void SetMotorSpeed(float speed)
{
motor = joint.motor;
motor.motorSpeed = speed;
joint.motor = motor;
}
I've also noticed that sprites connected with a hinge joint will sometimes break apart or behave strangely when the hinge joint hits the angle limit.
My solution is kinda hacky but I need to finish my game. Seriously.