123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- using Spine.Unity;
- using System;
- using UnityEngine;
- using XGame.Database;
- using XGame.Framework.Components;
- using XGame.Framework.Interfaces;
- using XGame.Framework.Time;
- namespace FL.Battle.Components
- {
- public interface ISpineContext
- {
- IEntity Entity { get; }
- SkeletonAnimation Skeleton { get; }
- ITimeModule Time { get; }
- }
- public class SpineComponent : Component<ISpineContext>, IAnimator, IReset
- {
- private ITimer _actionTimer;
- /// <summary>
- /// 触发器的定时器
- /// </summary>
- private ITimer _triggerTimer;
- protected override void OnDisable()
- {
- ClearTimers();
- }
- protected override void OnDispose()
- {
- ClearTimers();
- }
- private void ClearTimers()
- {
- _actionTimer?.Cancel();
- _actionTimer = null;
- _triggerTimer?.Cancel();
- _triggerTimer = null;
- }
- public bool IsLoop(EAnimationName actionName)
- {
- return actionName switch
- {
- EAnimationName.idle or EAnimationName.idle2 or EAnimationName.dizzy or EAnimationName.freeze or EAnimationName.palsy => true,
- _ => false,
- };
- }
- public void Play(EAnimationName aniName)
- {
- Play(new AnimationPlayArgs { aniName = aniName });
- }
- public void Play(AnimationPlayArgs args)
- {
- var skeleton = Context.Skeleton;
- if (skeleton == null)
- return;
- //if (_actionTimer != null)
- //{
- // Log.Debug($"Spine Name:{skeleton.name} Now:{skeleton.AnimationName} Next:{args.aniName}");
- //}
- var isLoop = IsLoop(args.aniName);
- skeleton.loop = isLoop;
- skeleton.AnimationName = args.aniName.ToString();
- //var state = skeleton.AnimationState;
- //state.Tracks.Items[0].Animation.Duration
- ClearTimers();
- var duration = skeleton.GetDurationMS();
- if (args.onTrigger != null && args.triggerFrame > 0 && args.triggerFrame < duration)
- {
- _triggerTimer = Context.Time.AddDelayTimer(args.triggerFrame, () =>
- {
- _triggerTimer = null;
- args.onTrigger.SafeInvoke();
- //try
- //{
- // args.onTrigger?.Invoke();
- //}
- //catch (Exception ex)
- //{
- // XGame.Log.Error($"SpineComponent onTrigger Exception Entity:{Context.Entity.EntityId} Name:{Context.Entity.Attr.Name}");
- // XGame.Log.Exception(ex);
- //}
- });
- }
- if (!isLoop)
- { // 非循环动作才有回调
- SetSkeletonFill(Color.yellow, 0.7f);
- //var startTime = Time.realtimeSinceStartup;
- _actionTimer = Context.Time.AddDelayTimer(duration, () =>
- {
- //Log.Debug($"SpineComponent Completed. Entity:{Context.Entity.EntityId} Name:{Context.Entity.Attr.Name} Frame:{Time.frameCount} duration:{duration} start:{startTime} used:{Time.realtimeSinceStartup - startTime}");
- SetSkeletonFill(Color.white, 0);
- _actionTimer = null;
- skeleton.loop = IsLoop(args.fallback);
- skeleton.AnimationName = args.fallback.ToString();
- args.onCompleted.SafeInvoke();
- //try
- //{
- // args.onCompleted?.Invoke();
- //}
- //catch (Exception ex)
- //{
- // XGame.Log.Error($"SpineComponent onCompleted Exception Entity:{Context.Entity.EntityId} Name:{Context.Entity.Attr.Name}");
- // XGame.Log.Exception(ex);
- //}
- });
- }
- //state.Complete += (_) =>
- //{
- // callback?.Invoke();
- //};
- }
- private MaterialPropertyBlock _mpb = new MaterialPropertyBlock();
- /// <summary>
- /// 设置spine的自定义颜色
- /// http://zh.esotericsoftware.com/spine-unity
- /// </summary>
- /// <param name="color"></param>
- /// <param name="phase"></param>
- private void SetSkeletonFill(Color color, float phase)
- {
- var renderer = Context.Skeleton.GetComponent<MeshRenderer>();
- if (renderer.sharedMaterial.shader.name != "Spine/Skeleton Fill")
- { // 该shader可自定义颜色叠加(color overlay)的Unlit 透明着色器. 不写 z-buffer. FillColor 决定叠加颜色, FillPhase 决定叠加强度.
- return;
- }
- //Log.Debug($"SetSkeletonFill color:{color} phase:{phase} Frame:{Time.frameCount}");
- _mpb.SetColor("_FillColor", color); // "_FillColor" is a named property on the used shader.
- _mpb.SetFloat("_FillPhase", phase); // "_FillPhase" is another named property on the used shader.
- renderer.SetPropertyBlock(_mpb);
- }
- void IReset.Reset()
- {
- ClearTimers();
- }
- //private void OnCompleted(TrackEntry trackEntry)
- //{
- //}
- }
- }
|