150 lines
5.6 KiB
C#
150 lines
5.6 KiB
C#
using System.Collections.Generic;
|
||
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;
|
||
private float currentTotalPlayTime => funcAnimSm.currentTotalPlayTime;
|
||
|
||
[Header("Animation Settings")]
|
||
[Tooltip("要播放的功能动画名称。")]
|
||
public string animationName;
|
||
[Tooltip("是否选择其他功能动画子模块,默认子模块为全身动作子模块。")]
|
||
public bool isOtherFuncAnimSm = false;
|
||
[Tooltip("如果选择了其他功能动画子模块,则需要指定子模块名称。")]
|
||
public string funcAnimSmName = "";
|
||
[Tooltip("动画过渡时间,单位秒。")]
|
||
public float transitionDuration = 0.1f;
|
||
[Tooltip("如果勾选此项,当动画被打断,返回Success(执行下一步),否则返回Failure(重新执行此步骤)。")]
|
||
public bool disruptionReturnSuccess = true;
|
||
[Tooltip("是否在开始播放动画时转向目标。")]
|
||
public bool willTurnToTargetAtStart = true;
|
||
[Tooltip("是否在播放过程中持续转向目标。")]
|
||
public bool willTurnToTargetDuringPlaying = false;
|
||
[Tooltip("是否调整根吸附以贴近目标。")]
|
||
public bool willAdjustAdsorption = true;
|
||
[Tooltip("是否持续调整根吸附以贴近目标,直到动画结束。")]
|
||
public bool willKeepAdjustingAdsorption = false;
|
||
[Tooltip("根吸附调整的最小距离。")]
|
||
public float adsorptionMinDistance = 2;
|
||
|
||
[Header("Other Settings")]
|
||
[Tooltip("是否记录此动作到动作记录子模块中。")]
|
||
public bool willRecordAction = true;
|
||
|
||
private bool successPlayed = false;
|
||
private bool frameBuffer;
|
||
|
||
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);
|
||
frameBuffer = false;
|
||
if (successPlayed)
|
||
{
|
||
funcAnim = funcAnimSm.currentRuntimeFuncAnim;
|
||
|
||
if (willTurnToTargetAtStart)
|
||
{
|
||
self.movementSc.SmartTurnToTarget(target);
|
||
}
|
||
|
||
if (willAdjustAdsorption)
|
||
{
|
||
if (!willKeepAdjustingAdsorption)
|
||
{
|
||
funcAnim.AddUpdateUntilEvent(new SetRootAdsorptionAdjustment.Once(target, adsorptionMinDistance));
|
||
}
|
||
else
|
||
{
|
||
funcAnim.AddUpdateEvent(new SetRootAdsorptionAdjustment.Keep(target, adsorptionMinDistance));
|
||
}
|
||
}
|
||
|
||
if (willRecordAction)
|
||
{
|
||
self.actionRecordSm.AddRecord(animationName);
|
||
}
|
||
}
|
||
}
|
||
|
||
public override TaskStatus OnUpdate()
|
||
{
|
||
if (!successPlayed)
|
||
{
|
||
if (!frameBuffer)
|
||
{
|
||
frameBuffer = true;
|
||
return TaskStatus.Running;
|
||
}
|
||
else
|
||
{
|
||
return TaskStatus.Failure;
|
||
}
|
||
}
|
||
|
||
if (funcAnimSm.currentRuntimeFuncAnim == funcAnim && funcAnimSm.CheckDisruption(DisruptionType.NormalAction))
|
||
{
|
||
if (!frameBuffer)
|
||
{
|
||
frameBuffer = true;
|
||
return TaskStatus.Running;
|
||
}
|
||
else
|
||
{
|
||
return TaskStatus.Success;
|
||
}
|
||
}
|
||
|
||
if (funcAnim.isDisrupted || funcAnimSm.currentRuntimeFuncAnim != funcAnim)
|
||
{
|
||
//if (self.isDuringGetHit) return TaskStatus.Running;
|
||
|
||
if (!frameBuffer)
|
||
{
|
||
frameBuffer = true;
|
||
return TaskStatus.Running;
|
||
}
|
||
else
|
||
{
|
||
return disruptionReturnSuccess ? TaskStatus.Success : TaskStatus.Failure;
|
||
}
|
||
}
|
||
|
||
if (willTurnToTargetDuringPlaying)
|
||
{
|
||
self.movementSc.TurnToTargetByAngle(target, 360f);
|
||
}
|
||
|
||
return TaskStatus.Running;
|
||
}
|
||
}
|
||
} |