using Cielonos.MainGame.Characters; using Cielonos.MainGame.FunctionalAnimation; using Opsive.BehaviorDesigner.Runtime.Tasks; using Opsive.BehaviorDesigner.Runtime.Tasks.Actions; using Opsive.GraphDesigner.Runtime; using Opsive.GraphDesigner.Runtime.Variables; using Opsive.Shared.Utility; using SLSUtilities.FunctionalAnimation; using UnityEngine; namespace Cielonos.MainGame.Characters.AI { [Description("让角色播放一个功能动画,播放过程中会检测打断情况。")] [NodeIcon("Assets/Sprites/Icon/Play.png")] [Category("Cielonos")] public class PlayFuncAnim : AutomataActionBase { protected CharacterBase target; [Tooltip("是否选择其他目标,默认目标为玩家。")] public bool isOtherTarget = false; [Tooltip("如果选择了其他目标,则需要指定目标对象。")] public SharedVariable targetGameObject; private AnimationSubcontrollerBase animationSc => self.animationSc; private FunctionalAnimationSubmodule funcAnimSm; private RuntimeFuncAnim funcAnim; private float currentPlayTime => funcAnimSm.currentPlayTime; [Header("Animation Settings")] [Tooltip("要播放的功能动画名称。")] public string animationName; [Tooltip("是否选择其他功能动画子模块,默认子模块为全身动作子模块。")] public bool isOtherFuncAnimSm = false; [Tooltip("如果选择了其他功能动画子模块,则需要指定子模块名称。")] public string funcAnimSmName = ""; [Tooltip("如果是循环动画,设置结束时间点,单位秒,-1表示不设置。")] public float loopAnimationEndTime = -1; [Tooltip("动画过渡时间,单位秒。")] public float transitionDuration = 0.1f; [Tooltip("如果勾选此项,当动画被打断,返回Success(执行下一步),否则返回Failure(重新执行此步骤)。")] public bool disruptionReturnSuccess = true; [Tooltip("是否在播放动画时转向目标。")] public bool willTurnToTarget = true; [Tooltip("是否调整根吸附以贴近目标。")] public bool willAdjustAdsorption = true; [Tooltip("根吸附调整的最小距离。")] public float adsorptionMinDistance = 2; [Header("Other Settings")] [Tooltip("是否记录此动作到动作记录子模块中。")] public bool willRecordAction = true; private bool successPlayed = false; private bool failureBuffer; public override void OnAwake() { base.OnAwake(); funcAnimSm = isOtherFuncAnimSm ? null : animationSc.fullBodyFuncAnimSm; target = isOtherTarget ? targetGameObject.Value.GetComponent() : MainGameManager.Player; } public override void OnStart() { successPlayed = funcAnimSm.Play(animationName); if (successPlayed) { funcAnim = funcAnimSm.currentRuntimeFuncAnim; // 以后可能有其它的FuncAnimSubmodule,暂时只考虑全身动作 if (willTurnToTarget) { self.movementSc.TurnToTarget(target); } if (willAdjustAdsorption) { funcAnim.AddUpdateUntilEvent(new SetRootAdsorptionAdjustment(target, adsorptionMinDistance)); } if (willRecordAction) { self.actionRecordSm.AddRecord(animationName); } } else { failureBuffer = false; } } public override TaskStatus OnUpdate() { if (!successPlayed) { if (!failureBuffer) { failureBuffer = true; return TaskStatus.Running; } else { Debug.LogWarning("功能动画播放失败:" + animationName); return TaskStatus.Failure; } } if (funcAnimSm.currentRuntimeFuncAnim == funcAnim && !funcAnim.isLooping && funcAnimSm.CheckDisruption(DisruptionType.NormalAction)) { Debug.Log("动画播放完成:" + animationName); return TaskStatus.Success; } if (funcAnim.isLooping) { if(loopAnimationEndTime > 0 && currentPlayTime >= loopAnimationEndTime) { return TaskStatus.Success; } } if (funcAnim.isDisrupted || funcAnimSm.currentRuntimeFuncAnim != funcAnim) { //if (self.isDuringGetHit) return TaskStatus.Running; return disruptionReturnSuccess ? TaskStatus.Success : TaskStatus.Failure; } return TaskStatus.Running; } } }