This is odd. It doesn’t look like there is state being kept that could cause this. Can you share your PlayerTargetingState
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerTargetingState : PlayerBaseState
{
private readonly int TargetingBlendTreeHash = Animator.StringToHash("TargetingBlendTree");
private readonly int TargetingForwardHash = Animator.StringToHash("TargetingForward");
private readonly int TargetingRightHash = Animator.StringToHash("TargetingRight");
public PlayerTargetingState(PlayerStateMachine stateMachine) : base(stateMachine){}
private const float CrossFadeDuration = 0.12f;
public override void Enter()
{
stateMachine.InputReader.CancelEvent += OnCancel;
stateMachine.InputReader.CycleTargetEvent += OnCycleTarget;
stateMachine.Animator.CrossFadeInFixedTime(TargetingBlendTreeHash, CrossFadeDuration);
Debug.Log("Switching Camera to Targeting");
}
//--------------------------------
public override void Tick(float deltaTime)
{
if(stateMachine.InputReader.IsAttacking)
{
stateMachine.SwitchState(new PlayerAttackingState(stateMachine, 0));
return; //
}
if(stateMachine.Targeter.CurrentTarget == null)
{
stateMachine.SwitchState(new PlayerFreeLookState(stateMachine));
return;
}
Vector3 movement = CalculateMovement();
Move(movement * stateMachine.TargetingMovementSpeed, deltaTime);
UpdateAnimator(deltaTime);
FaceTarget();
}
private void UpdateAnimator(float deltaTime)
{
if(stateMachine.InputReader.MovementValue.y == 0)
{
stateMachine.Animator.SetFloat(TargetingForwardHash, 0, 0.12f, deltaTime);
}
else
{
float value = stateMachine.InputReader.MovementValue.y > 0 ? 1f : -1f;
stateMachine.Animator.SetFloat(TargetingForwardHash, value, 0.12f, deltaTime);
}
if(stateMachine.InputReader.MovementValue.x == 0)
{
stateMachine.Animator.SetFloat(TargetingRightHash, 0, 0.12f, deltaTime);
}
else
{
float value = stateMachine.InputReader.MovementValue.x > 0 ? 1f : -1f;
stateMachine.Animator.SetFloat(TargetingRightHash, value, 0.12f, deltaTime);
}
}
public override void Exit()
{
stateMachine.InputReader.CancelEvent += OnCancel;
Debug.Log("Exiting Targeting State");
}
private void OnCancel()
{
stateMachine.Targeter.Cancel();
stateMachine.SwitchState(new PlayerFreeLookState(stateMachine));
}
private void OnCycleTarget()
{
stateMachine.Targeter.SelectNextTarget();
}
private Vector3 CalculateMovement()
{
Vector3 movement = new Vector3();
movement += stateMachine.transform.right * stateMachine.InputReader.MovementValue.x; // a-d key, left-right arrow
movement += stateMachine.transform.forward * stateMachine.InputReader.MovementValue.y;
return movement;
}
}
I shared my code. I also notice that for instance when I’m swinging my weapon in the TargetingState, and while swingining I leave the state by pressing the shouder button, it stops the swinging animation halfway and doesn’t finish it. Is that easy to fix?
First, you are not unhooking from the event
public override void Exit()
{
// ... other code ...
// unsubscribe from cycle event
stateMachine.InputReader.CycleTargetEvent -= OnCycleTarget;
}
Yes. I also see that you are not unhooking the cancel event. It’s not supposed to be listening in the attacking state but because you are not unhooking it, it is still active and can cancel the targeting. This is what your OnExit()
should look like
public override void Exit()
{
stateMachine.InputReader.CancelEvent -= OnCancel; // should be -= not +=
stateMachine.InputReader.CycleTargetEvent -= OnCycleTarget; // unhook target cycle
Debug.Log("Exiting Targeting State");
}
You are amazing. It works like a charm now! Turned out they were pretty straight forward fixes. I’m sorry I’m still very much a beginner.
Could I bother you one last time with a question? Maybe it happens later on in the course’s advanced movements, not sure… but right now the attacking is set up in a way that you have to hold down the action button to execute the 3-part combo. However, I’d much rather just press the action button 3 times to attack rather than holding it. Does not seem so intuitive. But how do I go about doing that?
This is my PlayerAttackingState script
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerAttackingState : PlayerBaseState
{
private float previousFrameTime;
private bool alreadyAppliedForce = false;
private AttackData attack;
public PlayerAttackingState(PlayerStateMachine stateMachine, int attackIndex) : base(stateMachine)
{
attack = stateMachine.Attacks[attackIndex];
}
public override void Enter()
{
stateMachine.Weapon.SetAttack(attack.Damage);
stateMachine.Animator.CrossFadeInFixedTime(attack.AnimationName, attack.TransitionDuration);
}
public override void Tick(float deltaTime)
{
Move(deltaTime);
FaceTarget();
float normalizedTime = GetNormalizedTime();
if(normalizedTime >= previousFrameTime && normalizedTime < 1f)
{
if(normalizedTime >= attack.ForceTime)
{
TryApplyForce();
}
if(stateMachine.InputReader.IsAttacking)
{
TryComboAttack(normalizedTime);
}
}
else{
// go back to locomotion
if(stateMachine.Targeter.CurrentTarget != null)
{
stateMachine.SwitchState(new PlayerTargetingState(stateMachine));
} else
{
stateMachine.SwitchState(new PlayerFreeLookState(stateMachine));
}
}
previousFrameTime = normalizedTime;
}
public override void Exit()
{
}
private void TryComboAttack(float normalizedTime)
{
if(attack.ComboStateIndex == -1) { return; } // if we don't have a combo, return
if(normalizedTime < attack.ComboAttackTime) { return;} // if it can combo, we need to make sure we are far enough through the animation to execute, if its less, we're not ready to combo attack
stateMachine.SwitchState // now we can switch state if the above 2 statements are not true
(
new PlayerAttackingState
(
stateMachine,
attack.ComboStateIndex
)
);
}
private void TryApplyForce()
{
if(alreadyAppliedForce){ return;}
stateMachine.ForceReceiver.AddForce(stateMachine.transform.forward * attack.Force);
alreadyAppliedForce = true;
}
private float GetNormalizedTime()
{
AnimatorStateInfo currentInfo = stateMachine.Animator.GetCurrentAnimatorStateInfo(0);
AnimatorStateInfo nextInfo = stateMachine.Animator.GetNextAnimatorStateInfo(0);
if (stateMachine.Animator.IsInTransition(0) && nextInfo.IsTag("Attack"))
{
return nextInfo.normalizedTime;
}
else if(!stateMachine.Animator.IsInTransition(0) && currentInfo.IsTag("Attack"))
{
return currentInfo.normalizedTime;
}
else
{
return 0f;
}
}
}
I think this may help. It’s something I answered a while ago
Edit
Out of curiosity; which of the cycle options did you go with?
Thank you I’ll check out that post!
I went with the first option. Seems to work fine!
I just noticed another weird issue. In the Input Actions I deleted the Look input for the mouse so I can only look around with the controller’s right stick. However, when I am in thge PlayerTargetingState, I can no longer rotate my camera around the player using the right stick. HOWEVER, I can rotate with the mouse…?! I cannot use the mouse outside of the targetingstate, why would it work during the targeting state?
It may be because the targeting state uses a different camera than the other states. The free look camera has a Cinemachine Input Provider
component which the targeting camera doesn’t. It is a little odd that the mouse overrides the target group. What does your Targeting Camera’s inspector look like?
Like this. I would like to be able to rotate around my player in targetingstate though, to see enemies coming. Just not with the mouse.
The targeting camera is set to point the camera at the target. There’s no rotating around the player in targeting state. Not with the way the course has done things. I see your Aim
is set to POV but in the course we used Group Composer
.
I suspect you may want to just add a Cinemachine Input Provider
like the one we have on the free look camera. It may help. I don’t know Cinemachine very well and would not be able to help much with that
Right, I changed it to Group Composer and the mouse now no longer interferes with the Targeting state. Thanks! I tried the Input Provider, that seems to work, but the camera is wayyy too floaty. I think I’ll just leave it out and follow the course as is. May be better after all
I’m not sure if I’m going to be able to figure out how to get the 3x button press combo done, seems quite a long thread, but I’ll give it a try to see if I comprehend. Downside of being a complete beginner, it all sounds complicated lol.
I’m also looking to figure out how to reduce camera snapping when you go out of the targeting state while moving backwards. If you do that, the camera rotates really quickly and the screen kinda snaps. I tried messing with the ease in out settings but that doesn’t help. Any quick tip you have for me? I promimse Ill stop bothering you now. I am realllyyy greatful of you.Learned a lot from you today and from the course.
What it boiled down to was that you change the attack to be like a jump. It fires once, instead of ‘on’ when you press and ‘off’ when you let go. Then, when the press event fires, you attack. Or move to the next attack.
I think stick to the course. I believe at some point we fix that
I think I’ll finish the course first since I haven’t gotten to the advanced moves yet. Perhaps it will click then. I’d like to thank you once again for your help today. Can’t wait to create my dream game.
It’s my pleasure. Enjoy the rest of the course
I’m kind of upset… I saved everything yesterday, closed Unity…now I reopened Unity and the animations won’t play when playing the game. Only idle is playing. I can see from the animator that it is running through the blend trees, also in the targeting state and when attacking. I can see those little bars fill up while executing the movement… however on screen he’s just stuck in an idle animation. No walk, no running, no attacks. How do you bug test something like this? What could it be?
It did throw an error a few times but I can’t seem to replicate it. It just appeared randomly a few times. It was something about object not set as an instance of something and it referred to line 31 in the Inputreader.cs which is
void OnDestroy()
{
controls.Player.Disable();
}
Do you have any idea what it could be?? I can’t get the error to show now that I’m trying. Just wish the animations would play again. Its not that the animation files are broken either because in the previews it does play the animations. Sorry to bother you again.
That could be anything.
Try this:
Close Unity, go into the project folder and delete the Library folder. Restart Unity. It will take longer to start now 'cos it’s rebuilding the Library folder. Check again.
If that doesn’t work, we’ll troubleshoot some more
I removed the entire Library folder. It did not fix it. It’s still not playing the animations, but the blend tree still seems to respond. Did not at first but now it does. There aren’t any errors in the console.
Can you zip the project (without the Library folder) and upload it somewhere. Then I can take a quick look. It will be very difficult to troubleshoot here
Definitely, thanks a lot
// link deleted
Although the compliler does say that there are some issues with some animations upon import, it did that before also and I’m aware of that. That should not be the cause of it since it worked before as well. I’m going to sort out the animations later after implementing the features.
Access Denied