您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

199 行
8.0 KiB

using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Unity.Entities;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Playables;
using UnityEngine.Profiling;
[CreateAssetMenu(fileName = "Move8Dir", menuName = "FPS Sample/Animation/AnimGraph/Move8Dir")]
public class AnimGraph_Move8Dir : AnimGraphAsset
{
public float animMovePlaySpeed = 1.0f;
public float damping = 0.1f;
public float maxStep = 15f;
[Range(0f, 1f)]
[Tooltip("The max. time between exiting ground move and re-entering, before a state reset is triggered")]
public float stateResetWindow;
public AnimationClip animAim;
public List<BlendSpaceNode> blendSpaceNodes;
public bool enableIK;
public ActionAnimationDefinition[] actionAnimations;
public override IAnimGraphInstance Instatiate(EntityManager entityManager, Entity owner, PlayableGraph graph)
{
var animState = new Instance(entityManager, owner, graph, this);
return animState;
}
class Instance : IAnimGraphInstance, IGraphState
{
public Instance(EntityManager entityManager, Entity owner, PlayableGraph graph, AnimGraph_Move8Dir settings)
{
m_settings = settings;
m_EntityManager = entityManager;
m_Owner = owner;
m_locomotionMixer = AnimationLayerMixerPlayable.Create(graph, 3);
// Movement
m_BlendTree = new BlendTree2dSimpleDirectional(graph, settings.blendSpaceNodes);
graph.Connect(m_BlendTree.GetRootPlayable(), 0, m_locomotionMixer, 0);
m_locomotionMixer.SetInputWeight(0, 1.0f);
m_BlendTree.masterSpeed = m_settings.animMovePlaySpeed;
// Aim
if (settings.animAim != null)
{
m_clipAim = AnimationClipPlayable.Create(graph, settings.animAim);
m_clipAim.SetApplyFootIK(false);
m_clipAim.Pause();
m_aimTimeFactor = m_clipAim.GetAnimationClip().length / 180.0f;
m_locomotionMixer.SetLayerAdditive(1, true);
graph.Connect(m_clipAim, 0, m_locomotionMixer, 1);
m_locomotionMixer.SetInputWeight(1, 1.0f);
}
// Actions
m_actionMixer = AnimationLayerMixerPlayable.Create(graph);
var port = m_actionMixer.AddInput(m_locomotionMixer, 0);
m_actionMixer.SetInputWeight(port, 1);
m_actionAnimationHandler = new ActionAnimationHandler(m_actionMixer, settings.actionAnimations);
}
public void Shutdown()
{
}
public void SetPlayableInput(int index, Playable playable, int playablePort)
{
}
public void GetPlayableOutput(int index, ref Playable playable, ref int playablePort)
{
playable = m_actionMixer;
playablePort = 0;
}
public void UpdatePresentationState(bool firstUpdate, GameTime time, float deltaTime)
{
Profiler.BeginSample("AnimGraph_Move8Dir.UpdatePresentationState");
var animState = m_EntityManager.GetComponentData<CharAnimState>(m_Owner);
if (firstUpdate)
{
// Do phase projection for time not spent in state
var ticksSincePreviousGroundMove = time.tick - animState.groundMoveExitTick;
if (ticksSincePreviousGroundMove > 1)
{
animState.locomotionPhase += m_playSpeed * (ticksSincePreviousGroundMove - 1f);
}
// Reset the phase and position in blend space if appropriate
var timeSincePreviousGroundMove = ticksSincePreviousGroundMove / (float)time.tickRate;
if (animState.previousCharLocoState != CharacterPredictedState.StateData.LocoState.GroundMove && timeSincePreviousGroundMove > m_settings.stateResetWindow)
{
// Debug.Log("Reset movement run! (Ticks since: " + ticksSincePreviousGroundMove + " Time since: " + timeSincePreviousGroundMove + ")");
animState.locomotionPhase = 0f;
animState.moveAngleLocal = CalculateMoveAngleLocal(animState.rotation, animState.moveYaw);
animState.locomotionVector = AngleToPosition(animState.moveAngleLocal);
m_CurrentVelocity = Vector2.zero;
}
}
// Get new local move angle
animState.rotation = animState.aimYaw;
animState.moveAngleLocal = CalculateMoveAngleLocal(animState.rotation, animState.moveYaw);
#if UNITY_EDITOR
m_BlendTree.masterSpeed = m_settings.animMovePlaySpeed;
m_BlendTree.footIk = m_settings.enableIK;
#endif
// Smooth through blend tree
var targetBlend = AngleToPosition(animState.moveAngleLocal);
animState.locomotionVector = Vector2.SmoothDamp(animState.locomotionVector, targetBlend, ref m_CurrentVelocity, m_settings.damping, m_settings.maxStep, deltaTime);
// Update position and increment phase
m_playSpeed = 1f / m_BlendTree.SetBlendPosition(animState.locomotionVector, false) * deltaTime;
m_DoUpdateBlendPositions = false;
animState.locomotionPhase += m_playSpeed;
animState.groundMoveExitTick = time.tick;
m_EntityManager.SetComponentData(m_Owner,animState);
Profiler.EndSample();
}
public void ApplyPresentationState(GameTime time, float deltaTime)
{
Profiler.BeginSample("CharacterAnimGraph_3PMove8Dir.UpdateNetwork");
var animState = m_EntityManager.GetComponentData<CharAnimState>(m_Owner);
if (m_DoUpdateBlendPositions)
{
m_BlendTree.SetBlendPosition(animState.locomotionVector, false);
}
m_BlendTree.UpdateGraph();
m_BlendTree.SetPhase(animState.locomotionPhase);
m_clipAim.SetTime(animState.aimPitch * m_aimTimeFactor);
var characterActionDuration = time.DurationSinceTick(animState.charActionTick);
m_actionAnimationHandler.UpdateAction(animState.charAction, characterActionDuration);
Profiler.EndSample();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static float CalculateMoveAngleLocal(float rotation, float moveYaw)
{
// Get new local move angle
var moveAngleLocal = Mathf.DeltaAngle(rotation, moveYaw);
// We cant blend running sideways and running backwards so in range 90->135 we snap to either sideways or backwards
var absMoveAngle = Mathf.Abs(moveAngleLocal);
if (absMoveAngle > 90 && absMoveAngle < 135)
{
var sign = Mathf.Sign(moveAngleLocal);
moveAngleLocal = absMoveAngle > 112.5f ? sign * 135.0f : sign * 90.0f;
}
return moveAngleLocal;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static Vector2 AngleToPosition(float _angle)
{
var dir3D = Quaternion.AngleAxis(_angle, Vector3.up) * Vector3.forward;
return new Vector2(dir3D.x, dir3D.z);
}
AnimGraph_Move8Dir m_settings;
EntityManager m_EntityManager;
Entity m_Owner;
AnimationLayerMixerPlayable m_locomotionMixer;
AnimationClipPlayable m_clipAim;
float m_aimTimeFactor;
AnimationLayerMixerPlayable m_actionMixer;
ActionAnimationHandler m_actionAnimationHandler;
BlendTree2dSimpleDirectional m_BlendTree;
float m_playSpeed;
Vector2 m_CurrentVelocity;
bool m_DoUpdateBlendPositions = true;
}
}