diff --git a/CHANGELOG.md b/CHANGELOG.md
index d311f2ce1..33ccaf835 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -53,14 +53,15 @@
* Added `Animation Update` mode (called `UpdateTiming` in code) `In Late Update` for `SkeletonAnimation`, `SkeletonMecanim` and `SkeletonGraphic`. This allows you to update the `SkeletonMecanim` skeleton in the same frame that the Mecanim Animator updated its state, which happens between `Update` and `LateUpdate`.
* URP Shaders: Added URP "Blend Mode" shader variants for both URP 3D and URP 2D renderers. They are listed under shader name "Universal Render Pipeline/Spine/Blend Modes/" and "Universal Render Pipeline/2D/Spine/Blend Modes/" respectively.
* URP Shaders: Added support for [Tint Black](http://en.esotericsoftware.com/spine-slots#Tint-black) functionality at "Blend Modes" Spine URP shaders (2D and 3D shaders).
- * PhysicsConstraints: Skeleton GameObjects now automatically apply Transform translation and rotation to the skeleton's `PhysicsConstraints`. You can disable applying translation or rotation at the Skeleton component Inspector under `Advanced - Physics Constraints` `Transform Translation` and `Transform Rotation`, or by setting the properties `applyTranslationToPhysics` and `applyRotationToPhysics` at the skeleton component via code.
+ * PhysicsConstraints: Skeleton GameObjects now automatically apply Transform translation and rotation to the skeleton's `PhysicsConstraints`. You can disable applying translation or rotation at the Skeleton component Inspector under `Advanced - Physics Inheritance` by setting `Position` to (0,0)and `Rotation` to 0, or by setting the properties `physicsPositionInheritanceFactor` to `Vector2.zero` and `physicsRotationInheritanceFactor` to `0` at the skeleton component via code.
* Added `Physics Constraints` example scene (located in `Spine Examples/Other Examples`) together with `celestial-circus` example skeleton assets. This scene demonstrates Transform movement automatically affecting physics constraints of a skeleton.
- * PhysicsConstraints: Skeleton components now allow you to use relative instead of world-space Transform movement (with `applyTranslationToPhysics` and `applyRotationToPhysics`) by assigning a Transform (typically the parent) to the new `Movement relative to` property. Leave this property at `null` (the default) to use world-space Transform movement for physics.
-
+ * PhysicsConstraints: Skeleton components now allow you to use relative instead of world-space Transform movement by assigning a Transform (typically the parent) to the new `Movement relative to` property. Leave this property at `null` (the default) to use world-space Transform movement for physics.
+
* **Breaking changes**
* Changed `SpineShaderWithOutlineGUI` outline related methods from `private` to `protected virtual` to allow for custom shader GUI subclasses to switch to different outline shaders.
* Changed `BoneFollower` and `BoneFollowerGraphic` methods `LateUpdate` and `Initialize` to `virtual` to allow easier overriding for e.g. positional offset in custom subclasses.
* `MeshGenerator` received a new optimization option to avoid rendering fully transparent attachments at slot alpha 0 by default. Comment out `#define SLOT_ALPHA_DISABLES_ATTACHMENT` in `MeshGenerator.cs` to revert to previous behaviour. You may only need this option disabled when utilizing a custom shader which uses vertex color alpha for purposes other than transparency.
+ * PhysicsConstraints: bool properties `ApplyTranslationToPhysics` and `ApplyRotationToPhysics` were changed to `Vector2 PhysicsPositionInheritanceFactor` and `float PhysicsRotationInheritanceFactor` to allow the Transform movement the be scaled by a factor before being applied to the skeleton. You can set the properties to `Vector2.zero` and `0` respectively to disable applying any Transform movement at all. The `Advanced` Inspector section `Physics Constraints` was renamed to `Physics Inheritance`, the properties in the section are now called `Position` and `Rotation`.
* **Changes of default values**
diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Components/SkeletonGraphicInspector.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Components/SkeletonGraphicInspector.cs
index 137cb1b47..86feac1ff 100644
--- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Components/SkeletonGraphicInspector.cs
+++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Components/SkeletonGraphicInspector.cs
@@ -62,7 +62,7 @@ namespace Spine.Unity.Editor {
SerializedProperty skeletonDataAsset, initialSkinName;
SerializedProperty startingAnimation, startingLoop, timeScale, freeze,
updateTiming, updateWhenInvisible, unscaledTime, tintBlack, layoutScaleMode, editReferenceRect;
- SerializedProperty applyTranslationToPhysics, applyRotationToPhysics, physicsMovementRelativeTo;
+ SerializedProperty physicsPositionInheritanceFactor, physicsRotationInheritanceFactor, physicsMovementRelativeTo;
SerializedProperty initialFlipX, initialFlipY;
SerializedProperty meshGeneratorSettings;
SerializedProperty allowMultipleCanvasRenderers, separatorSlotNames, enableSeparatorSlots,
@@ -73,10 +73,20 @@ namespace Spine.Unity.Editor {
"If enabled, AnimationState uses unscaled game time (Time.unscaledDeltaTime), " +
"running animations independent of e.g. game pause (Time.timeScale). " +
"Instance SkeletonAnimation.timeScale will still be applied.");
- readonly GUIContent ApplyTranslationToPhysicsLabel = new GUIContent("Transform Translation",
- "When enabled, the GameObject Transform translation movement is applied to PhysicsConstraints of the skeleton.");
- readonly GUIContent ApplyRotationToPhysicsLabel = new GUIContent("Transform Rotation",
- "When enabled, the GameObject Transform rotation movement is applied to PhysicsConstraints of the skeleton.");
+ readonly GUIContent PhysicsPositionInheritanceFactorLabel = new GUIContent("Position",
+ "When set to non-zero, Transform position movement in X and Y direction is applied to skeleton " +
+ "PhysicsConstraints, multiplied by these " +
+ "\nX and Y scale factors to the right. Typical values are " +
+ "\n(1,1) to apply XY movement normally, " +
+ "\n(2,2) to apply movement with double intensity, " +
+ "\n(1,0) to apply only horizontal movement, or" +
+ "\n(0,0) to not apply any Transform position movement at all.");
+ readonly GUIContent PhysicsRotationInheritanceFactorLabel = new GUIContent("Rotation",
+ "When set to non-zero, Transform rotation movement is applied to skeleton PhysicsConstraints, " +
+ "multiplied by this scale factor to the right. Typical values are " +
+ "\n1 to apply movement normally, " +
+ "\n2 to apply movement with double intensity, or " +
+ "\n0 to not apply any Transform rotation movement at all.");
readonly GUIContent PhysicsMovementRelativeToLabel = new GUIContent("Movement relative to",
"Reference transform relative to which physics movement will be calculated, or null to use world location.");
@@ -143,8 +153,8 @@ namespace Spine.Unity.Editor {
updateWhenInvisible = so.FindProperty("updateWhenInvisible");
layoutScaleMode = so.FindProperty("layoutScaleMode");
editReferenceRect = so.FindProperty("editReferenceRect");
- applyTranslationToPhysics = so.FindProperty("applyTranslationToPhysics");
- applyRotationToPhysics = so.FindProperty("applyRotationToPhysics");
+ physicsPositionInheritanceFactor = so.FindProperty("physicsPositionInheritanceFactor");
+ physicsRotationInheritanceFactor = so.FindProperty("physicsRotationInheritanceFactor");
physicsMovementRelativeTo = so.FindProperty("physicsMovementRelativeTo");
meshGeneratorSettings = so.FindProperty("meshGenerator").FindPropertyRelative("settings");
@@ -320,9 +330,16 @@ namespace Spine.Unity.Editor {
EditorGUILayout.Space();
using (new SpineInspectorUtility.LabelWidthScope()) {
- EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Physics Constraints", SpineEditorUtilities.Icons.constraintPhysics), EditorStyles.boldLabel);
- EditorGUILayout.PropertyField(applyTranslationToPhysics, ApplyTranslationToPhysicsLabel);
- EditorGUILayout.PropertyField(applyRotationToPhysics, ApplyRotationToPhysicsLabel);
+ EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Physics Inheritance", SpineEditorUtilities.Icons.constraintPhysics), EditorStyles.boldLabel);
+
+ using (new GUILayout.HorizontalScope()) {
+ EditorGUILayout.LabelField(PhysicsPositionInheritanceFactorLabel, GUILayout.Width(EditorGUIUtility.labelWidth));
+ int savedIndentLevel = EditorGUI.indentLevel;
+ EditorGUI.indentLevel = 0;
+ EditorGUILayout.PropertyField(physicsPositionInheritanceFactor, GUIContent.none, GUILayout.MinWidth(60));
+ EditorGUI.indentLevel = savedIndentLevel;
+ }
+ EditorGUILayout.PropertyField(physicsRotationInheritanceFactor, PhysicsRotationInheritanceFactorLabel);
EditorGUILayout.PropertyField(physicsMovementRelativeTo, PhysicsMovementRelativeToLabel);
}
}
diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Components/SkeletonRendererInspector.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Components/SkeletonRendererInspector.cs
index 91026d36b..e69c4bf16 100644
--- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Components/SkeletonRendererInspector.cs
+++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Components/SkeletonRendererInspector.cs
@@ -68,7 +68,7 @@ namespace Spine.Unity.Editor {
protected SerializedProperty normals, tangents, zSpacing, pmaVertexColors, tintBlack; // MeshGenerator settings
protected SerializedProperty maskInteraction;
protected SerializedProperty maskMaterialsNone, maskMaterialsInside, maskMaterialsOutside;
- protected SerializedProperty applyTranslationToPhysics, applyRotationToPhysics, physicsMovementRelativeTo;
+ protected SerializedProperty physicsPositionInheritanceFactor, physicsRotationInheritanceFactor, physicsMovementRelativeTo;
protected SpineInspectorUtility.SerializedSortingProperties sortingProperties;
protected bool wasInitParameterChanged = false;
protected bool requireRepaint = false;
@@ -88,10 +88,20 @@ namespace Spine.Unity.Editor {
protected GUIContent MaskMaterialsHeadingLabel, MaskMaterialsNoneLabel, MaskMaterialsInsideLabel, MaskMaterialsOutsideLabel;
protected GUIContent SetMaterialButtonLabel, ClearMaterialButtonLabel, DeleteMaterialButtonLabel;
- readonly GUIContent ApplyTranslationToPhysicsLabel = new GUIContent("Transform Translation",
- "When enabled, the GameObject Transform translation movement is applied to PhysicsConstraints of the skeleton.");
- readonly GUIContent ApplyRotationToPhysicsLabel = new GUIContent("Transform Rotation",
- "When enabled, the GameObject Transform rotation movement is applied to PhysicsConstraints of the skeleton.");
+ readonly GUIContent PhysicsPositionInheritanceFactorLabel = new GUIContent("Position",
+ "When set to non-zero, Transform position movement in X and Y direction is applied to skeleton " +
+ "PhysicsConstraints, multiplied by these " +
+ "\nX and Y scale factors to the right. Typical values are " +
+ "\n(1,1) to apply XY movement normally, " +
+ "\n(2,2) to apply movement with double intensity, " +
+ "\n(1,0) to apply only horizontal movement, or" +
+ "\n(0,0) to not apply any Transform position movement at all.");
+ readonly GUIContent PhysicsRotationInheritanceFactorLabel = new GUIContent("Rotation",
+ "When set to non-zero, Transform rotation movement is applied to skeleton PhysicsConstraints, " +
+ "multiplied by this scale factor to the right. Typical values are " +
+ "\n1 to apply movement normally, " +
+ "\n2 to apply movement with double intensity, or " +
+ "\n0 to not apply any Transform rotation movement at all.");
readonly GUIContent PhysicsMovementRelativeToLabel = new GUIContent("Movement relative to",
"Reference transform relative to which physics movement will be calculated, or null to use world location.");
@@ -169,8 +179,8 @@ namespace Spine.Unity.Editor {
maskMaterialsNone = so.FindProperty("maskMaterials.materialsMaskDisabled");
maskMaterialsInside = so.FindProperty("maskMaterials.materialsInsideMask");
maskMaterialsOutside = so.FindProperty("maskMaterials.materialsOutsideMask");
- applyTranslationToPhysics = so.FindProperty("applyTranslationToPhysics");
- applyRotationToPhysics = so.FindProperty("applyRotationToPhysics");
+ physicsPositionInheritanceFactor = so.FindProperty("physicsPositionInheritanceFactor");
+ physicsRotationInheritanceFactor = so.FindProperty("physicsRotationInheritanceFactor");
physicsMovementRelativeTo = so.FindProperty("physicsMovementRelativeTo");
separatorSlotNames = so.FindProperty("separatorSlotNames");
@@ -418,9 +428,16 @@ namespace Spine.Unity.Editor {
}
#endif
using (new SpineInspectorUtility.LabelWidthScope()) {
- EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Physics Constraints", SpineEditorUtilities.Icons.constraintPhysics), EditorStyles.boldLabel);
- EditorGUILayout.PropertyField(applyTranslationToPhysics, ApplyTranslationToPhysicsLabel);
- EditorGUILayout.PropertyField(applyRotationToPhysics, ApplyRotationToPhysicsLabel);
+ EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Physics Inheritance", SpineEditorUtilities.Icons.constraintPhysics), EditorStyles.boldLabel);
+
+ using (new GUILayout.HorizontalScope()) {
+ EditorGUILayout.LabelField(PhysicsPositionInheritanceFactorLabel, GUILayout.Width(EditorGUIUtility.labelWidth));
+ int savedIndentLevel = EditorGUI.indentLevel;
+ EditorGUI.indentLevel = 0;
+ EditorGUILayout.PropertyField(physicsPositionInheritanceFactor, GUIContent.none, GUILayout.MinWidth(60));
+ EditorGUI.indentLevel = savedIndentLevel;
+ }
+ EditorGUILayout.PropertyField(physicsRotationInheritanceFactor, PhysicsRotationInheritanceFactorLabel);
EditorGUILayout.PropertyField(physicsMovementRelativeTo, PhysicsMovementRelativeToLabel);
}
diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonGraphic.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonGraphic.cs
index 60e5edbc5..9faaddafb 100644
--- a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonGraphic.cs
+++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonGraphic.cs
@@ -391,21 +391,22 @@ namespace Spine.Unity {
public virtual void ApplyTransformMovementToPhysics () {
if (Application.isPlaying) {
- if (applyTranslationToPhysics) {
+ if (physicsPositionInheritanceFactor != Vector2.zero) {
Vector2 position = GetPhysicsTransformPosition();
Vector2 positionDelta = (position - lastPosition) / meshScale;
if (physicsMovementRelativeTo != null) {
positionDelta.x *= physicsMovementRelativeTo.lossyScale.x;
positionDelta.y *= physicsMovementRelativeTo.lossyScale.y;
}
- positionDelta.x /= transform.lossyScale.x;
- positionDelta.y /= transform.lossyScale.y;
+ positionDelta.x *= physicsPositionInheritanceFactor.x / transform.lossyScale.x;
+ positionDelta.y *= physicsPositionInheritanceFactor.y / transform.lossyScale.y;
+
skeleton.PhysicsTranslate(positionDelta.x, positionDelta.y);
lastPosition = position;
}
- if (applyRotationToPhysics) {
+ if (physicsRotationInheritanceFactor != 0f) {
float rotation = GetPhysicsTransformRotation();
- skeleton.PhysicsRotate(0, 0, rotation - lastRotation);
+ skeleton.PhysicsRotate(0, 0, physicsRotationInheritanceFactor * (rotation - lastRotation));
lastRotation = rotation;
}
}
@@ -567,10 +568,10 @@ namespace Spine.Unity {
}
}
- /// When enabled, Transform translation is applied to skeleton PhysicsConstraints.
- [SerializeField] protected bool applyTranslationToPhysics = true;
- /// When enabled, Transform rotation is applied to skeleton PhysicsConstraints.
- [SerializeField] protected bool applyRotationToPhysics = true;
+ ///
+ [SerializeField] protected Vector2 physicsPositionInheritanceFactor = Vector2.one;
+ ///
+ [SerializeField] protected float physicsRotationInheritanceFactor = 1.0f;
/// Reference transform relative to which physics movement will be calculated, or null to use world location.
[SerializeField] protected Transform physicsMovementRelativeTo = null;
@@ -579,25 +580,33 @@ namespace Spine.Unity {
/// Used for applying Transform rotation to skeleton PhysicsConstraints.
protected float lastRotation;
- /// When enabled, Transform translation is applied to skeleton PhysicsConstraints.
- public bool ApplyTranslationToPhysics {
+ /// When set to non-zero, Transform position movement in X and Y direction
+ /// is applied to skeleton PhysicsConstraints, multiplied by this scale factor.
+ /// Typical values are Vector2.one to apply XY movement 1:1,
+ /// Vector2(2f, 2f) to apply movement with double intensity,
+ /// Vector2(1f, 0f) to apply only horizontal movement, or
+ /// Vector2.zero to not apply any Transform position movement at all.
+ public Vector2 PhysicsPositionInheritanceFactor {
get {
- return applyTranslationToPhysics;
+ return physicsPositionInheritanceFactor;
}
set {
- if (value && !applyTranslationToPhysics) ResetLastPosition();
- applyTranslationToPhysics = value;
+ if (physicsPositionInheritanceFactor == Vector2.zero && value != Vector2.zero) ResetLastPosition();
+ physicsPositionInheritanceFactor = value;
}
}
- /// When enabled, Transform rotation is applied to skeleton PhysicsConstraints.
- public bool ApplyRotationToPhysics {
+ /// When set to non-zero, Transform rotation movement is applied to skeleton PhysicsConstraints,
+ /// multiplied by this scale factor. Typical values are 1 to apply movement 1:1,
+ /// 2 to apply movement with double intensity, or
+ /// 0 to not apply any Transform rotation movement at all.
+ public float PhysicsRotationInheritanceFactor {
get {
- return applyRotationToPhysics;
+ return physicsRotationInheritanceFactor;
}
set {
- if (value && !applyRotationToPhysics) ResetLastRotation();
- applyRotationToPhysics = value;
+ if (physicsRotationInheritanceFactor == 0f && value != 0f) ResetLastRotation();
+ physicsRotationInheritanceFactor = value;
}
}
@@ -608,8 +617,8 @@ namespace Spine.Unity {
}
set {
physicsMovementRelativeTo = value;
- if (applyTranslationToPhysics) ResetLastPosition();
- if (applyRotationToPhysics) ResetLastRotation();
+ if (physicsPositionInheritanceFactor != Vector2.zero) ResetLastPosition();
+ if (physicsRotationInheritanceFactor != 0f) ResetLastRotation();
}
}
diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs
index 41ee7ecd3..0fe7adae3 100644
--- a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs
+++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs
@@ -289,10 +289,10 @@ namespace Spine.Unity {
#endregion
#region Physics
- /// When enabled, Transform translation is applied to skeleton PhysicsConstraints.
- [SerializeField] protected bool applyTranslationToPhysics = true;
- /// When enabled, Transform rotation is applied to skeleton PhysicsConstraints.
- [SerializeField] protected bool applyRotationToPhysics = true;
+ ///
+ [SerializeField] protected Vector2 physicsPositionInheritanceFactor = Vector2.one;
+ ///
+ [SerializeField] protected float physicsRotationInheritanceFactor = 1.0f;
/// Reference transform relative to which physics movement will be calculated, or null to use world location.
[SerializeField] protected Transform physicsMovementRelativeTo = null;
@@ -301,25 +301,33 @@ namespace Spine.Unity {
/// Used for applying Transform rotation to skeleton PhysicsConstraints.
protected float lastRotation;
- /// When enabled, Transform translation is applied to skeleton PhysicsConstraints.
- public bool ApplyTranslationToPhysics {
+ /// When set to non-zero, Transform position movement in X and Y direction
+ /// is applied to skeleton PhysicsConstraints, multiplied by this scale factor.
+ /// Typical values are Vector2.one to apply XY movement 1:1,
+ /// Vector2(2f, 2f) to apply movement with double intensity,
+ /// Vector2(1f, 0f) to apply only horizontal movement, or
+ /// Vector2.zero to not apply any Transform position movement at all.
+ public Vector2 PhysicsPositionInheritanceFactor {
get {
- return applyTranslationToPhysics;
+ return physicsPositionInheritanceFactor;
}
set {
- if (value && !applyTranslationToPhysics) ResetLastPosition();
- applyTranslationToPhysics = value;
+ if (physicsPositionInheritanceFactor == Vector2.zero && value != Vector2.zero) ResetLastPosition();
+ physicsPositionInheritanceFactor = value;
}
}
- /// When enabled, Transform rotation is applied to skeleton PhysicsConstraints.
- public bool ApplyRotationToPhysics {
+ /// When set to non-zero, Transform rotation movement is applied to skeleton PhysicsConstraints,
+ /// multiplied by this scale factor. Typical values are 1 to apply movement 1:1,
+ /// 2 to apply movement with double intensity, or
+ /// 0 to not apply any Transform rotation movement at all.
+ public float PhysicsRotationInheritanceFactor {
get {
- return applyRotationToPhysics;
+ return physicsRotationInheritanceFactor;
}
set {
- if (value && !applyRotationToPhysics) ResetLastRotation();
- applyRotationToPhysics = value;
+ if (physicsRotationInheritanceFactor == 0f && value != 0f) ResetLastRotation();
+ physicsRotationInheritanceFactor = value;
}
}
@@ -330,8 +338,8 @@ namespace Spine.Unity {
}
set {
physicsMovementRelativeTo = value;
- if (applyTranslationToPhysics) ResetLastPosition();
- if (applyRotationToPhysics) ResetLastRotation();
+ if (physicsPositionInheritanceFactor != Vector2.zero) ResetLastPosition();
+ if (physicsRotationInheritanceFactor != 0f) ResetLastRotation();
}
}
@@ -504,21 +512,21 @@ namespace Spine.Unity {
public virtual void ApplyTransformMovementToPhysics () {
if (Application.isPlaying) {
- if (applyTranslationToPhysics) {
+ if (physicsPositionInheritanceFactor != Vector2.zero) {
Vector2 position = GetPhysicsTransformPosition();
Vector2 positionDelta = position - lastPosition;
if (physicsMovementRelativeTo != null) {
positionDelta.x *= physicsMovementRelativeTo.lossyScale.x;
positionDelta.y *= physicsMovementRelativeTo.lossyScale.y;
}
- positionDelta.x /= transform.lossyScale.x;
- positionDelta.y /= transform.lossyScale.y;
+ positionDelta.x *= physicsPositionInheritanceFactor.x / transform.lossyScale.x;
+ positionDelta.y *= physicsPositionInheritanceFactor.y / transform.lossyScale.y;
skeleton.PhysicsTranslate(positionDelta.x, positionDelta.y);
lastPosition = position;
}
- if (applyRotationToPhysics) {
+ if (physicsRotationInheritanceFactor != 0f) {
float rotation = GetPhysicsTransformRotation();
- skeleton.PhysicsRotate(0, 0, rotation - lastRotation);
+ skeleton.PhysicsRotate(0, 0, physicsRotationInheritanceFactor * (rotation - lastRotation));
lastRotation = rotation;
}
}