Nah… Doesn’t matter about walls it does that always.
public class PlayerTargetingState : PlayerBaseState
{
public PlayerTargetingState(PlayerStateMachine stateMachine, bool shouldBlend = true) : base(stateMachine)
{
this.shouldBlend = shouldBlend;
}
private readonly int TARGETINGBLENDTREEHASH = Animator.StringToHash("TargetingBlendTree");
private readonly int TARGETINGFORWARDHASH = Animator.StringToHash("TargetingForward");
private readonly int TARGETINGRIGHTHASH = Animator.StringToHash("TargetingRight");
private const float ANIMATORDAMPTIME = 0.1f;
private const float ANIMATORBLENDTIME = 0.2f;
private bool shouldBlend;
private bool isAttacking = false;
public override void Enter()
{
stateMachine.InputReader.TargetEvent += OnTarget; //Subscribe to cancel target event.
//stateMachine.InputReader.TargetEvent += AttemptTargetChange;
stateMachine.InputReader.AttackDown += OnAttack;
isAttacking = false;
// Check to see if a smooth blend should happen or an abrupt play for special transitions such as pulling up
if (shouldBlend) stateMachine.Animator.CrossFadeInFixedTime(TARGETINGBLENDTREEHASH, ANIMATORBLENDTIME); // Enter normal targeting blend tree to trigger Cinemachine camera.
else stateMachine.Animator.Play(TARGETINGRIGHTHASH);
}
public void AttemptTargetChange()
{
stateMachine.Targeter.AttemptChangeTarget();
}
public override void Tick(float deltaTime)
{
// Check for ability animation. Disable when done and return to natural state.
if (stateMachine.IsAnimatingAbility())
{
if (GetNormalizedTime(stateMachine.Animator, "Ability") < 1) return;
else
{
stateMachine.SetAnimatingAbility(false);
ReturnToLocomotion();
}
}
if (isAttacking)
{
stateMachine.SwitchState(new PlayerAttackingState(stateMachine, 0)); //Switch to attack with first attack.
return;
}
if (stateMachine.Targeter.currentTarget == null)
{
stateMachine.SwitchState(new PlayerFreeLookState(stateMachine));
return;
}
Vector3 movement = CalculateMovement(deltaTime);
Move(movement * stateMachine.GetCurrentSpeed(false) * DistanceSpeedModifier(), deltaTime);
UpdateAnimator(deltaTime);
FaceTarget(deltaTime);
}
public override void Exit()
{
stateMachine.InputReader.TargetEvent -= OnTarget;
stateMachine.InputReader.AttackDown -= OnAttack;
}
private void OnTarget()
{
if (stateMachine.IsInUI()) return; //Ignore target change while in UI
stateMachine.Targeter.Cancel();
stateMachine.SwitchState(new PlayerFreeLookState(stateMachine));
}
private void OnAttack()
{
if (stateMachine.IsInUI()) return; //Ignore attack requests while in UI
if (stateMachine.IsMouseTargeting()) return; //Ignore attack requests while targeting abilities.
isAttacking = true;
}
private Vector3 CalculateMovement(float deltaTime)
{
Vector3 movement = new Vector3();
movement += stateMachine.transform.right * stateMachine.InputReader.MovementValue.x; //Calculate lateral movement.
movement += stateMachine.transform.forward * stateMachine.InputReader.MovementValue.y; //Calculate forward/backward movement.
return movement;
}
private void UpdateAnimator(float deltaTime)
{
if (stateMachine.InputReader.MovementValue.y == 0) //Check for no forward/back movement
{
stateMachine.Animator.SetFloat(TARGETINGFORWARDHASH, 0, ANIMATORDAMPTIME, deltaTime);
}
else
{
//Check to see if moving forward or back and then set Animator value to match
float value = stateMachine.InputReader.MovementValue.y > 0 ? 1f : -1f;
stateMachine.Animator.SetFloat(TARGETINGFORWARDHASH, value, ANIMATORDAMPTIME, deltaTime);
}
if (stateMachine.InputReader.MovementValue.x == 0) //Check for no forward/back movement
{
stateMachine.Animator.SetFloat(TARGETINGRIGHTHASH, 0, ANIMATORDAMPTIME, deltaTime);
}
else
{
//Check to see if moving right or left and then set Animator value to match
float value = stateMachine.InputReader.MovementValue.x > 0 ? 1f : -1f;
stateMachine.Animator.SetFloat(TARGETINGRIGHTHASH, value, ANIMATORDAMPTIME, deltaTime);
}
}
}
And the (false) for GetCurrentSpeed is just saying it isn’t FreeLook. I have the two separate speeds and use a MovementSpeed Stat that uses one or the other fore base. DistanceModifier is something you helped with for that illusion of how fast you can rotate around an enemy. It works like a charm, too.
But in any event, isn’t this sort of irrelevant since all of movement will be in PlayJumpingState and PlayerFallingState ?
public class PlayerJumpingState : PlayerBaseState
{
private readonly int JUMPHASH = Animator.StringToHash("Jump");
private const float ANIMATORBLENDTIME = 0.1f;
private const float JUMPVOLUME = 0.7f;
private Vector3 momentum;
private bool queueJumpAttack = false;
public PlayerJumpingState(PlayerStateMachine stateMachine) : base(stateMachine) { }
public override void Enter()
{
stateMachine.LedgeDetector.OnLedgeDetect += HandleLedgeDetect;
stateMachine.InputReader.AttackDown += HandleJumpAttack;
stateMachine.SetJumping(true);
stateMachine.ForceReceiver.Jump(stateMachine.JumpForce);
stateMachine.AudioSource.PlayOneShot(stateMachine.JumpSounds[Random.Range(0, stateMachine.JumpSounds.Length)], JUMPVOLUME);
momentum = stateMachine.Controller.velocity;
momentum.y = 0;
stateMachine.Animator.CrossFadeInFixedTime(JUMPHASH, ANIMATORBLENDTIME);
stateMachine.FaceMovementDirection();
}
public override void Tick(float deltaTime)
{
// Move with current momentum
if (stateMachine.Targeter.currentTarget == null) Move(momentum, deltaTime);
else Move(HandleLateralMovement(momentum), deltaTime);
// Enter Falling state if y starts to head towards ground
if (stateMachine.Controller.velocity.y <= 0 || stateMachine.Controller.isGrounded)
{
stateMachine.SwitchState(new PlayerFallingState(stateMachine, queueJumpAttack));
return;
}
FaceTarget(deltaTime);
}
public override void Exit()
{
stateMachine.LedgeDetector.OnLedgeDetect -= HandleLedgeDetect;
stateMachine.InputReader.AttackDown -= HandleJumpAttack;
stateMachine.SetJumping(false);
}
private Vector3 HandleLateralMovement(Vector3 momentum)
{
return momentum;
}
private void HandleLedgeDetect(Vector3 ledgeForward, Vector3 closestPoint)
{
if (!stateMachine.Sheathe.IsSheathed()) return; //Do not allow ledge grab while weapon is unsheathed.
stateMachine.SwitchState(new PlayerHangingState(stateMachine, ledgeForward, closestPoint));
}
private void HandleJumpAttack()
{
queueJumpAttack = true;
}
}
(You can see that I have the if check there and HandleLateralMovement from when I was trying different things. I assume we need to mess with momentum a bit here to fix this). I also have a jump attack that queues in JumpingState and actually calls over to attack from FallingState