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

This commit is contained in:
Harald Csaszar 2025-04-23 21:30:50 +02:00
parent 3f65213f70
commit d7f3ab4723
2 changed files with 89 additions and 55 deletions

View File

@ -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;
rootFollowerKinematic.AddComponent<FollowLocationRigidbody2D>().reference = kinematicParentUtilityBone.transform;
rootFollowerKinematic.transform.position = kinematicParentUtilityBone.transform.position;
rootFollowerKinematic.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;
}
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;
rootFollowerKinematic.AddComponent<FollowLocationRigidbody>().reference = kinematicParentUtilityBone.transform;
rootFollowerKinematic.transform.position = kinematicParentUtilityBone.transform.position;
rootFollowerKinematic.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;
CreateHingeChain(utilityBone, mass, rotationLimit, chainParentObject.transform, rootFollowerKinematic.transform);
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;
}
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;

View File

@ -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",