Files
Cielonos/Assets/Scripts/MainGame/Characters/Automata/AI/Behaviors/PlayFuncAnim.cs

133 lines
5.1 KiB
C#
Raw Normal View History

2025-11-25 08:19:33 -05:00
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;
2025-12-08 05:27:53 -05:00
namespace Cielonos.MainGame.Characters.AI
2025-11-25 08:19:33 -05:00
{
[Description("让角色播放一个功能动画,播放过程中会检测打断情况。")]
[NodeIcon("Assets/Sprites/Icon/Play.png")]
[Category("Cielonos")]
2025-12-08 05:27:53 -05:00
public class PlayFuncAnim : AutomataActionBase
2025-11-25 08:19:33 -05:00
{
2025-12-08 05:27:53 -05:00
protected CharacterBase target;
2025-11-25 08:19:33 -05:00
[Tooltip("是否选择其他目标,默认目标为玩家。")]
public bool isOtherTarget = false;
[Tooltip("如果选择了其他目标,则需要指定目标对象。")]
public SharedVariable<GameObject> targetGameObject;
2025-12-08 05:27:53 -05:00
private AnimationSubcontrollerBase animationSc => self.animationSc;
private FunctionalAnimationSubmodule funcAnimSm;
private RuntimeFuncAnim funcAnim;
private float currentPlayTime => funcAnimSm.currentPlayTime;
2025-11-25 08:19:33 -05:00
[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;
2025-12-08 05:27:53 -05:00
[Header("Other Settings")]
[Tooltip("是否记录此动作到动作记录子模块中。")]
public bool willRecordAction = true;
2025-11-25 08:19:33 -05:00
private bool successPlayed = false;
2025-12-08 05:27:53 -05:00
private bool failureBuffer;
2025-11-25 08:19:33 -05:00
public override void OnAwake()
{
2025-12-08 05:27:53 -05:00
base.OnAwake();
2025-11-25 08:19:33 -05:00
funcAnimSm = isOtherFuncAnimSm ? null : animationSc.fullBodyFuncAnimSm;
target = isOtherTarget ? targetGameObject.Value.GetComponent<CharacterBase>() : 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));
}
2025-12-08 05:27:53 -05:00
if (willRecordAction)
{
self.actionRecordSm.AddRecord(animationName);
}
}
else
{
failureBuffer = false;
2025-11-25 08:19:33 -05:00
}
}
public override TaskStatus OnUpdate()
{
if (!successPlayed)
{
2025-12-08 05:27:53 -05:00
if (!failureBuffer)
{
failureBuffer = true;
return TaskStatus.Running;
}
else
{
Debug.LogWarning("功能动画播放失败:" + animationName);
return TaskStatus.Failure;
}
2025-11-25 08:19:33 -05:00
}
if (funcAnimSm.currentRuntimeFuncAnim == funcAnim && !funcAnim.isLooping &&
funcAnimSm.CheckDisruption(DisruptionType.NormalAction))
{
2025-12-08 05:27:53 -05:00
Debug.Log("动画播放完成:" + animationName);
2025-11-25 08:19:33 -05:00
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;
}
}
}