using System; using System.ComponentModel; using System.Linq; using System.Threading.Tasks; using Castle.Core.Internal; using UnityEngine; using UnityEngine.Playables; using UnityEngine.Serialization; /// /// 挂在脚本,方便额外的处理 /// public enum CBoxState { Locked = 0, UnLocking = 1, // 解锁中 UnLocked = 2, // 已解锁 Attacking = 3, // 袭击中 Broken = 4 // 破碎 } public class ChallengeBox : MonoBehaviour { [Header("Timeline配置")] public PlayableDirector AppearTimeline;//出现表现timeline public PlayableDirector BreakTimeline;//销毁表现timeline [Header("头像运动参数")] public float AppearJumpDelay = 4f;//播放出现表现timeline同时,延迟多久播放头像动画 [Header("被破坏的箱子")] private ChallengeBox box; [Header("箱子破碎,被鳄鱼袭击特效")] [SerializeField] private ParticleSystem psBoxBroken; // 断开藤曼,同时播放吗 [Header("断开藤曼")] [SerializeField] private Animation aniKnife; [SerializeField] private ParticleSystem psKnife; // 藤曼退开,可以跳跃 [Header("藤曼退开,箱子可供站立")] [SerializeField] private Animation aniBoxOn; private float _speed = 1.0f; private void Awake() { if (psBoxBroken) { psBoxBroken.Stop(); } if (psKnife) { psKnife.Stop(); } if (aniBoxOn) { aniBoxOn.Stop(); } if (aniKnife) { aniKnife.Stop(); // aniKnife.gameObject.SetActive(false); } // if (challengeKiller) // { // challengeKiller.OnIdle(); // } } private void Start() { // AppearTimeline.initialTime = 0; // AppearTimeline.Evaluate(); // // AppearTimeline.playOnAwake(); // IdleTimeline.initialTime = 0; // IdleTimeline.Evaluate(); // BreakTimeline.initialTime = 0; // BreakTimeline.Evaluate(); } private void OnDestroy() { } public void Log(object t) { // Debug.Log(""); } public float GetSpeed() { return _speed; } public float SpeedUpSeconds(float seconds) { return _speed * seconds; } public void UpdateTimeController(ChallengeSetAnimationEvent e) { _speed = e.speed; // _timeForUnlocking = e.timeForUnlocking; // _timeForUnlockingEnd = e.timeForUnLockingEnd; // _timeForAttackStart = e.timeForAttackStart; // _timeForAttacking1 = e.timeForAttacking_1; // _timeForAttacking2 = e.timeForAttacking_2; // _timeForAttackEnd = e.timeForAttackEnd; // _timeForAttackEndWait = e.timeForAttackEndWait; } public void SnapToEnd(Animation anim, string clipName = null) { if (!anim) return; if (clipName == null) { clipName = anim.clip?.name; } if (clipName == null) return; if (anim[clipName] == null) { Log($"动画片段 {clipName} 不存在"); return; } // 方法1:直接设置时间并采样 anim[clipName].time = anim[clipName].length; anim.Play(clipName); anim.Sample(); anim.Stop(clipName); } public void SnapToStart(Animation anim) { if (!anim || !anim.clip ) return; var clipName = anim.clip.name; if (anim[clipName] == null) { Log($"动画片段 {clipName} 不存在"); return; } // var speed = anim[clipName].speed; anim.Play(clipName); anim[clipName].time = 0f; anim.Sample(); // anim[clipName].speed = 0f; anim.Stop(clipName); // anim[clipName].time = speed; } // private async Task OnUnLocking() { Log("OnUnlocking"); // aniKnife.gameObject.SetActive(true); // var knifeName = (from AnimationState state in aniKnife select state.name).FirstOrDefault(); // aniKnife.Play(knifeName); // // 注意时间是自己调的,有时间最好协助回调中 // await Awaiters.Seconds(SpeedUpSeconds(_timeForUnlocking)); // aniBoxOn.Play(); // await Awaiters.Seconds(SpeedUpSeconds(_timeForUnlockingEnd)); // aniKnife.gameObject.SetActive(true); AppearTimeline.initialTime = 0; AppearTimeline.Play(); // AppearTimeline.playableGraph.GetRootPlayable(0).SetSpeed(2.0f); await Awaiters.Seconds(SpeedUpSeconds(AppearJumpDelay)); } private async Task OnAttacking() { Log("OnAttacking"); BreakTimeline.initialTime = 0; BreakTimeline?.Play(); } public void OnLocked() { gameObject.SetActive(true); AppearTimeline.initialTime = 0; AppearTimeline.Evaluate(); AppearTimeline.Stop(); } private void OnUnlocked() { gameObject.SetActive(true); AppearTimeline.initialTime = AppearTimeline.duration; AppearTimeline.Evaluate(); AppearTimeline.Stop(); } private void OnBroken() { Log("OnBroken"); gameObject.SetActive(false); } /////// public async Task UpdateState(CBoxState state) { Log($"UpdateState({state})"); switch (state) { case CBoxState.UnLocked: OnUnlocked(); break; case CBoxState.Broken: OnBroken(); break; case CBoxState.Locked: OnLocked(); break; case CBoxState.UnLocking: await OnUnLocking(); break; case CBoxState.Attacking: await OnAttacking(); break; default: throw new ArgumentOutOfRangeException(nameof(state), state, null); } } }