- Home /
Child-objects are not properly 'transformed' with parent
It's hard to explain so I made a quick video: https://youtu.be/F8cTXPTTljs
Note that the position works correctly when the grid is placed at the world-origin.
I recreated the problem with 2 simple primitive cubes attached to each other through code, but those don't work either (you can see that the attached testcube is not rotated). What's going on here? Why does the 2nd cube not inherit it's paren's rotation?
http://answers.unity3d.com/storage/attachments/43907-cubes.png
using UnityEngine;
using System.Collections;
public class PlacementTest : MonoBehaviour
{
void Awake()
{
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.name = "TestCube";
cube.transform.localScale = new Vector3(8, 8, 8);
cube.transform.position = new Vector3(10, 20, 10);
cube.transform.parent = transform.Find("test").transform;
//transform.Rotate(170, 0, 0);
}
}
Setting the world angles manually (just once) seems to solve this problem at least. Though I do not understand why I have to do this MANUALLY.
using UnityEngine;
using System.Collections;
public class PlacementTest : MonoBehaviour
{
void Awake()
{
CreateCube(new Vector3(10, 20, 10));
CreateCube(new Vector3(0, 0, 10));
}
private GameObject CreateCube(Vector3 location)
{
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.name = "TestCube";
cube.transform.localScale = new Vector3(8, 8, 8);
cube.transform.localPosition = location;
cube.transform.parent = transform.Find("test").transform;
//transform.Rotate(170, 0, 0);
//cube.transform.localEulerAngles = transform.localEulerAngles;
cube.transform.eulerAngles = transform.eulerAngles;
return cube;
}
}
I really don't understand what possibly could be causing these position&rotational problems. I need to know that before I can fix the actual problem below I suppose.
For some reason the child-objects do not correctly move along with their parent's position. But they do for a certain % of their parent's transform...
And they don't rotate at all... But rotating the grid AFTER the cells have been attached does correctly rotate them. I don't understand why they don't take their parent's rotation when they are created and attached to the parent object.
// Creating a childobject and assigning it to it's parent
GameObject obj = Instantiate(GameSettings.Instance.PlacementCellReference); // More or less just a gameobject with a collisionbox
obj.transform.parent = transform.Find("Cells").transform; // Attach the cell to the grid's childnode called "Cells". Hierarchy: [Placementgrid] --> [Cells (empty gameobject)] --> [All the cells go here]
// Parent gizmo (purple grid from video)
void OnDrawGizmos(){
Gizmos.matrix = transform.localToWorldMatrix;
for (int y = 0; y < Rows; y++)
{
for (int x = 0; x < Columns; x++)
Gizmos.DrawWireCube(transform.position + new Vector3(x * PlacementCell.SIZE, y * PlacementCell.SIZE, 0), PlacementCell.SIZE_V3);
}
}
// How the child object positions itself (once):
transform.localPosition = new Vector3(index_x * SIZE, index_y * SIZE, 0);
Note that the childs also did not copy the parent's rotation for some reason. The greenboxes that you saw in the video are the collisionboxes from the children (=PlacementCells).
EDIT:
Here is some more code just in case:
Grid (parent object):
void Awake()
{
Cells = new PlacementCell[Rows, Columns];
for (int y = 0; y < Rows; y++)
{
for (int x = 0; x < Columns; x++)
{
// Create a new game-object and attach it to the "Cells" node
GameObject newCell = Instantiate(GameSettings.Instance.PlacementCellReference);
newCell.transform.parent = transform.Find("Cells").transform;
// Perform the PlacementCell stuff here
//PlacementCell c = obj.AddComponent<PlacementCell>(); // old code
newCell.GetComponent<PlacementCell>().Initialize(transform.rotation, x, y);
Cells[x, y] = newCell.GetComponent<PlacementCell>();
}
}
}
Placement Cell (child):
public void Initialize(Quaternion gridRotation, int index_x, int index_y)
{
this.Index.X = index_x;
this.Index.Y = index_y;
// Set the position of the cell. Take into account that the grid may be rotated.
transform.localPosition = new Vector3(index_x * SIZE, index_y * SIZE, 0);
// Collider
Collider = gameObject.AddComponent<BoxCollider>();
Collider.name = string.Format("{0}{1};{2}", COLLIDER_PREFIX, index_x, index_y);
Collider.isTrigger = true;
Collider.size = new Vector3(SIZE, SIZE, TRIGGER_DEPTH);
}
Try replacing
Gizmos.matrix = transform.localToWorld$$anonymous$$atrix;
with
Gizmos.matrix = $$anonymous$$atrix4x4.TRS(transform.position, transform.rotation, transform.lossyScale);
I had that before and I tried it again now. Changes nothing. Besides, I suppose that the parent's gizmo drawing code is correct. I fear that there is some problem with how I attach the childs to the parent or something.. The children are the ones that don't move&rotate properly. The parent (grid) seems to work properly.
All looks well in the hierarchy.
I added some more code to the op.
Also 2 test-cubes fail to rotate it's children as well. I don't understand how this is possible. As if I have to do something manually before a child-object responds to it's parent rotation? Seems almost like a Unity bug.
Does it happen when you drag your root object by mouse and not hand typing a value in the transform menu? There is no reason as far as i can see why would this happen. I suggest you creating a new project and importing all of your existing files into new project and try again. Seems more like a bug.
I also suspect this to be a Unity-bug. The child-objects not rotating automatically also happens when I drag it. Even with the simple 2-cubes-example.
This is what I did: I place a cube in the editor and rotate it. I create an empty gameobject as it's child named "test", then I attach the sample script "PlacementTest" from the op to it (without the eulerangles fix). And the dynamically generated cube then does not have any rotation whatsoever until I manually set it :/. It also happens in a new clean project with nothing but those cubes and that one single script added.
Then I tried it by adding a new cube as a child through the editor. Then there is no problem and it 'inherits' it's parents rotation. So yes I do believe that this is a bug.
But I did find the solution by accident. I still do not understand why this happens. But at least this solves the problem.
Answer by Napoleonite · Apr 05, 2015 at 08:34 AM
There were 2 problems:
1. (location % offset problem)
//Gizmos.matrix = Matrix4x4.TRS(transform.position, transform.rotation, transform.lossyScale); // Wrong!
//Gizmos.matrix = transform.localToWorldMatrix; // Wrong!
Gizmos.matrix = Matrix4x4.TRS(Vector3.zero, transform.rotation, transform.lossyScale); // Good!
2. (child objects not 'inheriting' their parent's rotation)
The eulerangles from the parent must manually be copied into the child-object. I don't know why Unity does not do this automatically for dynamically created objects but this does solve it for me:
cube.transform.eulerAngles = transform.eulerAngles; // Do this for each child object. cube being the child-object in this example.
However this workaround does cause any gizmo-drawing code for the cells in the grid to bug (applying double rotation) but at least the real transforms & collisionboxes work.
Thank you! Your answer to your own question saved me a lot of headache.
Your answer
Follow this Question
Related Questions
Rotate transform without rotation the children 1 Answer
Camera follow ball along cylinder 1 Answer
Neutralising child rotations -> Parent 1 Answer
transform.childCount == 0, but a child shows up in the hierarchy. How is this possible? 2 Answers
Rotating Children as Rigidbodies2D because transform rotation is too costly 0 Answers