Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Digital Leaf · Sep 28, 2012 at 06:14 AM · physicsrigidbodyhingejointlocalscale

Hinge Joint Breaks When LocalScale is Changed

I have a composite GameObject with arms, legs, and head connected to a torso with hingejoint components. Each contains a non-kinematic rigidbody, collider, and is parented to a common empty GameObject. The mass for each rigidbody is exactly 1. The colliders all exist on the same Layermask which is set to collide with itself. At original scale, the colliders do not overlap. Additionally, these GameObjects are linked to a prefab. All hinge joints are instantiated with a non-infinite breaking force.

When the local scale of the parent Transform is changed, the hinge joints break. This is observed when:

  • The common Layermask is set to not collide with itself.

  • When gravity is zero'd.

  • When Instantiating the prefab programatically and immediately changing the localscale of the parent transform.

  • When Instantiating the prefab from the editor and changing the localscale of the parent transform arbitrarily.

  • When Instantiating the prefab, setting each rigidbody to kinematic, changing the localscale, advancing a frame, and setting each rigidbody back to non-kinematic.

  • Setting break forces to infinity, setting localscale, setting break forces back to non-infinite values. Single frame operation.


On inspection, it appears that hinge joint anchors do not move when localscale is modified. This will account for the hingejoint breaks; transforms move, but they are expected to be in a previous location. The hingejoint will exert a force on itself in order to return to the expected position, but this force is enough to break some breaking forces. This is exacerbated with colliders and a increase in local scale; the hingejoints will need to move the joints to within a collider, which will probably result in massive forces. Think about that for a minute.

Originally, I was going to ask for ideas on how to avoid those breaks, but researching the issue seems to have given me some ideas. Regardless, I'll submit this in case anyone else runs into the same issue, or has a better solution.

Proposed solution: During the frame where you adjust the localscale of a parent GameObject which contains hingejoints, scale the positions of the hingejoint anchors by the magnitude of the adjustment to the localscale. Assuming that this works, I will respond with confirmation. Else, frustration.


So, I tried out the anchor-adjustment strategy. Unfortunately, it doesn't work. Kind-of. I've made some observations:

  1. If your Prefab is instantiated with the HingeJoints already attached and then local scale is changed, the break occurs. However, if your Prefab contains no pre-attached HingeJoints, but instead adds HingeJoints afterwards, the HingeJoints will not break after local scale is changed.

  2. If you recycle and reconstruct (put all the transforms back in the original positions, rotations, etc) the HingeJointed object (including recreating broken HingeJoints), your HingeJoints will not break when they have their local scale changed.

For clarity, adjusting the anchors of the HingeJoints doesn't help at all. What matters is the difference between the positions of the transforms of the HingeJoint objects before and after the change to local scale. If the hinge joints don't exist before the local scale is changed, then there can be no difference.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by zzxzczxczxc · Aug 10, 2014 at 02:22 PM

I've solved similar problem and want to share solution.

My situation was: I have built chain of nodes with HingeJoint2D and angle limit. When i try to change scale of nodes or theirs parent limits work incorrectly.

What really happens: I found that HingeJoint2D.referenceAngle changes after any of this operations, but limits are the same. It cause incorrect angle clamping.

I fix it by store angle limits of joint in world space and apply back after reference angle changed.

Here the code:

using UnityEngine;

public class JointCorrector : MonoBehaviour { private HingeJoint2D _joint; private float _referenceAngle; private float _lowerLimit; private float _upperLimit;

 void Start() {
     _joint = GetComponent<HingeJoint2D>();

     if (_joint != null) {
         _referenceAngle = _joint.referenceAngle;

         var localLimits = _joint.limits;
         _lowerLimit = _referenceAngle + localLimits.min;
         _upperLimit = _referenceAngle + localLimits.max;
     }
 }
 
 void Update() {
     if (_joint == null) {
         return;
     }

     float newAngle = _joint.referenceAngle;
     if (_referenceAngle != newAngle) {
         var limits = new JointAngleLimits2D();
         
         limits.min = Angle(_lowerLimit - newAngle);
         limits.max = Angle(_upperLimit - newAngle);
         
         _joint.limits = limits;
         _referenceAngle = newAngle;
     }
 }
 
 public static float Angle(float angle) {
     angle = Mathf.Repeat(angle, 360f);
     if (angle > 180f) {
         angle -= 360f;
     }
     return angle;
 }

}

Will be glad if it help anybody.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image cmann · May 20, 2019 at 02:00 PM 0
Share

Thanks this worked.

avatar image
0

Answer by dioxidin · Nov 21, 2013 at 07:58 PM

I'm faced with similar behavior in v. 4.3.0 See my project on github

There I've attached the smooth grow script to Bones. It seems that when localScale is changed in script, then Angle Limits in HingeJoint of child stops working. Or maybe I'm doing something wrong.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image dioxidin · Nov 21, 2013 at 08:44 PM 0
Share

The issue with HingeJoint2D fixed by scaling the connectedAnchor See the commit with fix

avatar image AngryCSharpNerd · Jul 18, 2014 at 01:15 PM 0
Share

Sorry for bumping this - but can I get extra help on this? I don't understand this solution.

avatar image
0

Answer by cmann · May 20, 2019 at 02:31 PM

I found the same problem when changing a joint's connectedBody. Based on zzxzczxczxc's answer, but I instead calculate the difference when something changes.

 public static void UpdateHingeJoint2DConnectedBody(HingeJoint2D joint, Rigidbody2D newBody)
 {
     float originalReferenceAngle = joint.referenceAngle;
     
     // Make changes here
     joint.connectedBody = newBody;
     
     float delta = Mathf.DeltaAngle(joint.referenceAngle, originalReferenceAngle);
     JointAngleLimits2D limits = joint.limits;
     limits.min += delta;
     limits.max += delta;
     joint.limits = limits;
 }
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

12 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How do you attach moving parts (moved by physics) to an animated character? (Secondary Animations) 1 Answer

How to limit the motion direction of a GameObject? 1 Answer

Hinge Joints Interfering with each other 0 Answers

Hingejoint: how to change axis correctly? 0 Answers

Hinge Joint goes crazy 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges