2024-10-29 15:22:32 +08:00
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Spine Runtimes License Agreement
2024-11-21 09:35:48 +08:00
* Last updated July 28 , 2023. Replaces all prior versions .
2024-10-29 15:22:32 +08:00
*
2024-11-21 09:35:48 +08:00
* Copyright ( c ) 2013 - 2023 , Esoteric Software LLC
2024-10-29 15:22:32 +08:00
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement :
* http : //esotericsoftware.com/spine-editor-license
*
2024-11-21 09:35:48 +08:00
* Otherwise , it is permitted to integrate the Spine Runtimes into software or
* otherwise create derivative works of the Spine Runtimes ( collectively ,
2024-10-29 15:22:32 +08:00
* "Products" ) , provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice .
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
* ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ,
* BUSINESS INTERRUPTION , OR LOSS OF USE , DATA , OR PROFITS ) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
2024-11-21 09:35:48 +08:00
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THE
* SPINE RUNTIMES , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
2024-10-29 15:22:32 +08:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
using System.Collections.Generic ;
2024-11-21 09:35:48 +08:00
using UnityEngine ;
2024-10-29 15:22:32 +08:00
namespace Spine.Unity.Examples {
// SkeletonUtilityKinematicShadow allows hinge chains to inherit a velocity interpreted from changes in parent transform position or from unrelated rigidbodies.
// Note: Uncheck "useRootTransformIfNull
public class SkeletonUtilityKinematicShadow : MonoBehaviour {
#region Inspector
[Tooltip("If checked, the hinge chain can inherit your root transform's velocity or position/rotation changes.")]
public bool detachedShadow = false ;
public Transform parent ;
public bool hideShadow = true ;
public PhysicsSystem physicsSystem = PhysicsSystem . Physics3D ;
#endregion
GameObject shadowRoot ;
readonly List < TransformPair > shadowTable = new List < TransformPair > ( ) ;
struct TransformPair {
public Transform dest , src ;
}
public enum PhysicsSystem {
Physics2D ,
Physics3D
} ;
void Start ( ) {
// Duplicate this gameObject as the "shadow" with a different parent.
shadowRoot = Instantiate < GameObject > ( this . gameObject ) ;
Destroy ( shadowRoot . GetComponent < SkeletonUtilityKinematicShadow > ( ) ) ;
// Prepare shadow gameObject's properties.
2024-11-21 09:35:48 +08:00
Transform shadowRootTransform = shadowRoot . transform ;
2024-10-29 15:22:32 +08:00
shadowRootTransform . position = transform . position ;
shadowRootTransform . rotation = transform . rotation ;
Vector3 scaleRef = transform . TransformPoint ( Vector3 . right ) ;
float scale = Vector3 . Distance ( transform . position , scaleRef ) ;
shadowRootTransform . localScale = Vector3 . one ;
if ( ! detachedShadow ) {
// Do not change to null coalescing operator (??). Unity overloads null checks for UnityEngine.Objects but not the ?? operator.
if ( parent = = null )
shadowRootTransform . parent = transform . root ;
else
shadowRootTransform . parent = parent ;
}
if ( hideShadow )
shadowRoot . hideFlags = HideFlags . HideInHierarchy ;
2024-11-21 09:35:48 +08:00
Joint [ ] shadowJoints = shadowRoot . GetComponentsInChildren < Joint > ( ) ;
2024-10-29 15:22:32 +08:00
foreach ( Joint j in shadowJoints )
j . connectedAnchor * = scale ;
// Build list of bone pairs (matches shadow transforms with bone transforms)
2024-11-21 09:35:48 +08:00
SkeletonUtilityBone [ ] bones = GetComponentsInChildren < SkeletonUtilityBone > ( ) ;
SkeletonUtilityBone [ ] shadowBones = shadowRoot . GetComponentsInChildren < SkeletonUtilityBone > ( ) ;
foreach ( SkeletonUtilityBone b in bones ) {
2024-10-29 15:22:32 +08:00
if ( b . gameObject = = this . gameObject )
continue ;
System . Type checkType = ( physicsSystem = = PhysicsSystem . Physics2D ) ? typeof ( Rigidbody2D ) : typeof ( Rigidbody ) ;
2024-11-21 09:35:48 +08:00
foreach ( SkeletonUtilityBone sb in shadowBones ) {
2024-10-29 15:22:32 +08:00
if ( sb . GetComponent ( checkType ) ! = null & & sb . boneName = = b . boneName ) {
shadowTable . Add ( new TransformPair {
dest = b . transform ,
src = sb . transform
} ) ;
break ;
}
}
}
// Destroy conflicting and unneeded components
DestroyComponents ( shadowBones ) ;
DestroyComponents ( GetComponentsInChildren < Joint > ( ) ) ;
DestroyComponents ( GetComponentsInChildren < Rigidbody > ( ) ) ;
DestroyComponents ( GetComponentsInChildren < Collider > ( ) ) ;
}
static void DestroyComponents ( Component [ ] components ) {
for ( int i = 0 , n = components . Length ; i < n ; i + + )
Destroy ( components [ i ] ) ;
}
void FixedUpdate ( ) {
if ( physicsSystem = = PhysicsSystem . Physics2D ) {
2024-11-21 09:35:48 +08:00
Rigidbody2D shadowRootRigidbody = shadowRoot . GetComponent < Rigidbody2D > ( ) ;
2024-10-29 15:22:32 +08:00
shadowRootRigidbody . MovePosition ( transform . position ) ;
shadowRootRigidbody . MoveRotation ( transform . rotation . eulerAngles . z ) ;
} else {
2024-11-21 09:35:48 +08:00
Rigidbody shadowRootRigidbody = shadowRoot . GetComponent < Rigidbody > ( ) ;
2024-10-29 15:22:32 +08:00
shadowRootRigidbody . MovePosition ( transform . position ) ;
shadowRootRigidbody . MoveRotation ( transform . rotation ) ;
}
for ( int i = 0 , n = shadowTable . Count ; i < n ; i + + ) {
2024-11-21 09:35:48 +08:00
TransformPair pair = shadowTable [ i ] ;
2024-10-29 15:22:32 +08:00
pair . dest . localPosition = pair . src . localPosition ;
pair . dest . localRotation = pair . src . localRotation ;
}
}
}
}