Files
Cielonos/Assets/Scripts/MainGame/Characters/Base/Subcontrollers/AnimationSubcontrollerBase.cs
SoulliesOfficial f7af60351b 阶段性完成
2025-12-08 05:27:53 -05:00

168 lines
6.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using SLSFramework.General;
using SLSUtilities.FunctionalAnimation;
using UnityEngine;
using UnityEngine.Serialization;
namespace Cielonos.MainGame.Characters
{
public partial class AnimationSubcontrollerBase : SubcontrollerBase<CharacterBase>
{
public Animator animator;
public Dictionary<DisruptionType, bool> disruptionStatus;
public bool isDuringRootMotion;
public bool isDisablingMoveXZ;
public bool isDisablingMoveY;
public BaseAnimationGroup defaultAnimationGroup;
public FunctionalAnimationSubmodule fullBodyFuncAnimSm;
public Dictionary<string, Action<RuntimeFuncAnim>> registeredFunctions;
public List<FuncAnimInterval> lastFrameIntervals { get; private set; }
public List<FuncAnimInterval> currentIntervals { get; private set; }
public override void Initialize()
{
base.Initialize();
fullBodyFuncAnimSm = new FunctionalAnimationSubmodule(this, "FullBodyAction");
registeredFunctions = new Dictionary<string, Action<RuntimeFuncAnim>>();
defaultAnimationGroup?.SetUp(this);
disruptionStatus = new Dictionary<DisruptionType, bool>()
{
{ DisruptionType.NormalExternal, false },
{ DisruptionType.NormalAction, false },
{ DisruptionType.Movement, false }
};
lastFrameIntervals = new List<FuncAnimInterval>();
currentIntervals = new List<FuncAnimInterval>();
RegisterDefaultFunctions();
}
protected virtual void Update()
{
if (owner.statusSm.isDead)
{
return;
}
fullBodyFuncAnimSm?.UpdateTime();
UpdateIntervalInfo();
}
protected virtual void LateUpdate()
{
fullBodyFuncAnimSm?.UpdateEvents();
}
}
public partial class AnimationSubcontrollerBase
{
protected virtual void UpdateIntervalInfo()
{
if (fullBodyFuncAnimSm?.currentRuntimeFuncAnim == null)
{
isDuringRootMotion = false;
return;
}
lastFrameIntervals = currentIntervals;
currentIntervals = fullBodyFuncAnimSm.currentRuntimeFuncAnim.GetEnablingIntervals();
disruptionStatus[DisruptionType.NormalExternal] = currentIntervals.Any(interval => interval.intervalType == IntervalType.ExternalDisruption);
disruptionStatus[DisruptionType.NormalAction] = currentIntervals.Any(interval => interval.intervalType == IntervalType.ActionDisruption);
disruptionStatus[DisruptionType.Movement] = currentIntervals.Any(interval => interval.intervalType == IntervalType.MovementDisruption);
isDuringRootMotion = currentIntervals.Any(interval => interval.intervalType == IntervalType.RootMotion);
}
}
public partial class AnimationSubcontrollerBase
{
public virtual void RegisterDefaultFunctions()
{
registeredFunctions.Add("SetRootMotionMoveXMultiplier", anim =>
{
owner.movementSc.rootMotionMoveXMultiplier = anim.runtimeVariables.GetVariable<float>("RootMotionMoveXMultiplier");
});
registeredFunctions.Add("SetRootMotionMoveYMultiplier", anim =>
{
owner.movementSc.rootMotionMoveYMultiplier = anim.runtimeVariables.GetVariable<float>("SetRootMotionMoveYMultiplier");
});
registeredFunctions.Add("SetRootMotionMoveZMultiplier", anim =>
{
owner.movementSc.rootMotionMoveZMultiplier = anim.runtimeVariables.GetVariable<float>("SetRootMotionMoveZMultiplier");
});
}
}
public partial class AnimationSubcontrollerBase
{
public virtual bool SetGetHitDisruption(DisruptionType disruptionType, BreakthroughType breakthroughType)
{
if (owner.reactionSc.breakthroughResistances[breakthroughType])
{
return false;
}
if (fullBodyFuncAnimSm.Stop(disruptionType))
{
return true;
}
return false;
}
public virtual void PlayGetHitMediumAnimation(Vector3 direction = default)
{
int fullBodyActionIndex = animator.GetLayerIndex("FullBodyAction");
if (animator.HasState(fullBodyActionIndex, Animator.StringToHash("GetHitMediumFront")))
{
float normalizedTransitionDuration = 0.1f / animator.GetCurrentAnimatorStateInfo(fullBodyActionIndex).length;
if (direction == default)
{
animator.CrossFade("GetHitMediumFront", normalizedTransitionDuration, fullBodyActionIndex, 0);
return;
}
direction.y = 0;
direction = direction.normalized;
float angle = Vector3.SignedAngle(transform.forward, direction, Vector3.up);
if (angle > -45f && angle <= 45f)
{
animator.CrossFade("GetHitMediumBack", normalizedTransitionDuration, fullBodyActionIndex, 0);
}
else if (angle > 45f && angle <= 135f)
{
animator.CrossFade("GetHitMediumLeft", normalizedTransitionDuration, fullBodyActionIndex, 0);
}
else if (angle > -135f && angle <= -45f)
{
animator.CrossFade("GetHitMediumRight", normalizedTransitionDuration, fullBodyActionIndex, 0);
}
else
{
animator.CrossFade("GetHitMediumFront", normalizedTransitionDuration, fullBodyActionIndex, 0);
}
}
else
{
if (animator.HasState(fullBodyActionIndex, Animator.StringToHash("GetHit")))
{
animator.CrossFade("GetHit", 0.1f, fullBodyActionIndex, 0);
}
else
{
animator.CrossFade("Empty", 0f, fullBodyActionIndex, 0);
}
}
}
}
}