- Home /
How to change position of child component without affecting the position of the parent
I'm using Instantiate() to create a new instance of a resource prefab called "meteor". After the instance is created, I want to add a new Camera to the instance and change the position of the camera, relative to the parent. However, every time I change the position of the child component ( the camera ), it affects the position of the parent ( the meteor instance ). I've tried several different ways of approaching this, but each attempt has the same results. Watching the values in the debugger, it shows them both changing through the execution of only one statement.
Perhaps someone can spot something wrong?
Thanks!
GameObject spawnedMeteor;
void OnTriggerEnter(Collider collider)
{
if( collider.name == "Player1" )
{
// Spawn the meteor
spawnedMeteor = Instantiate(
( Resources.Load( "Meteor" ) ),
initialSpawnLocation,
new Quaternion( 0, 0, 0, 0 )
) as GameObject;
Camera meteorCamera = (Camera)spawnedMeteor.AddComponent( typeof(Camera) );
// Disable the main camera
GameObject mainCamera = GameObject.Find("Main Camera");
if( mainCamera )
{
mainCamera.active = false;
}
meteorCamera.active = true;
meteorCamera.transform.position = spawnedMeteor.transform.position;
// Changes the value of spawnedMeteor.transform.position as well
meteorCamera.transform.position += new Vector3( 0, cameraDistance, 0 );
// Changes the value of meteorCamera.transform.position as well
spawnedMeteor.transform.position -= new Vector3( 0, cameraDistance, 0 );
}
}
Answer by voodoo · Dec 30, 2012 at 04:30 AM
A Camera is a component attached to a GameObject - it looks like they're both moving because you're attaching the Camera to the same GameObject that the meteor is, meaning they are the same object with the same Transform. When you use AddComponent() it isn't the same as parenting; it is adding more behaviour to the same GameObject, which all share the same Transform. What you want is for the Camera to have its own Transform, which entails that it must be a component of an entirely separate GameObject.
// First create the new GameObject to assign our Camera component to
// All GameObjects come with Transforms already so we don't need to attach one
GameObject GO = new GameObject("editorNameOfMyNewGameObject");
// Now add the Camera component. We can optionally cache it in a variable on creation.
Camera CAM = GO.AddComponent<Camera>();
// IMPORTANT :: GO.transform and CAM.transform are the *SAME* Transform
// When you use a .transform member it is only a shortcut to the Transform component of the current GameObject
if ( GO.GetComponent<Transform>() == CAM.GetComponent<Transform>() ) {
Debug.Log("It's true, they're the same Transform. If I edit it, it moves the whole GameObject along with all components attached.");
}
// Parent the camera's transform to the meteor's transform
CAM.transform.parent = spawnedMeteor.transform;
// If we want the camera to look at the meteor from a distance (as an example) but still follow it (since we are still parented)
// Move away so we can take a look
CAM.transform.position = spawnedMeteor.transform.position + new Vector3(10f,10f,0f);
// Look at it. This only 'looks' once, it won't continue to track unless we call this each frame
CAM.transform.LookAt(spawnedMeteor.transform.position);
// Or, if we wanted the camera to be exactly on top of the meteor we can do one of two things
CAM.transform.position = spawnedMeteor.transform.position;
// but for me this is is a bit more clean (totally subjective) - make note of *LOCAL*position
CAM.transform.localPosition = Vector3.zero;
// If we want to align the camera with the same rotation as the meteor
CAM.transform.localRotation = Quaternion.identity; // No rotation locally, meaning we have only our parent's rotation
Let me know if I made any mistakes and it's not working like I said!
$$anonymous$$y first attempt at this failed. I think I figured out why though.
After reading your code, I read the new GameObject("editorNameOf$$anonymous$$yNewGameObject") line as "place my meteor instantiation here". With that assumption, I made the modifications to parent the camera to the meteor object and it didn't work. Watching in the debugger, it showed the parent as being null after my attempted assignment. I'm not sure why that is, but I suppose it has something to do with the hierarchy of how my object was instantiated as well?
This got me thinking about the hierarchy situation you've highlighted. So I tried to create a new, private empty gameObject, then add the camera component to that, and the parent assignment worked great.
Why is it that the parent assignment resulted in a null parent when I had added the camera component to the meteor instance? I looked at the parent of the meteor transform and it was null as well. Perhaps I need to read up a bit more on parenting in unity :).
Thanks!
You'll leave your original meteor instantiation code, this is how to create the camera's object after that. You instantiated the meteor fine in your original post; that's one object - we need two. So that's where my code comes in, creating the camera's object. The "editorNameOf$$anonymous$$yNewGameObject" is just the label that the new GameObject gets, you can see it in the editor hierarchy once it is made and can access it using the .name member.
It is also useful because the debugger may reference the object if there is a problem, and if we gave it an intelligent name it will be easier for us to tell which object it's talking about at a glance. Perhaps I should have used "CameraObject" as the name ins$$anonymous$$d, but I didn't want it to look like the name we gave served any functional purpose, that it's not a class name or anything, it's just whatever you want it to show up as in the hierarchy.
If you attempted to parent the camera's Transform to the meteor's transform while the Camera component was attached to the meteor object, you're attempting to parent the Transform into itself; if they are on the same GameObject they share the same Transform, you are telling the Transform to become a child of itself. Only when we deal with two separate GameObjects do we have two separate Transforms, then we can make one a child of the other.
Does that clear it up?
That clears it up perfectly! I really appreciate the insight. Thank you!
Your answer
Follow this Question
Related Questions
Make a simple tree 1 Answer
can't parent an Object, a second time. 0 Answers
Prefab, procedural attachment of child, childCount return 0 1 Answer
Rotate parent object so that child is facing camera 0 Answers
Give prefab a parent 2 Answers