Files
Cielonos/Assets/Scripts/MainGame/Characters/Automata/AI/Behaviors/PlayFuncAnim.cs
SoulliesOfficial f7af60351b 阶段性完成
2025-12-08 05:27:53 -05:00

133 lines
5.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<GameObject> 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<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));
}
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;
}
}
}