Hello, I am having an issue with the application of forces upon my player character. Both the PlayerAttackState.TryApplyForce() and ForceReceiver.AddForce(Vector3 force) are being called at the appropriate times, I have verified this with debug logs, but no forces are being applied to my character.
I have set up the fields in the inspector, I receive no errors, but even when I crank the numbers up to 1000, nothing happens.
Edit:
Actually after further testing, it seems it is being applied but like WAY late… after all three animations have completed and the character is back at Idle.
My attack state
public class PlayerAttackState : PlayerBaseState
{
bool alreadyAppliedForce;
Attack attack;
float previousFrameTime;
public PlayerAttackState(PlayerStateMachine stateMachine, int attackIndex) : base(stateMachine)
{
attack = stateMachine.Attacks[attackIndex];
}
public override void Enter()
{
stateMachine.Animator.CrossFadeInFixedTime(attack.AnimationName, attack.TransitionDuration);
}
public override void Tick(float deltaTime)
{
Move(deltaTime);
FaceTarget();
float normalizedTime = GetNormalizedTime();
if (normalizedTime > previousFrameTime && normalizedTime < 1)
{
if(stateMachine.InputReader.isAttacking)
{
if (normalizedTime >= attack.ForceTime)
{
TryApplyForce();
}
TryComboAttack(normalizedTime);
}
}
else
{
//go back to prvious locomotion state
}
}
private void TryComboAttack(float normalizedTime)
{
if (attack.ComboStateIndex == -1)
{
return;
}
if (normalizedTime < attack.ComboAttackTime) { return; }
stateMachine.SwitchState(new PlayerAttackState(stateMachine, attack.ComboStateIndex));
}
private void TryApplyForce()
{
if (alreadyAppliedForce) return;
Debug.Log("Attack applying force");
stateMachine.ForceReciever.AddForce(stateMachine.transform.forward * attack.Force);
alreadyAppliedForce = true;
}
public override void Exit()
{
}
private float GetNormalizedTime()
{
AnimatorStateInfo currentStateInfo = stateMachine.Animator.GetCurrentAnimatorStateInfo(0);
AnimatorStateInfo nextStateInfo = stateMachine.Animator.GetNextAnimatorStateInfo(0);
if (stateMachine.Animator.IsInTransition(0) && nextStateInfo.IsTag("Attack"))
{
return nextStateInfo.normalizedTime;
}
else if (!stateMachine.Animator.IsInTransition(0) && currentStateInfo.IsTag("Attack"))
{
return currentStateInfo.normalizedTime;
}
else
{
return 0;
}
}
}
I’m guessing your animations are animating the absolute position values as opposed to animating the relative position values to the gameObject with the rigidbody. If that’s the case, you’re essentially overriding the physics with your animations.
It’s starting to look like @MichaelP is on the right track for this one. If you want to zip up your project and upload it to https://gdev.tv/projectupload I’ll take a look and confirm (or rule it out and hopefully find the issue). Be sure to remove the Library folder from the zip to conserve space.
Unfortunately, I’m working in an existing Project that is already pretty big, and to be perfectly honest this seem pretty small at the moment, and I don’t want to take the time to extract the part of the project I’m talking about. I appreciate it though, and If I cant figure it out, or get it to my liking, I may hit you up! Thanks!
i dont understand … i bought animation from asset store and im using it now … i didn’t understand what do u mean with animate it relative or to absolute space
Say you’ve got an object in a scene and you move its transform.position, you’re moving it in the full world of 3d space. When you have a child object, you have an option to move it relative to the parent object.
So say you’re animating an object to move to position 1,1,1 in world space (not absolute, don’t ask me why I said absolute) it’ll move to 1,1,1 full stop. If you’re animating it to move say between 1,1,1 and 2,2,2, it’ll move in absolute space. Any kind of gravity/movement of the parent object would be overridden with the animation telling it to go to a particular position.
A lot of the time, people animate the position in world space as opposed to relative position to an object and get a result they didn’t expect.
I have a (totally unqualified because I haven’t done the course yet) comment.
The attack state is calling an overloaded Move that in turn supplies a motion of Vector3.zero and a movementSpeed of 0. This, multiplied by whatever force is currently being applied, results in no movement - or Vector3.zero. After this, it tries to apply more force which, on next update, will result in more movement of Vector3.zero.
I will have to look at the videos and code to see if this is intended, but from my unblemished eyes it doesn’t look right.
Edit
I had a look at the code in the repo.
The code looks different. There is no movementSpeed in the repo
I suspect the code was refactored to have the movementSpeed passed in as opposed to it being calculated outside the function. If that’s the case, the calculation inside is wrong.
From what I can see, the usage in the repo is ((motion * speed) + force) * deltaTime
In this case, if speed == 0, the result will still be whatever force is applied (multiplied by deltaTime)
But what the posted code does is (motion + force) * speed * deltaTime
Here, if speed == 0, the result will always be Vector3.zero
I’ll try correcting for this! Thanks for the insight. I actually came back to this because the application of the forces works on Impact, so I knew something in my code had to be incorrect.
And, You are correct, I misunderstood the instruction and thought we were passing in the movement speed of the current state, and since I have a FreeRunState, and a FreeWalkState, I was trying to pass in the correct movement speed. Thank you for catching this! I’ll let you know if it works!