浏览代码

[unity] Fixed SkeletonMecanim blend result weights at mode `MixNext`, no longer bahaving unexpectedly. At additive layers, `MixMode.MixNext` is always set to `MixMode.AlwaysMix` since `MixNext` makes no sense there. Closes #1718.

Harald Csaszar 5 年之前
父节点
当前提交
7626f3b58a
共有 1 个文件被更改,包括 25 次插入16 次删除
  1. 25 16
      spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonMecanim.cs

+ 25 - 16
spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonMecanim.cs

@@ -198,7 +198,7 @@ namespace Spine.Unity {
 			}
 			}
 
 
 			private bool ApplyAnimation (Skeleton skeleton, AnimatorClipInfo info, AnimatorStateInfo stateInfo,
 			private bool ApplyAnimation (Skeleton skeleton, AnimatorClipInfo info, AnimatorStateInfo stateInfo,
-										int layerIndex, float layerWeight, MixBlend layerBlendMode, bool useWeight1 = false) {
+										int layerIndex, float layerWeight, MixBlend layerBlendMode, bool useClipWeight1 = false) {
 				float weight = info.weight * layerWeight;
 				float weight = info.weight * layerWeight;
 				if (weight == 0)
 				if (weight == 0)
 					return false;
 					return false;
@@ -209,7 +209,7 @@ namespace Spine.Unity {
 
 
 				var time = AnimationTime(stateInfo.normalizedTime, info.clip.length,
 				var time = AnimationTime(stateInfo.normalizedTime, info.clip.length,
 										info.clip.isLooping, stateInfo.speed < 0);
 										info.clip.isLooping, stateInfo.speed < 0);
-				weight = useWeight1 ? 1.0f : weight;
+				weight = useClipWeight1 ? layerWeight : weight;
 				clip.Apply(skeleton, 0, time, info.clip.isLooping, null,
 				clip.Apply(skeleton, 0, time, info.clip.isLooping, null,
 						weight, layerBlendMode, MixDirection.In);
 						weight, layerBlendMode, MixDirection.In);
 				if (_OnClipApplied != null)
 				if (_OnClipApplied != null)
@@ -220,7 +220,7 @@ namespace Spine.Unity {
 			private bool ApplyInterruptionAnimation (Skeleton skeleton,
 			private bool ApplyInterruptionAnimation (Skeleton skeleton,
 				bool interpolateWeightTo1, AnimatorClipInfo info, AnimatorStateInfo stateInfo,
 				bool interpolateWeightTo1, AnimatorClipInfo info, AnimatorStateInfo stateInfo,
 				int layerIndex, float layerWeight, MixBlend layerBlendMode, float interruptingClipTimeAddition,
 				int layerIndex, float layerWeight, MixBlend layerBlendMode, float interruptingClipTimeAddition,
-				bool useWeight1 = false) {
+				bool useClipWeight1 = false) {
 
 
 				float clipWeight = interpolateWeightTo1 ? (info.weight + 1.0f) * 0.5f : info.weight;
 				float clipWeight = interpolateWeightTo1 ? (info.weight + 1.0f) * 0.5f : info.weight;
 				float weight = clipWeight * layerWeight;
 				float weight = clipWeight * layerWeight;
@@ -233,7 +233,7 @@ namespace Spine.Unity {
 
 
 				var time = AnimationTime(stateInfo.normalizedTime + interruptingClipTimeAddition,
 				var time = AnimationTime(stateInfo.normalizedTime + interruptingClipTimeAddition,
 										info.clip.length, stateInfo.speed < 0);
 										info.clip.length, stateInfo.speed < 0);
-				weight = useWeight1 ? 1.0f : weight;
+				weight = useClipWeight1 ? layerWeight : weight;
 				clip.Apply(skeleton, 0, time, info.clip.isLooping, null,
 				clip.Apply(skeleton, 0, time, info.clip.isLooping, null,
 							weight, layerBlendMode, MixDirection.In);
 							weight, layerBlendMode, MixDirection.In);
 				if (_OnClipApplied != null) {
 				if (_OnClipApplied != null) {
@@ -256,26 +256,28 @@ namespace Spine.Unity {
 			}
 			}
 
 
 			public void Apply (Skeleton skeleton) {
 			public void Apply (Skeleton skeleton) {
+			#if UNITY_EDITOR
+				if (!Application.isPlaying) {
+					GetLayerBlendModes();
+				}
+			#endif
+
 				if (layerMixModes.Length < animator.layerCount) {
 				if (layerMixModes.Length < animator.layerCount) {
 					int oldSize = layerMixModes.Length;
 					int oldSize = layerMixModes.Length;
 					System.Array.Resize<MixMode>(ref layerMixModes, animator.layerCount);
 					System.Array.Resize<MixMode>(ref layerMixModes, animator.layerCount);
 					for (int layer = oldSize; layer < animator.layerCount; ++layer) {
 					for (int layer = oldSize; layer < animator.layerCount; ++layer) {
-						layerMixModes[layer] = layer == 0 ? MixMode.MixNext : MixMode.AlwaysMix;
+						bool isAdditiveLayer = false;
+						if (layer < layerBlendModes.Length)
+							isAdditiveLayer = layerBlendModes[layer] == MixBlend.Add;
+						layerMixModes[layer] = isAdditiveLayer ? MixMode.MixNext : MixMode.AlwaysMix;
 					}
 					}
 				}
 				}
 
 
-			#if UNITY_EDITOR
-				if (!Application.isPlaying) {
-					GetLayerBlendModes();
-				}
-			#endif
 				InitClipInfosForLayers();
 				InitClipInfosForLayers();
 				for (int layer = 0, n = animator.layerCount; layer < n; layer++) {
 				for (int layer = 0, n = animator.layerCount; layer < n; layer++) {
 					GetStateUpdatesFromAnimator(layer);
 					GetStateUpdatesFromAnimator(layer);
 				}
 				}
 
 
-				//skeleton.Update(Time.deltaTime); // Doesn't actually do anything, currently. (Spine 3.6).
-
 				// Clear Previous
 				// Clear Previous
 				if (autoReset) {
 				if (autoReset) {
 					var previousAnimations = this.previousAnimations;
 					var previousAnimations = this.previousAnimations;
@@ -348,8 +350,15 @@ namespace Spine.Unity {
 					GetAnimatorClipInfos(layer, out isInterruptionActive, out clipInfoCount, out nextClipInfoCount, out interruptingClipInfoCount,
 					GetAnimatorClipInfos(layer, out isInterruptionActive, out clipInfoCount, out nextClipInfoCount, out interruptingClipInfoCount,
 										out clipInfo, out nextClipInfo, out interruptingClipInfo, out interpolateWeightTo1);
 										out clipInfo, out nextClipInfo, out interruptingClipInfo, out interpolateWeightTo1);
 
 
-					MixMode mode = layerMixModes[layer];
 					MixBlend layerBlendMode = (layer < layerBlendModes.Length) ? layerBlendModes[layer] : MixBlend.Replace;
 					MixBlend layerBlendMode = (layer < layerBlendModes.Length) ? layerBlendModes[layer] : MixBlend.Replace;
+					MixMode mode = layerMixModes[layer];
+					// Note: at additive blending it makes no sense to use constant weight 1 at a fadeout anim add1 as
+					// with override layers, so we use AlwaysMix instead to use the proper weights.
+					// AlwaysMix leads to the expected result = lower_layer + lerp(add1, add2, transition_weight).
+					if (layerBlendMode == MixBlend.Add && mode == MixMode.MixNext) {
+						mode = MixMode.AlwaysMix;
+						layerMixModes[layer] = mode;
+					}
 					if (mode == MixMode.AlwaysMix) {
 					if (mode == MixMode.AlwaysMix) {
 						// Always use Mix instead of Applying the first non-zero weighted clip.
 						// Always use Mix instead of Applying the first non-zero weighted clip.
 						for (int c = 0; c < clipInfoCount; c++) {
 						for (int c = 0; c < clipInfoCount; c++) {
@@ -372,7 +381,7 @@ namespace Spine.Unity {
 						// Apply first non-zero weighted clip
 						// Apply first non-zero weighted clip
 						int c = 0;
 						int c = 0;
 						for (; c < clipInfoCount; c++) {
 						for (; c < clipInfoCount; c++) {
-							if (!ApplyAnimation(skeleton, clipInfo[c], stateInfo, layer, layerWeight, layerBlendMode, useWeight1:true))
+							if (!ApplyAnimation(skeleton, clipInfo[c], stateInfo, layer, layerWeight, layerBlendMode, useClipWeight1:true))
 								continue;
 								continue;
 							++c; break;
 							++c; break;
 						}
 						}
@@ -386,7 +395,7 @@ namespace Spine.Unity {
 							// Apply next clip directly instead of mixing (ie: no crossfade, ignores mecanim transition weights)
 							// Apply next clip directly instead of mixing (ie: no crossfade, ignores mecanim transition weights)
 							if (mode == MixMode.Hard) {
 							if (mode == MixMode.Hard) {
 								for (; c < nextClipInfoCount; c++) {
 								for (; c < nextClipInfoCount; c++) {
-									if (!ApplyAnimation(skeleton, nextClipInfo[c], nextStateInfo, layer, layerWeight, layerBlendMode, useWeight1:true))
+									if (!ApplyAnimation(skeleton, nextClipInfo[c], nextStateInfo, layer, layerWeight, layerBlendMode, useClipWeight1:true))
 										continue;
 										continue;
 									++c; break;
 									++c; break;
 								}
 								}
@@ -405,7 +414,7 @@ namespace Spine.Unity {
 								for (; c < interruptingClipInfoCount; c++) {
 								for (; c < interruptingClipInfoCount; c++) {
 									if (ApplyInterruptionAnimation(skeleton, interpolateWeightTo1,
 									if (ApplyInterruptionAnimation(skeleton, interpolateWeightTo1,
 										interruptingClipInfo[c], interruptingStateInfo,
 										interruptingClipInfo[c], interruptingStateInfo,
-										layer, layerWeight, layerBlendMode, interruptingClipTimeAddition, useWeight1:true)) {
+										layer, layerWeight, layerBlendMode, interruptingClipTimeAddition, useClipWeight1:true)) {
 
 
 										++c; break;
 										++c; break;
 									}
 									}