Browse Source

[unity] Fixed Create Hinge Chain creating incorrect hierarchy on multiple children. Closes #2825.

Harald Csaszar 4 months ago
parent
commit
d7f3ab4723

+ 91 - 57
spine-unity/Assets/Spine/Editor/spine-unity/Editor/Components/SkeletonUtilityBoneInspector.cs

@@ -310,7 +310,6 @@ namespace Spine.Unity.Editor {
 				UnityEditor.EditorUtility.DisplayDialog("No parent SkeletonUtilityBone found!", "Please select the first physically moving chain node, having a parent GameObject with a SkeletonUtilityBone component attached.", "OK");
 				return;
 			}
-
 			float mass = 10;
 			const float rotationLimit = 20.0f;
 
@@ -334,40 +333,55 @@ namespace Spine.Unity.Editor {
 			//followRotationComponent.reference = skeletonUtility.boneRoot;
 
 			// Follower Kinematic Rigidbody
-			GameObject followerKinematicObject = new GameObject(kinematicParentUtilityBone.name + " Follower");
-			followerKinematicObject.transform.parent = normalChainParentObject.transform;
-			Rigidbody2D followerRigidbody = followerKinematicObject.AddComponent<Rigidbody2D>();
+			GameObject rootFollowerKinematic = new GameObject(kinematicParentUtilityBone.name + " Follower");
+			rootFollowerKinematic.transform.parent = normalChainParentObject.transform;
+			Rigidbody2D followerRigidbody = rootFollowerKinematic.AddComponent<Rigidbody2D>();
 			followerRigidbody.mass = mass;
 			followerRigidbody.isKinematic = true;
-			followerKinematicObject.AddComponent<FollowLocationRigidbody2D>().reference = kinematicParentUtilityBone.transform;
-			followerKinematicObject.transform.position = kinematicParentUtilityBone.transform.position;
-			followerKinematicObject.transform.rotation = kinematicParentUtilityBone.transform.rotation;
-
-			// Child Bones
-			SkeletonUtilityBone[] utilityBones = utilityBone.GetComponentsInChildren<SkeletonUtilityBone>();
-			Transform childBoneParentReference = followerKinematicObject.transform;
-			for (int i = 0; i < utilityBones.Length; ++i) {
-				SkeletonUtilityBone childBone = utilityBones[i];
-				mass *= 0.75f;
-				childBone.parentReference = (i == 0) ? kinematicParentUtilityBone.transform : childBoneParentReference;
-				childBone.transform.SetParent(normalChainParentObject.transform, true); // we need a flat hierarchy of all Joint objects in Unity.
-				AttachRigidbodyAndCollider2D(childBone);
-				childBone.mode = SkeletonUtilityBone.Mode.Override;
-				childBone.scale = childBone.position = childBone.zPosition = false;
-
-				HingeJoint2D joint = childBone.gameObject.AddComponent<HingeJoint2D>();
-				joint.connectedBody = childBoneParentReference.GetComponent<Rigidbody2D>();
-				joint.useLimits = true;
-				ApplyJoint2DAngleLimits(joint, rotationLimit, childBoneParentReference, childBone.transform);
-
-				childBone.GetComponent<Rigidbody2D>().mass = mass;
-				childBoneParentReference = childBone.transform;
-			}
+			rootFollowerKinematic.AddComponent<FollowLocationRigidbody2D>().reference = kinematicParentUtilityBone.transform;
+			rootFollowerKinematic.transform.position = kinematicParentUtilityBone.transform.position;
+			rootFollowerKinematic.transform.rotation = kinematicParentUtilityBone.transform.rotation;
+
+			CreateHingeChain2D(utilityBone, mass, rotationLimit, normalChainParentObject.transform,
+				rootFollowerKinematic.transform, kinematicParentUtilityBone.transform);
 
 			Duplicate2DHierarchyForFlippedChains(normalChainParentObject, commonParentActivateOnFlip, skeletonUtility.transform, rotationLimit);
 			UnityEditor.Selection.activeGameObject = commonParentObject;
 		}
 
+		void CreateHingeChain2D (SkeletonUtilityBone bone, float mass, float rotationLimit, Transform groupObject,
+			Transform jointParent, Transform utilityParent) {
+
+			mass *= 0.75f;
+			bone.parentReference = utilityParent;
+			bone.transform.SetParent(groupObject, true); // we need a flat hierarchy of all Joint objects in Unity.
+			AttachRigidbodyAndCollider2D(bone);
+			bone.mode = SkeletonUtilityBone.Mode.Override;
+			bone.scale = bone.position = bone.zPosition = false;
+
+			HingeJoint2D joint = bone.gameObject.AddComponent<HingeJoint2D>();
+			joint.connectedBody = jointParent.GetComponent<Rigidbody2D>();
+			joint.useLimits = true;
+			ApplyJoint2DAngleLimits(joint, rotationLimit, jointParent, bone.transform);
+			bone.GetComponent<Rigidbody2D>().mass = mass;
+
+			Transform parent = bone.transform;
+			List<SkeletonUtilityBone> children = new List<SkeletonUtilityBone>();
+			int utilityChildCount = 0;
+			for (int i = 0; i < parent.childCount; ++i) {
+				var childUtilityBone = parent.GetChild(i).GetComponent<SkeletonUtilityBone>();
+				if (childUtilityBone != null)
+					children.Add(childUtilityBone);
+			}
+			mass /= Mathf.Max(1.0f, utilityChildCount);
+
+			for (int i = 0; i < children.Count; ++i) {
+				SkeletonUtilityBone childBone = children[i];
+				if (childBone == null) continue;
+				CreateHingeChain2D(childBone, mass, rotationLimit, groupObject, parent, parent);
+			}
+		}
+
 		void ApplyJoint2DAngleLimits (HingeJoint2D joint, float rotationLimit, Transform parentBone, Transform bone) {
 #if HINGE_JOINT_NEW_BEHAVIOUR
 			float referenceAngle = (parentBone.eulerAngles.z - bone.eulerAngles.z + 360f) % 360f;
@@ -452,6 +466,8 @@ namespace Spine.Unity.Editor {
 				UnityEditor.EditorUtility.DisplayDialog("No parent SkeletonUtilityBone found!", "Please select the first physically moving chain node, having a parent GameObject with a SkeletonUtilityBone component attached.", "OK");
 				return;
 			}
+			float mass = 10;
+			const float rotationLimit = 20.0f;
 
 			SetSkeletonUtilityToFlipByRotation();
 
@@ -465,39 +481,57 @@ namespace Spine.Unity.Editor {
 			followRotationComponent.reference = skeletonUtility.boneRoot;
 
 			// Follower Kinematic Rigidbody
-			GameObject followerKinematicObject = new GameObject(kinematicParentUtilityBone.name + " Follower");
-			followerKinematicObject.transform.parent = chainParentObject.transform;
-			Rigidbody followerRigidbody = followerKinematicObject.AddComponent<Rigidbody>();
-			followerRigidbody.mass = 10;
+			GameObject rootFollowerKinematic = new GameObject(kinematicParentUtilityBone.name + " Follower");
+			rootFollowerKinematic.transform.parent = chainParentObject.transform;
+			Rigidbody followerRigidbody = rootFollowerKinematic.AddComponent<Rigidbody>();
+			followerRigidbody.mass = mass;
 			followerRigidbody.isKinematic = true;
-			followerKinematicObject.AddComponent<FollowLocationRigidbody>().reference = kinematicParentUtilityBone.transform;
-			followerKinematicObject.transform.position = kinematicParentUtilityBone.transform.position;
-			followerKinematicObject.transform.rotation = kinematicParentUtilityBone.transform.rotation;
-
-			// Child Bones
-			SkeletonUtilityBone[] utilityBones = utilityBone.GetComponentsInChildren<SkeletonUtilityBone>();
-			Transform childBoneParentReference = followerKinematicObject.transform;
-			foreach (SkeletonUtilityBone childBone in utilityBones) {
-				childBone.parentReference = childBoneParentReference;
-				childBone.transform.SetParent(chainParentObject.transform, true); // we need a flat hierarchy of all Joint objects in Unity.
-				AttachRigidbodyAndCollider(childBone);
-				childBone.mode = SkeletonUtilityBone.Mode.Override;
-
-				HingeJoint joint = childBone.gameObject.AddComponent<HingeJoint>();
-				joint.axis = Vector3.forward;
-				joint.connectedBody = childBoneParentReference.GetComponent<Rigidbody>();
-				joint.useLimits = true;
-				joint.limits = new JointLimits {
-					min = -20,
-					max = 20
-				};
-				childBone.GetComponent<Rigidbody>().mass = childBoneParentReference.transform.GetComponent<Rigidbody>().mass * 0.75f;
-
-				childBoneParentReference = childBone.transform;
-			}
+			rootFollowerKinematic.AddComponent<FollowLocationRigidbody>().reference = kinematicParentUtilityBone.transform;
+			rootFollowerKinematic.transform.position = kinematicParentUtilityBone.transform.position;
+			rootFollowerKinematic.transform.rotation = kinematicParentUtilityBone.transform.rotation;
+
+			CreateHingeChain(utilityBone, mass, rotationLimit, chainParentObject.transform, rootFollowerKinematic.transform);
+
 			UnityEditor.Selection.activeGameObject = chainParentObject;
 		}
 
+		void CreateHingeChain (SkeletonUtilityBone bone, float mass, float rotationLimit, Transform groupObject,
+			Transform jointParent) {
+
+			mass *= 0.75f;
+
+			bone.parentReference = jointParent;
+			bone.transform.SetParent(groupObject.transform, true); // we need a flat hierarchy of all Joint objects in Unity.
+			AttachRigidbodyAndCollider(bone);
+			bone.mode = SkeletonUtilityBone.Mode.Override;
+
+			HingeJoint joint = bone.gameObject.AddComponent<HingeJoint>();
+			joint.axis = Vector3.forward;
+			joint.connectedBody = jointParent.GetComponent<Rigidbody>();
+			joint.useLimits = true;
+			joint.limits = new JointLimits {
+				min = -rotationLimit,
+				max = rotationLimit
+			};
+			bone.GetComponent<Rigidbody>().mass = mass;
+
+			Transform parent = bone.transform;
+			List<SkeletonUtilityBone> children = new List<SkeletonUtilityBone>();
+			int utilityChildCount = 0;
+			for (int i = 0; i < parent.childCount; ++i) {
+				var childUtilityBone = parent.GetChild(i).GetComponent<SkeletonUtilityBone>();
+				if (childUtilityBone != null)
+					children.Add(childUtilityBone);
+			}
+			mass /= Mathf.Max(1.0f, utilityChildCount);
+
+			for (int i = 0; i < children.Count; ++i) {
+				SkeletonUtilityBone childBone = children[i];
+				if (childBone == null) continue;
+				CreateHingeChain(childBone, mass, rotationLimit, groupObject, parent);
+			}
+		}
+
 		void SetSkeletonUtilityToFlipByRotation () {
 			if (!skeletonUtility.flipBy180DegreeRotation) {
 				skeletonUtility.flipBy180DegreeRotation = true;

+ 1 - 1
spine-unity/Assets/Spine/package.json

@@ -2,7 +2,7 @@
 	"name": "com.esotericsoftware.spine.spine-unity",
 	"displayName": "spine-unity Runtime",
 	"description": "This plugin provides the spine-unity runtime core.",
-	"version": "4.2.100",
+	"version": "4.2.101",
 	"unity": "2018.3",
 	"author": {
 		"name": "Esoteric Software",