I have an object that I want to keep it’s position relative to it’s parent in world space, not in local space. If the parent only translates, I need the child to translate with it, for example, the parent moves right 1, the child moves right 1. However, if the parent only rotates, I need the child to stay still. This object and it’s parent are a prefab, and this relationship is necessary because I am using GetComponentInParent and referencing the object’s transform instead brings “Object reference not set to an instance” errors.
Whenever you rotate the parent, just un-rotate the child.
The easiest method would be to just un-parent it, and make it a sibling of the object, child of an empty object. You rotate the child of an empty object, and call GetComponentInChildren on the parent object. Hierarchy would look like this.
> Empty GameObject Parent
> Rotating Object
> Non-rotating Object
I can’t unparent it, unless you know of a way to reference an object in a prefab without triggering the “Object reference not set to an instance” error.
The second easiest way would be to reset the localPosition & localRotation to whatever they need to be whenever the transform changes.
private Vector3 requiredLocalPos;
private Vector3 requiredLocalRot;
void Awake()
{
requiredLocalPos = transform.localPosition;
requiredLocalRot = transform.localRotation;
}
void Update()
{
if (transform.hasChanged)
{
print("The transform has changed!");
transform.localPosition = requiredLocalPos;
transform.localRotation = requiredLocalRot;
transform.hasChanged = false;
}
}
Panda’s solution would avoid this issue. The empty root object would be the root of the prefab.
And I think you can simplify Panda’s even farther:
As long as you don’t care if the object is rotated during some intermediate timeframe, you don’t need the unparent / parent.
Simply rotate the parent object as you wish, which WILL rotate the child.
Finally just implement a LateUpdate()
that asserts the rotation of the child to be whatever you want.
You can even make a script to test in the editor if you add [ExecuteInEditMode]
attribute.
Here is some timing diagram help:
https://docs.unity3d.com/Manual/ExecutionOrder.html
EDIT: it works pretty solidly. Set your scene up like this:
and this is GyroHead.cs:
using UnityEngine;
// @kurtdekker - put this on a child object and it will remain
// level regardless of what any hierarchy above it is doing.
[ExecuteInEditMode]
public class GyroHead : MonoBehaviour
{
void LateUpdate ()
{
transform.rotation = Quaternion.identity;
}
}
How would I set it’s position to the required position?
How would that avoid the issue? Explain.
That doesn’t work because it would still rotate around the object. I need it to remain stationary relative to the parent, the parent needs to rotate independently from the child.
- You make Empty Parent GameObject the Root of the Prefab
- In your code, you rotate Child Object 1, which won’t rotate the entire Prefab
- When you move your object, you move the Empty Parent, which will move the entire Prefab, including both children
If you’re getting Null Refs it’s because you have to adapt your code, not because the solution doesn’t work.
I think you would also need to assert the position relative to the parent every frame, as with this idea the object will move around the parent, but will face the same direction. You would either need to somehow save the local position data beforehand and then set the localPosition every LateUpdate, or if it doesn’t ever move relative to the parent, just set its localPosition to whatever you want every LateUpdate.
It totally would still work… just reparent!!
FIXED ROTATION LOCAL POSITION(0,0,0) with my script above on it
RELATIVE CUBE OFFSET AWAY```
I know that, however, I don’t know how I would adapt my code to be able to reference something in a prefab.
This would only be a problem if the component that makes the object move wasn’t attached to an object contained in the prefab.
Can you elaborate a little on what, exactly, you’re implementing here? That might help.
The parent has a variable that changes, the child needs to read that. The parent and child are a prefab, and so when I try to reference the parent without GetComponentInParent, it pulls an “Object reference not set to an instance” error. I either need to be able to reference an object in a prefab with no errors, or prevent the child from moving when the parent rotates. If this isn’t clear enough, I would be happy to further elaborate.
Transform point can be used to achieve this along with inverse transform point:
To reference something in a prefab ask for the prefabs child count or component type attached to which child of the count.
If you know the prefab has 6 children you can talk whatever one of those children if you know the child number.
I figured out a solution! transform.parent.parent.Find("Sibling").gameObject.GetComponent<Script>()
Then I used a position constraint. Thanks for all you’re help!
If they’re both in a prefab, can’t you just set ‘Script’ using an Inspector Variable?
You should always try to minimize the amount of traversal across hierarchies, since that’s very easy to break (by changing the hierarchy or by changing the name of a GameObject if you use Find()).