Revision Difference

Player_Animator#546580

<cat>Code.Player</cat> <title>Player Animator</title> # What is a Player Animator The Animator is responsible for maintaining your AnimGraph with up to date information. You can also set the position and rotation of your player in the Animator. # Example ``` public class StandardPlayerAnimator : PlayerAnimator { public override void Tick() { DoRotation(); DoWalk(); // // Let the animation graph know some shit // SetParam( "b_grounded", GroundEntity != null ); // // Look in the direction what the player's input is facing // SetLookAt( "lookat_pos", Player.EyePos + Input.Rot.Forward * 1000 ); } public virtual void DoRotation() { // // Our ideal player model rotation is the way we're facing // var idealRotation = Rotation.LookAt( Input.Rot.Forward.WithZ( 0 ), Vector3.Up ); // // If we're moving, rotate to our ideal rotation // Rot = Rotation.Slerp( Rot, idealRotation, WishVelocity.Length * Time.Delta * 0.01f ); // // Clamp the foot rotation to within 120 degrees of the ideal rotation // Rot = Rot.Clamp( idealRotation, 120 ); } void DoWalk() { // // These tweak the animation speeds to something we feel is right, // so the foot speed matches the floor speed. Your art should probably // do this - but that ain't how we roll // SetParam( "walkspeed_scale", 2.0f / 190.0f ); SetParam( "runspeed_scale", 2.0f / 320.0f ); // // Work out our movement relative to our body rotation // var moveDir = WishVelocity.Normal; var forward = Rot.Forward.Dot( moveDir ); var sideward = Rot.Right.Dot( moveDir ); // // Set our speeds on the animgraph // SetParam( "forward", forward ); SetParam( "sideward", sideward ); SetParam( "wishspeed", WishVelocity.Length ); } } public class StandardPlayerAnimator : PawnAnimator { TimeSince TimeSinceFootShuffle = 60; float duck; public override void Simulate() { var player = Pawn as Player; var idealRotation = Rotation.LookAt( Input.Rotation.Forward.WithZ( 0 ), Vector3.Up ); DoRotation( idealRotation ); DoWalk(); // // Let the animation graph know some shit // bool sitting = HasTag( "sitting" ); bool noclip = HasTag( "noclip" ) && !sitting; SetAnimParameter( "b_grounded", GroundEntity != null || noclip || sitting ); SetAnimParameter( "b_noclip", noclip ); SetAnimParameter( "b_sit", sitting ); SetAnimParameter( "b_swim", Pawn.WaterLevel > 0.5f && !sitting ); if ( Host.IsClient && Client.IsValid() ) { SetAnimParameter( "voice", Client.TimeSinceLastVoice < 0.5f ? Client.VoiceLevel : 0.0f ); } Vector3 aimPos = Pawn.EyePosition + Input.Rotation.Forward * 200; Vector3 lookPos = aimPos; // // Look in the direction what the player's input is facing // SetLookAt( "aim_eyes", lookPos ); SetLookAt( "aim_head", lookPos ); SetLookAt( "aim_body", aimPos ); if ( HasTag( "ducked" ) ) duck = duck.LerpTo( 1.0f, Time.Delta * 10.0f ); else duck = duck.LerpTo( 0.0f, Time.Delta * 5.0f ); SetAnimParameter( "duck", duck ); if ( player != null && player.ActiveChild is BaseCarriable carry ) { carry.SimulateAnimator( this ); } else { SetAnimParameter( "holdtype", 0 ); SetAnimParameter( "aim_body_weight", 0.5f ); } } public virtual void DoRotation( Rotation idealRotation ) { var player = Pawn as Player; // // Our ideal player model rotation is the way we're facing // var allowYawDiff = player?.ActiveChild == null ? 90 : 50; float turnSpeed = 0.01f; if ( HasTag( "ducked" ) ) turnSpeed = 0.1f; // // If we're moving, rotate to our ideal rotation // Rotation = Rotation.Slerp( Rotation, idealRotation, WishVelocity.Length * Time.Delta * turnSpeed ); // // Clamp the foot rotation to within 120 degrees of the ideal rotation // Rotation = Rotation.Clamp( idealRotation, allowYawDiff, out var change ); // // If we did restrict, and are standing still, add a foot shuffle // if ( change > 1 && WishVelocity.Length <= 1 ) TimeSinceFootShuffle = 0; SetAnimParameter( "b_shuffle", TimeSinceFootShuffle < 0.1 ); } void DoWalk() { // Move Speed { var dir = Velocity; var forward = Rotation.Forward.Dot( dir ); var sideward = Rotation.Right.Dot( dir ); var angle = MathF.Atan2( sideward, forward ).RadianToDegree().NormalizeDegrees(); SetAnimParameter( "move_direction", angle ); SetAnimParameter( "move_speed", Velocity.Length ); SetAnimParameter( "move_groundspeed", Velocity.WithZ( 0 ).Length ); SetAnimParameter( "move_y", sideward ); SetAnimParameter( "move_x", forward ); SetAnimParameter( "move_z", Velocity.z ); } // Wish Speed { var dir = WishVelocity; var forward = Rotation.Forward.Dot( dir ); var sideward = Rotation.Right.Dot( dir ); var angle = MathF.Atan2( sideward, forward ).RadianToDegree().NormalizeDegrees(); SetAnimParameter( "wish_direction", angle ); SetAnimParameter( "wish_speed", WishVelocity.Length ); SetAnimParameter( "wish_groundspeed", WishVelocity.WithZ( 0 ).Length ); SetAnimParameter( "wish_y", sideward ); SetAnimParameter( "wish_x", forward ); SetAnimParameter( "wish_z", WishVelocity.z ); } } public override void OnEvent( string name ) { // DebugOverlay.Text( Pos + Vector3.Up * 100, name, 5.0f ); if ( name == "jump" ) { Trigger( "b_jump" ); } base.OnEvent( name ); } } ``` # Setting Setting the Animator is the same as setting a <page>Player Controller</page>. ``` public override void Respawn() { base.Respawn(); Animator = new StandardPlayerAnimator(); } ``` Like the <page>Player Controller</page>, this property can be changed at any time and is replicated to the client. Setting to null will mean your player isn't animated.