Force is applied after animation is finished

For attack 1 the force is applied correctly based upon the “Force Time”, but for attacks 2 and 3 the force is only applied after the animation is played regardless of the “Force Time” value.

Inspector:

PlayerAttackingState code:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerAttackingState : PlayerBaseState
{
    Attack attack;
    bool alreadyAppliedForce;


    public PlayerAttackingState(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 < 1f)
        {
            if (normalizedTime >= attack.ForceTime)
            {
                TryApplyForce();
                
            }

            if (stateMachine.InputReader.IsAttacking)
            {
                TryComboAttack(normalizedTime);
            }

        }
        else
        {
            if (stateMachine.Targeter.CurrentTarget != null)
            {
                stateMachine.SwitchState(new PlayerTargetingState(stateMachine));
            }
            else
            {
                stateMachine.SwitchState(new PlayerFreeLookState(stateMachine));
            }
        }


    }



    public override void Exit()
    {

    }  
    
    private void TryComboAttack(float normalizedTime)
    {
        if (attack.ComboStateIndex == -1) { return ; }

        if ( normalizedTime < attack.ComboAttackTime) { return ; }

        stateMachine.SwitchState
        (
            new PlayerAttackingState
            (
                stateMachine,
                attack.ComboStateIndex
            )
        );
    }

    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;
        }
    }

    void TryApplyForce()
    {
        if (alreadyAppliedForce) {return ;}

        stateMachine.ForceReceiver.AddForce(stateMachine.transform.forward * attack.Force);

        alreadyAppliedForce = true;
    }

    
}

That’s something I honestly can’t explain… since the Attack State is working off of the same methodology for each of the attack states (the only real difference that the TryComboAttack() will not even check the normalizedTime if the ComboStateIndex is -1…).

Let’s add a couple Debugs into the Tick:

        if (normalizedTime < 1f)
        {
            Debug.Log($"normalizedTime = {normalizedTime}, attack.ForceTime = {attack.ForceTime}");
            if (normalizedTime >= attack.ForceTime)
            {
                Debug.Log($"normalizedTime > attack.ForceTime, calling TryApplyforce(), alreadyAppliedForce == {alreadyAppliedForce}");
                TryApplyForce();
                
            }

Added the debugs in the PlayerAttackingState script, it looks like it should work, it’s calling TryApplyForce after the normalizedTime is greater than ForceTime, however the “dash foward” seems to wait until the animation reaches the Combo Attack Time value.

I don’t know if it has something to do with the animations:

I tested all the animations with an without the “Root Transform …” boxes ticked, in both the problem persists, again only for attack 2 and 3.

And here’s how the animator is set up:
image_2023-10-04_160641798

Here’s the log from a complete sequence (I removed some of the similar logs so it would fit the character limit, there’s a description of what happens in bold):

normalizedTime = 0, attack.ForceTime = 0.35
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime = 0.00320711, attack.ForceTime = 0.35
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

(normalizedTime is going up)

normalizedTime = 0.3478479, attack.ForceTime = 0.35
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime = 0.3500842, attack.ForceTime = 0.35
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime > attack.ForceTime, calling TryApplyforce(), alreadyAppliedForce == False
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:40)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime = 0.3523012, attack.ForceTime = 0.35
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime > attack.ForceTime, calling TryApplyforce(), alreadyAppliedForce == True
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:40)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime = 0.3550049, attack.ForceTime = 0.35
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime > attack.ForceTime, calling TryApplyforce(), alreadyAppliedForce == True
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:40)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

(normalizedTime is going up)

normalizedTime = 0.5005897, attack.ForceTime = 0.35
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime > attack.ForceTime, calling TryApplyforce(), alreadyAppliedForce == True
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:40)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime = 0, attack.ForceTime = 0.45
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime = 0.002291874, attack.ForceTime = 0.45
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

(normalizedTime is going up)

normalizedTime = 0.4492868, attack.ForceTime = 0.45
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime = 0.4509192, attack.ForceTime = 0.45
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime > attack.ForceTime, calling TryApplyforce(), alreadyAppliedForce == False
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:40)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime = 0.4524879, attack.ForceTime = 0.45
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime > attack.ForceTime, calling TryApplyforce(), alreadyAppliedForce == True
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:40)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime = 0.4542135, attack.ForceTime = 0.45
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime > attack.ForceTime, calling TryApplyforce(), alreadyAppliedForce == True
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:40)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

(normalizedTime is going up)

normalizedTime = 0.600233, attack.ForceTime = 0.45
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime > attack.ForceTime, calling TryApplyforce(), alreadyAppliedForce == True
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:40)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime = 0, attack.ForceTime = 0.8
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime = 0.00135268, attack.ForceTime = 0.8
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

(normalizedTime is going up)

normalizedTime = 0.7973536, attack.ForceTime = 0.8
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime = 0.8003838, attack.ForceTime = 0.8
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime > attack.ForceTime, calling TryApplyforce(), alreadyAppliedForce == False
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:40)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime = 0.8017328, attack.ForceTime = 0.8
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime > attack.ForceTime, calling TryApplyforce(), alreadyAppliedForce == True
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:40)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime = 0.8049088, attack.ForceTime = 0.8
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime > attack.ForceTime, calling TryApplyforce(), alreadyAppliedForce == True
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:40)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

(normalizedTime is going up)

normalizedTime = 0.9986878, attack.ForceTime = 0.8
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:37)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

normalizedTime > attack.ForceTime, calling TryApplyforce(), alreadyAppliedForce == True
UnityEngine.Debug:Log (object)
PlayerAttackingState:Tick (single) (at Assets/Scripts/StateMachines/Player/PlayerAttackingState.cs:40)
StateMachine:Update () (at Assets/Scripts/StateMachines/StateMachine.cs:19)

Zip up your project and upload it to https://gdev.tv/projectupload
Please remove the Library folder to conserve space.

Ok, it’s uploaded. Thanks!

This turned out to be simply that the forcetime was not correct. Many attack style animations have quite a bit of reset between the end of the actual attack and the end of the animation. In the case of the final animation, it’s long since over by .8f.

If you go into the animation import dialogue, while looking at the preview, you can scrub the animation until you get to the part where the force receiver should receive the animation. You’ll see that it shows the frame index as well as the percentage of the animation. This percentage is what you want to put in the fields for Force Time.


In this example, from the 2nd animation, the ideal place for the force to be applied is at about 33% of the animation, but the field in the attack was 45%

Here are the values I came up with for the three attacks you are using:

1 Like

Thank you so much! Guess I should’ve tested more values before assuming I made a mistake on the code haha.

Something that bothered me is this “inverted ghost” on the animation preview, it isn’t really a problem, but do you know why this could be happening?

This is a known bug in URP.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms