Search code examples
c#unity-game-enginevectorlerp

Vector3.Lerp won't move my object despite my debugging saying it should


So this is for an aim-down sight motion in a FPS game. When the player right clicks, this coroutine is fired up which should move the player's right hand from its "idle" position to its "aiming" position. Once the aiming position is reached, hitbox is activated, and an animation plays.

public float ChargeTime;
public Vector3 TargetPosition;

public override IEnumerator Attack(PlayerController player)
{
    float elapsedTime = 0f;
    Vector3 currentPos = player.RightHand.transform.localPosition;

    while (elapsedTime < ChargeTime)
    {
        elapsedTime += Time.deltaTime;
        player.RightHand.transform.localPosition = Vector3.Lerp(currentPos, TargetPosition, (elapsedTime / ChargeTime));

        yield return null;
    }

    player.RightHand.transform.localPosition = TargetPosition;

    player.Hitbox.SetActive(true);
    player.RightHandAnimator.SetBool("IsHolding", true);

    yield return null;
}

I've been going over and over this code and everything should be working as intended. Debug.Logs will show me I've reached this code exactly once, that I'm looping through this while() function properly, that the t variable of the Lerp does increase properly from 0 to 1, and that the hitbox properly triggers at the end of while()... but the hand simply refuses to move.

I've tripled and quadrupled checked that the RightHand variable is indeed referencing the proper object, and that no other code ever interferes (there is nothing else that makes that specific object move).

Am I not understanding how Vector3.Lerp works? What am I missing?

Thanks!

EDIT: The "override" is because this class derives from "Weapon" which has a virtual Attack coroutine, which gets overriden by different types of Weapon subclasses.


Solution

  • Looks to me like there is an Animator on your player that affects the right hand position - at least player.RightHandAnimator leads me to that thought ;)

    The Animator is one of the last things to be executed within a frame and as soon as it holds any keyframe in any state on the player.RightHand.transform.localPosition it will always overrule whatever changes you make in code!

    you could in the meantime turn it off and do e.g.

    public override IEnumerator Attack(PlayerController player)
    {
        player.RightHandAnimator.enabled = false;
    
        var rightHand = player.RightHand.transform;
    
        var currentPos = rightHand.localPosition;
    
        for(var elapsedTime = 0f; elapsedTime < ChargeTime; elapsedTime += Time.deltaTime)
        {
            rightHand.localPosition = Vector3.Lerp(currentPos, TargetPosition, elapsedTime / ChargeTime);
    
            yield return null;
        }
    
        rightHand.localPosition = TargetPosition;
    
        player.Hitbox.SetActive(true);
        player.RightHandAnimator.enabled = true;
        player.RightHandAnimator.SetBool("IsHolding", true);
    }