- Home /
Simulate Child Parent Relationship (parent constraint)
There seems to be another question like this with no solution: http://answers.unity3d.com/questions/516217/simulate-child-effect-by-script.html
My end goal is to be able to have the same effect of attaching colliders to bones without having to add the component to the bone. This will make an easy swap or switch of the model.
What the script should do is... put it on the GameObject you want to be the child and pass in the GameObject you want to be the parent in the parameters. The child will act just as if you put underneath the parent.
It seems that all the information necessary is the initial position of child, initial position of parent, and the initial rotation of the parent. I could be wrong on that one.
I have tried a bunch of things and tried to use Transform.RotateAround, Vector3.Angle but I can't seem to get a solution.
I have to somehow rotate around the parent the amount to get the initial positions relationship equal.
If anybody knows the math/relationship between the parent child then please explain.
I have been racking my brain for hours and maybe am trying too hard at this.
Here is the script atm:
using UnityEngine;
using System.Collections;
// Apply this script to a object you want to move with bone
public class SimulateChildOf : MonoBehaviour {
public GameObject correspondingParent;
private Vector3 initialObjectPosition;
private Vector3 initialCorrespondingBonePosition;
private Quaternion initialCorrespondingBoneRotation;
// Use this for initialization
void Start () {
this.initialObjectPosition = this.transform.position;
this.initialCorrespondingBonePosition = this.correspondingParent.transform.position;
this.initialCorrespondingBoneRotation = this.correspondingParent.transform.rotation;
}
// Update is called once per frame
void Update () {
// Update the position
this.transform.position = this.correspondingParent.transform.position + (this.initialObjectPosition-this.initialCorrespondingBonePosition);
// Update the rotation
}
}
What are you looking to do ? Create a body + joint + body mechanism that responds to collisions ? Where one body is the child of the other ?
From op: "$$anonymous$$y end goal is to be able to simulate the effect of attaching colliders to bones without having to add the component to the bone. This will make an easy swap or switch of the model." - The colliders need to respond to say turret movement.
ok I guess there are some things I didn't understand in the original post
$$anonymous$$y end goal is to be able to simulate
Why simulate it ? why not just do it ?
the effect of attaching colliders to bones
Are the bones joined ?
without having to add the component to the bone
Which component ?
maybe I'm just slow tonight but I'm missing so much of the context of your problem that there are multiple ways for me to interpret / misinterpret it.
$$anonymous$$aybe simulate is not the best word, but mimic/do the parent-child relationship. When you attach a collider to a bone it moves with the bone. The bones are in a chain, yes but why does that matter?. I do not want to have to add a box collider component for example to the bone every time I swap or update the model/mesh.
Perhaps you are looking at the problem from the wrong end: You need a solution for model-swapping that allows colliders to be updated (re-added) automatically as well. Correct?
Answer by AdenFlorian · Aug 18, 2013 at 10:25 PM
This is good as I can get it.
http://hastebin.com/puwuqoreji.vala
Everything works how it should except for the scale of the child object. When scaling the parent, the child's position will be changed as expected, but I can't get it to scale itself the way you would expect, because there is no built in way to scale something in world space.
There probably is a way to make a scale function, but I've spent enough time on this.
There is a bool you can turn on if you want to use the possibly inaccurate scaling, but it only works in certain situations, like if the rotations of the child and parent match at the beginning of the game, then it should work right.
I also left in some of the child scale code I was working on, although I don't think it is of any use, because you can't skew an object with just localScale.
using UnityEngine;
using System.Collections;
public class Child : MonoBehaviour {
public Transform parentTransform;
// If true, will attempt to scale the child accurately as the parent scales
// Will not be accurate if starting rotations are different or irregular
// Experimental
public bool attemptChildScale = false;
Vector3 startParentPosition;
Quaternion startParentRotationQ;
Vector3 startParentScale;
Vector3 startChildPosition;
Quaternion startChildRotationQ;
Vector3 startChildScale;
Matrix4x4 parentMatrix;
void Start () {
startParentPosition = parentTransform.position;
startParentRotationQ = parentTransform.rotation;
startParentScale = parentTransform.lossyScale;
startChildPosition = transform.position;
startChildRotationQ = transform.rotation;
startChildScale = transform.lossyScale;
// Keeps child position from being modified at the start by the parent's initial transform
startChildPosition = DivideVectors(Quaternion.Inverse(parentTransform.rotation) * (startChildPosition - startParentPosition), startParentScale);
}
void Update () {
parentMatrix = Matrix4x4.TRS(parentTransform.position, parentTransform.rotation, parentTransform.lossyScale);
transform.position = parentMatrix.MultiplyPoint3x4(startChildPosition);
transform.rotation = (parentTransform.rotation * Quaternion.Inverse(startParentRotationQ)) * startChildRotationQ;
// Incorrect scale code; it scales the child locally not gloabally; Might work in some cases, but will be inaccurate in others
if (attemptChildScale) {
transform.localScale = Vector3.Scale(startChildScale, DivideVectors(parentTransform.lossyScale, startParentScale));
}
// Scale code 2; I was working on to scale the child globally through it's local scale, but turned out to be impossible using localScale
/*
Vector3 modVec;
float angleX = Mathf.Abs(Vector3.Angle(transform.right, parentTransform.right));
modVec.x = Mathf.Abs(angleX - 90) / 90;
float angleY = Mathf.Abs(Vector3.Angle(transform.up, parentTransform.up));
modVec.y = Mathf.Abs(angleY - 90) / 90;
float angleZ = Mathf.Abs(Vector3.Angle(transform.forward, parentTransform.forward));
modVec.z = Mathf.Abs(angleZ - 90) / 90;
transform.localScale = Vector3.Scale(startChildScale, Vector3.Scale(DivideVectors(parentTransform.lossyScale, startParentScale), modVec));
*/
}
Vector3 DivideVectors(Vector3 num, Vector3 den) {
return new Vector3(num.x / den.x, num.y / den.y, num.z / den.z);
}
}
The script I have in the op already does position no problem and it is important to atleast have rotation (not worried about scale at this time). The only usable thing I read was this:
In Start(), just change transform.parent to whatever you want the parent to be. When play stops, it will become unparented like how it was before the game started. Sounds perfect for what you want.
BUT this is not a fool-proof solution. Say you wanted to do this where the location in the hierarchy mattered like a camera or wheelcollider, then your plan falls short.
I feel like an idiot. I didn't see the code in your question for some reason.
So do you need the child to rotate around the parent when the parent is rotated?
do you need the child to rotate around the parent when the parent is rotated?
Correct :)
Another idea is to create a GameObject that kind of acts as a buffer. This GO would be a child of the bone in the hierarchy, but it starts at the position of your collider object. Then use the script to match the collider objects transform to the buffer object's.
That defeats the purpose of ease of use when swapping models.
Your answer
Follow this Question
Related Questions
Rotating a parent-child pair 2 Answers
Camera rotation around player while following. 6 Answers
Make a simple tree 1 Answer
Children Objects move weird 1 Answer