- Home /
Moving objects together without parenting
hello, I have a question about transform movement. So I have a gameobject that's always moving and rotating, and I want another gameobject to move and rotate with the first object(position translation and rotation) just like being a child object, but without actually parenting it in the hierarchy.
For translation, so far I can get a pretty nice movement by 1. first getting the delta position of the "parent" object then adding this delta value to the "child" object.
DeltaPos = parent.position - parent_position_LastFrame;
child.position += DeltaPos;
However what's really bugging me is the rotation. The "child" object does not really rotate like the way "parent" object does if simply getting the delta rotation of the parent and then adding it to child.
I'm kind of confused of which functions to use and if I should take localRotation of each object into consideration(since these two objects in the hierarchy are parented under other different gameobjects....)
Any help is appreciated. Thank you!
How do you want the fake child object to act? Like it is a child and if the parent rotates, it moves position while staying in the same 'local rotation' as it were?
hey. I want the fake child to rotate as well if the parent rotates.
Rotate like an actual child so the parent would be the pivot point or just rotate to match the parent?
Answer by WarmedxMints · Mar 22, 2019 at 03:28 AM
This should do what you are after. Note though if you want to rotate the fake child at all, you would need to create a method to add to the rotation offset variable.
using UnityEngine;
public class FakeChild : MonoBehaviour
{
public Transform FakeParent;
private Vector3 _positionOffset;
private Quaternion _rotationOffset;
private void Start()
{
if(FakeParent != null)
{
SetFakeParent(FakeParent);
}
}
private void Update()
{
if (FakeParent == null)
return;
var targetPos = FakeParent.position - _positionOffset;
var targetRot = FakeParent.localRotation * _rotationOffset;
transform.position = RotatePointAroundPivot(targetPos, FakeParent.position, targetRot);
transform.localRotation = targetRot;
}
public void SetFakeParent(Transform parent)
{
//Offset vector
_positionOffset = parent.position - transform.position;
//Offset rotation
_rotationOffset = Quaternion.Inverse(parent.localRotation * transform.localRotation);
//Our fake parent
FakeParent = parent;
}
public Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Quaternion rotation)
{
//Get a direction from the pivot to the point
Vector3 dir = point - pivot;
//Rotate vector around pivot
dir = rotation * dir;
//Calc the rotated vector
point = dir + pivot;
//Return calculated vector
return point;
}
}
Doesnt work for me :/ i set fakeparent for few objects and they dont move with fakeparent
The scripts works perfectly fine.
You have to attach the script on a gameObject C
and drag & drop the gameObject P
you want into the FakeParent
field of the FakeChild
script. Once you start your game, moving and rotating the gameObject P
will also move and rotate the gameObject C
.
Answer by Henry_Sub · Feb 10, 2021 at 07:16 PM
You guys are making it too complex. It's as simple as this: ( Can't change child's position and rotation after being parented. You may want to script that by yourself if you need)
using UnityEngine;
public class Child : MonoBehaviour
{
public Transform Parent;//Remember to assign the parent transform
private Vector3 pos, fw, up;
void Start()
{
pos = Parent.transform.InverseTransformPoint(transform.position);
fw = Parent.transform.InverseTransformDirection(transform.forward);
up = Parent.transform.InverseTransformDirection(transform.up);
}
void Update()
{
var newpos = Parent.transform.TransformPoint(pos);
var newfw = Parent.transform.TransformDirection(fw);
var newup = Parent.transform.TransformDirection(up);
var newrot = Quaternion.LookRotation(newfw, newup);
transform.position = newpos;
transform.rotation = newrot;
}
}
Thx so much I knew the mathematical way of putting it, but I was in the process of writing matrices operations without knowing all the operation handling unity give us.
This is much more elegant and should be marked as a true answer. Thanks
Answer by Nwy140 · Jun 04, 2021 at 01:51 AM
A solution already exists. You should just use the parent constraint component instead. https://docs.unity3d.com/Manual/class-ParentConstraint.html
That's a great answer! Thanks! It's always better to use what already exists than creating yet another solution
Answer by MAGIK_NASA · Jul 15, 2020 at 05:17 AM
I tried the code from @WarmedxMints above, but it did not work properly. The child object would rotate to a different position before becoming linked. I think this was caused by the child starting with a different rotation than the parent. Below is my code which is cleaner and fixed this problem.
using UnityEngine;
public class FakeChild : MonoBehaviour
{
public Transform FakeParent;
private Transform _thisChild;
private Vector3 _positionOffset;
private Quaternion _rotationOffset;
private void Start()
{
_thisChild = this.transform;
if(FakeParent != null)
{
SetFakeParent(FakeParent);
}
}
private void Update()
{
if (FakeParent == null)
return;
// Position the object on top of the parent
_thisChild.position = FakeParent.position;
// Set the rotation based on the parent and stored offset rotation
_thisChild.rotation = FakeParent.rotation * _rotationOffset;
// Move the child back to the reference location
_thisChild.Translate(_positionOffset);
}
public void SetFakeParent(Transform parent)
{
//Offset vector
_positionOffset = _thisChild.InverseTransformPoint(_thisChild.position) - _thisChild.InverseTransformPoint(parent.position);
//Offset rotation
_rotationOffset = Quaternion.Inverse(parent.rotation) * transform.rotation;
//Our fake parent
FakeParent = parent;
}
}
This solution worked great for my situation, thank you!
I'm getting weird offset issues with the child object. When setting up the fake parent it makes the child higher than where placed in the scene.
Answer by Cornelis-de-Jager · Mar 22, 2019 at 03:33 AM
Simple script for mimicking rotation and position
[SerializedField]
Transform fakeParent;
Vector3 offset;
void FixedUpdate () {
transform.rotation = fakeParent.rotation;
transform.position = fakeParent.position + offset;
}
It's got a drawback that the child can't have its own direction.