Files
Cielonos/Assets/Opsive/BehaviorDesigner/Add-Ons/CielonosPack/Actions/FuncAnim/PlayLoopFuncAnim.cs

178 lines
6.5 KiB
C#
Raw Normal View History

2026-03-20 12:07:44 -04:00
using System.Collections.Generic;
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
{
2026-03-20 12:07:44 -04:00
public enum PlayLoopReturnMode
{
ReturnImmediately,
2026-06-27 12:52:03 -04:00
WaitForDuration,
LoopIndefinitely
2026-03-20 12:07:44 -04:00
}
2026-06-27 12:52:03 -04:00
[Description("播放一个循环类型的功能动画,并可选择是立刻返回成功,等待规定时间后再返回,还是无限循环直到被外部节点打断。")]
2025-11-25 08:19:33 -05:00
[NodeIcon("Assets/Sprites/Icon/Play.png")]
[Category("Cielonos")]
2026-03-20 12:07:44 -04:00
public class PlayLoopFuncAnim : 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;
2026-06-05 04:21:00 -04:00
private FuncAnimSubmodule funcAnimSm;
2025-12-08 05:27:53 -05:00
private RuntimeFuncAnim funcAnim;
2025-11-25 08:19:33 -05:00
[Header("Animation Settings")]
2026-03-20 12:07:44 -04:00
[Tooltip("要播放的功能动画名称。必须是循环动画。")]
2025-11-25 08:19:33 -05:00
public string animationName;
[Tooltip("是否选择其他功能动画子模块,默认子模块为全身动作子模块。")]
public bool isOtherFuncAnimSm = false;
[Tooltip("如果选择了其他功能动画子模块,则需要指定子模块名称。")]
public string funcAnimSmName = "";
2026-06-27 12:52:03 -04:00
[Tooltip("动画过渡时间,单位秒。")]
public float transitionDuration = 0.1f;
2026-03-20 12:07:44 -04:00
[Header("Return Mode")]
2026-06-27 12:52:03 -04:00
[Tooltip("节点返回模式:\nReturnImmediately: 播放动画后立即返回 Success。\nWaitForDuration: 在指定时间内返回 Running结束后返回 Success。\nLoopIndefinitely: 永远返回 Running由外部如 Parallel 节点)负责中止它。")]
2026-03-20 12:07:44 -04:00
public PlayLoopReturnMode returnMode = PlayLoopReturnMode.ReturnImmediately;
[Tooltip("播放持续时间(秒)。仅在 WaitForDuration 模式下有效。")]
2026-06-27 12:52:03 -04:00
public SharedVariable<float> playDuration = 2f;
2026-03-20 12:07:44 -04:00
[Header("Behaviors")]
2026-06-27 12:52:03 -04:00
[Tooltip("是否在开始播放动画时转向目标。")]
public bool willTurnToTargetAtStart = true;
[Tooltip("是否在播放过程中持续转向目标。")]
public bool willTurnToTargetDuringPlaying = false;
2025-11-25 08:19:33 -05:00
[Tooltip("是否调整根吸附以贴近目标。")]
public bool willAdjustAdsorption = true;
2026-06-27 12:52:03 -04:00
[Tooltip("是否持续调整根吸附以贴近目标,直到动画结束。")]
public bool willKeepAdjustingAdsorption = false;
2025-11-25 08:19:33 -05:00
[Tooltip("根吸附调整的最小距离。")]
public float adsorptionMinDistance = 2;
2025-12-08 05:27:53 -05:00
2026-06-27 12:52:03 -04:00
2026-03-20 12:07:44 -04:00
[Tooltip("如果动画在外力干预下被打断,是否当作执行成功。")]
public bool disruptionReturnSuccess = true;
2025-11-25 08:19:33 -05:00
private bool successPlayed = false;
2026-03-20 12:07:44 -04:00
private bool frameBuffer;
private float startTime;
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()
{
2026-06-27 12:52:03 -04:00
successPlayed = funcAnimSm.Play(animationName, 1, transitionDuration);
2026-03-20 12:07:44 -04:00
frameBuffer = false;
startTime = Time.time;
2025-11-25 08:19:33 -05:00
if (successPlayed)
{
2026-03-20 12:07:44 -04:00
funcAnim = funcAnimSm.currentRuntimeFuncAnim;
2025-11-25 08:19:33 -05:00
2026-06-27 12:52:03 -04:00
if (willTurnToTargetAtStart)
2025-11-25 08:19:33 -05:00
{
2026-04-28 15:46:32 -04:00
self.movementSc.SmartTurnToTarget(target);
2025-11-25 08:19:33 -05:00
}
if (willAdjustAdsorption)
{
2026-06-27 12:52:03 -04:00
if (!willKeepAdjustingAdsorption)
{
funcAnim.AddUpdateUntilEvent(new SetRootAdsorptionAdjustment.Once(target, adsorptionMinDistance));
}
else
{
funcAnim.AddUpdateEvent(new SetRootAdsorptionAdjustment.Keep(target, adsorptionMinDistance));
}
2025-11-25 08:19:33 -05:00
}
2025-12-08 05:27:53 -05:00
2026-06-27 12:52:03 -04:00
2025-12-08 05:27:53 -05:00
}
2025-11-25 08:19:33 -05:00
}
public override TaskStatus OnUpdate()
{
2026-03-20 12:07:44 -04:00
// 播放失败时的 1 帧缓冲返回
2025-11-25 08:19:33 -05:00
if (!successPlayed)
{
2026-03-20 12:07:44 -04:00
if (!frameBuffer)
2025-12-08 05:27:53 -05:00
{
2026-03-20 12:07:44 -04:00
frameBuffer = true;
2025-12-08 05:27:53 -05:00
return TaskStatus.Running;
}
else
{
return TaskStatus.Failure;
}
2025-11-25 08:19:33 -05:00
}
2026-03-20 12:07:44 -04:00
// 被外部干预打断或覆盖时的 1 帧缓冲返回
if (funcAnim.isDisrupted || funcAnimSm.currentRuntimeFuncAnim != funcAnim)
2025-11-25 08:19:33 -05:00
{
2026-03-20 12:07:44 -04:00
if (!frameBuffer)
{
frameBuffer = true;
return TaskStatus.Running;
}
else
{
return disruptionReturnSuccess ? TaskStatus.Success : TaskStatus.Failure;
}
2025-11-25 08:19:33 -05:00
}
2026-06-27 12:52:03 -04:00
if (willTurnToTargetDuringPlaying)
{
self.movementSc.TurnToTargetByAngle(target, 360f);
}
2026-03-20 12:07:44 -04:00
// 根据返回模式判定
if (returnMode == PlayLoopReturnMode.ReturnImmediately)
2025-11-25 08:19:33 -05:00
{
2026-03-20 12:07:44 -04:00
if (!frameBuffer)
{
frameBuffer = true;
return TaskStatus.Running;
}
else
2025-11-25 08:19:33 -05:00
{
return TaskStatus.Success;
}
}
2026-03-20 12:07:44 -04:00
else if (returnMode == PlayLoopReturnMode.WaitForDuration)
2025-11-25 08:19:33 -05:00
{
2026-06-27 12:52:03 -04:00
if (Time.time - startTime >= playDuration.Value)
2026-03-20 12:07:44 -04:00
{
if (!frameBuffer)
{
frameBuffer = true;
return TaskStatus.Running;
}
else
{
return TaskStatus.Success;
}
}
2025-11-25 08:19:33 -05:00
}
return TaskStatus.Running;
}
}
2026-03-20 12:07:44 -04:00
}