Harald đã viếtThis looks very nice!
Which version of Unity did you implement this for?
Would you be interested in contributing your code to Spine?
Unity 2018.3.
This is experimental code. I need more test.
It has some issues and not optimized yet.
public class CustomSpineAnimationMixerBehaviour : PlayableBehaviour
{
private const float FIRST_CLIP_BLEND_DURATION = 0.2f;
private const float FINAL_CLIP_BLEND_DURATION = 0.2f;
private SkeletonAnimation _trackBindingSkeletonAnimation;
private Skeleton _trackBindingSkeleton;
private TrackEntry _oldTrack;
private bool _firstFrameHappend;
public override void PrepareFrame(Playable playable, FrameData info)
{
if (_trackBindingSkeletonAnimation == null) return;
if (_trackBindingSkeleton == null) _trackBindingSkeleton = _trackBindingSkeletonAnimation.Skeleton;
int inputCount = playable.GetInputCount();
for (int i = 0; i < inputCount; i++)
{
ScriptPlayable<CustomSpineAnimationBehaviour> inputPlayable = (ScriptPlayable<CustomSpineAnimationBehaviour>)playable.GetInput(i);
CustomSpineAnimationBehaviour clipBehaviourData = inputPlayable.GetBehaviour();
clipBehaviourData.Init(_trackBindingSkeleton.Data);
if (clipBehaviourData.animation == null) continue;
//set key
clipBehaviourData.animation.SetKeyedItemsToSetupPose(_trackBindingSkeleton);
}
}
public override void ProcessFrame(Playable playable, FrameData info, object playerData)
{
_trackBindingSkeletonAnimation = playerData as SkeletonAnimation;
if (_trackBindingSkeletonAnimation == null) return;
if (_trackBindingSkeleton == null) _trackBindingSkeleton = _trackBindingSkeletonAnimation.Skeleton;
if (_firstFrameHappend == false)
{
_oldTrack = _trackBindingSkeletonAnimation.AnimationState?.GetCurrent(0);
_firstFrameHappend = true;
}
if (_oldTrack != null)
{
var playableTime = (float)playable.GetTime();
var playableDuration = (float)playable.GetGraph().GetRootPlayable(0).GetDuration();
var firstClipBlend = Mathf.Max(0, 1 - playableTime / FIRST_CLIP_BLEND_DURATION);
var finalClipBlend = Mathf.Max(0, 1 - (playableDuration - playableTime) / FINAL_CLIP_BLEND_DURATION);
_oldTrack.Alpha = firstClipBlend + finalClipBlend;
}
int inputCount = playable.GetInputCount();
int currentInputs = 0;
for (int i = 0; i < inputCount; i++)
{
//check weight
float inputWeight = playable.GetInputWeight(i);
if (Mathf.Approximately(inputWeight, 0f)) continue;
//check animation
ScriptPlayable<CustomSpineAnimationBehaviour> inputPlayable = (ScriptPlayable<CustomSpineAnimationBehaviour>)playable.GetInput(i);
CustomSpineAnimationBehaviour clipBehaviourData = inputPlayable.GetBehaviour();
clipBehaviourData.Init(_trackBindingSkeleton.Data);
if (clipBehaviourData.animation == null) continue;
//set animation
float time = clipBehaviourData.reverse ? (float)(inputPlayable.GetDuration() - inputPlayable.GetTime()) : (float)inputPlayable.GetTime();
MixBlend mixBlend = currentInputs == 0 ? MixBlend.Setup : MixBlend.First;
MixDirection mixDirection = inputWeight < 1 && currentInputs > 1 ? MixDirection.Out : MixDirection.In;
clipBehaviourData.animation.Apply(_trackBindingSkeleton, 0f, time, clipBehaviourData.loop, null, inputWeight, mixBlend, mixDirection);
currentInputs++;
}
_trackBindingSkeletonAnimation.Update(0);
_trackBindingSkeletonAnimation.LateUpdate();
}
public override void OnPlayableDestroy(Playable playable)
{
if (_trackBindingSkeleton != null) _trackBindingSkeleton.SetToSetupPose();
if (_trackBindingSkeletonAnimation != null) _trackBindingSkeletonAnimation.Update(0);
}
}
This is part of mixbehaviour class.
Is it possible to contribute my code?
(Sorry for my bad English grammer...)
bali33 đã viếtLooks great, congrats !
Do you plan to share by any chance ?
I hope so 🙂