Rikk Carey
Rikk Carey

Reputation: 219

Why is transform.hasChanged always true? (i.e. who's job is it to set hasChanged to false?)

I clearly do not understand Transform.hasChanged and created a simple test:

I created a default scene, created a sphere, and created a script on the Sphere that simply checks transform.hasChanged every frame of the Update.

Why is it returning TRUE every frame?

FWIW: I assume that Unity sets the value to TRUE when it detects changes to the transform and resets to FALSE after frame is complete. But that does not appear to be happening. What the heck am I missing?

using UnityEngine;
public class TestHasChanged : MonoBehaviour
{
    void Start() { }

    void Update()
    {
        if (transform.hasChanged) Debug.Log("Sphere hasChanged = TRUE!");
        else Debug.Log("Sphere hasChanged = FALSE!");
    }
}

Next, I added a Listener script that simply checks hasChanged on the Sphere every frame of update. No surprise, it's true every frame.

public class HasChangedListener : MonoBehaviour
{
    public GameObject target;   // the Sphere GO

    void Start() {}

    void Update()
    {
        if (target.transform.hasChanged) {
            Debug.Log("HasChangedListener::Update: hasChanged = TRUE!");
        } else {
            Debug.Log("HasChangedListener::Update: hasChanged = FALSE!");
        }
    }
}

Upvotes: 3

Views: 2087

Answers (2)

Rikk Carey
Rikk Carey

Reputation: 219

I believe that I now understand how Transform.hasChanged works and how it was intended to be used.

My original mistake was believing that Transform.hasChanged was completely managed by Unity (i.e. Unity automatically: a) sets hasTransform=true any time the Transform is changed (duh) AND b) would reset to false at the end of every frame.). IOW you could call hasChanged on any Transform and expect it to reflect changes made this frame. But that appears to be 1/2 wrong (b).

I now believe that the Transform.hasTransform field is an unmanaged convenience 'dirty bit' to be managed by the application. As expected, Unity will set hasChanged=true when changes are made to the Transform. But, that's it. Your job (application) is to manage this frame-by-frame yourself (i.e. set hasChanged=false each frame after you're done checking it).

Please correct me if I have this wrong.

Upvotes: 2

zambari
zambari

Reputation: 5035

I think this is in the docs, no built in method changes hasChanged back to false, its your job. On the plus side, its very cheap (the bit is always set, no branching), on the down side, its problematic to have multiple components watching the same transform - if the first one resets it, the second one will see false. As long as you keep that in mind, you are safe to 'consume' hasChanged with your MonoBehaviour.

I hope that helps

Upvotes: 3

Related Questions