简体   繁体   中英

Why is this transform.position reset between frames

So, my issue is as follows:

I'm developing a very simple 2D game as I'm quite new to Unity. Basically, there is a knight, and there is a troll. I'm developing my custom AI for the troll and got stumped at the very beginning. I tried to make the troll sprite correctly rotate and walk towards the player (in Update()), but then it turned out that the troll game object doesn't move as much as a millionth of a unit (although it rotates correctly)!

Now, what is special about my problem is the following: it's not about using localPosition instead of position (the troll has no parents – pun intended), it's not about referencing the transform in the script via "[SerializeField]", it's not about working with static objects or messed-up prefab coordinates or any of the other issues I've found in my desperate 10-hour search on the Internet. No, the issue is that I HAVE the troll transform in my code, I modify it successfully, but then it fails to be applied to the in-game troll object. Let that sink in – I am correctly modifying the correct transform (checked multiple times via debugging) but at the beginning of the next frame, all changes get magically reverted and the transform doesn't move the slightest.

I've made almost twenty modifications to my code in order to try and make it work (including separating stuff in different files as was suggested in a particular forum topic) but it just doesn't, and I can't think of anything else. Any help is very, very much appreciated.

public class EnemyController : MonoBehaviour
{
    [SerializeField]
    private Animator animator;
    [SerialiseField]
    private float walkingSpeed;
    [SerializeField]
    [Header("The aggro range of the enemy in Unity units.")]
    private float aggroRange;

    private float dir;

    private Transform playerTransform;

    void Update()
    {
        if (Aggro(playerTransform, aggroRange))
        {
            //WALKING:
            WalkTowards(playerTransform, walkingSpeed); 
        }
    }

    private void WalkTowards(Transform targetTransform, float walkingSpeed)
    {
        animator.SetBool("IsRunning", false);
        dir = 0.0f;

        //Get the direction (left or right)
        if (targetTransform.position.x < transform.position.x) //Left
        {
            dir = -1.0f;
            //Flip the sprite to the left
            transform.rotation = Quaternion.Euler(0.0f, 180.0f, 0.0f);
        }
        else //Right
        {
            dir = 1.0f;
            //Flip the sprite to the right
            transform.rotation = Quaternion.Euler(0.0f, 0.0f, 0.0f);
        }

        transform.position = new Vector3(
            transform.position.x + (walkingSpeed * dir * Time.deltaTime),
            transform.position.y,
            transform.position.z
        );

        Debug.Log(
            string.Format("Troll 1 position:\nx: {0:#.##}",  transform.position.x) +
            string.Format(" y: {0:#.##}", transform.position.y) +
            string.Format(" z: {0:#.##}", transform.position.z)
        );
    }
}

(NOTE: Aggro() is a custom method that determines when the enemy aggros; not included in the code as it is irrelevant to the issue)

So basically, transform.position gets changed correctly in the script and stays that way until the end of the method, but at the beginning of the next frame – ie when WalkTowards() gets called again, the transform.position remains the same as it was at the beginning of the last frame – as if no calculations or changes were ever made.

@Ruzihm,

You were right!!! Turns out the Animator component of the troll was causing the issue – "Apply root motion" was off, I turned it on and the position gets correctly updated now. Thank you ever so much for the help!

Example:

检查器中的动画组件

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM