It seems when I enable a object via SetActiveRecursively, that it’s local position is thought to be <0,0,0> in it’s Start(). The object’s local position is not <0,0,0>, and it has been carefully positioned relative to it’s parent. I need that value to be preserved. So how do I get the local position without doing something stupid like creating an extra variable I have to set from the inspector.
To give you a better idea of what I mean.
//In some object's GUI function
public GameObject FooInstance;
void OnGUI()
{
if (GUILayout.Button("DooFoo", GUILayout.Width(Screen.width / 3), GUILayout.Height(75)))
{
FooInstance.SetActiveRecursively(true);
Started = true;
}
}
//Deep in Foo's tree of objects there's a component
Vector3 HomePosition;
void Start ()
{
HomePosition = transform.localPosition;
MonoBehaviour.print(HomePosition); //Prints (0.0, 0.0, 0.0), but the object is not at the local origin.
}
The script functions as expected when I have the object pre-activated from in the inspector, the error only occurs when I activate it from the script.
Does the transform have a parent? The localPosition is the position relative to the parent, or if there is no parent then it’s the world space position.
So, if there’s a parent, and the object is at < 0, 0 ,0 > relative to the parent, then localPosition will be < 0, 0, 0 >.
No matter what i do i can’t reproduce what you describe. I have a gameobject with a nested child-tree. Every child has a script that prints it’s name and localPosition in Start. All child gameobjects are deactivated in the inspector. The parent has a script that uses SetActiveRecursively(true); (which is actually deprecated but still works) when you press a button. I’ve moved all childs to certain local positions and when i press the button at runtime i get a print from each child with it’s correct localPosition.
I’ve have even 5 childs, so it definitely works as it should. I’m pretty sure there’s no bug in unity (why everyone’s first guess is “it might be a bug”?). In most cases it’s a fault in your own code. The only person that can debug your script is you.
While I didn’t have enough information in the post to determine the issue. I still consider it a bug in unity. When SetActiveRecursively is called it begins to activate the child objects. But it doesn’t complete this action before beginning to call updates to objects in the tree.
This violates reasonably intuitive rules of initialization. Just like members of a class are initialized, one would expect the children of an activated object to be initialized before updates were processed. Especially in an architecture that encourages multiple levels of objects.
I wouldn’t have expected something similar to a race condition to emerge on something that is single threaded. But I suspect it’s a result of “lazy initialization”. AKA, the object’s start isn’t called until the object is needed by the internals of unity. I suspect this because adding an empty Update() function to the component suddenly remedies the issue. The object isn’t recognized as needed when a member function is called. Perhaps there’s some way to notify an object that it’s needed?
So when an object higher up in the tree of objects modified the position of a lower object in the tree, the lower object wasn’t initialized and the variable it accessed was still it’s default value and not it’s actual value. Which also makes me wonder where localPosition is stored before an object is activated…
Here’s a sample showing the issue.[8143-breaksunity.zip|8143]