# Two child transform collective forward direction

Hi,

I have a parent object with two children. One child rotates around its local y-axis and another around its local x-axis. I want to move the parent object in the forward direction of the two child object’s collective forward direction. How can this be done?

Thanks.

It sounds like you’re making a terrapin turtle!

Rotating an object does not imply any distance unless you also have a radius in mind, i.e., the radius of the wheel.

In that case, the motion would simply be the vector made up by the two axes coordinate values, and those values would be the rate of rotation times the radius. Post some code if you want some more specific pointers. Be sure to use code tags.

1 Like

Not so much a turtle as an aeroplane. I basically need to move the parent object forward, where forward is determined by the orientation of one (which is pitching) and another (which is yawing). Here is what I have now:

``````void Start() {

// Aircraft transform is comprised of a container (this.transform) and three child transforms
// to allow for independent local rotations.
yzTransform = this.gameObject.transform.GetChild(0);
xTransform = yzTransform.gameObject.transform.GetChild(0);
bodyTransform = xTransform.gameObject.transform.GetChild(0);
}

void Update () {

yaw = Input.GetAxis("Horizontal");
pitch = Input.GetAxis("Vertical");
roll = -yaw;

if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
{
canRoll = true;
}
else
canRoll = false;

RotateAircraft();
MoveAircraft();
}

void RotateAircraft()
{
if (!canRoll)
{
// If roll-key is not pressed, yaw and pitch respective child transforms according to input.
yzTransform.Rotate(new Vector3(0, yaw * rotationSpeed * Time.deltaTime, 0));
xTransform.Rotate(new Vector3(pitch * rotationSpeed * Time.deltaTime, 0, 0));

Debug.Log(roll);

// Animate a slight tilt of the aircraft's body when yawing.
Quaternion modelRotation = bodyTransform.localRotation;
Quaternion toRotation = Quaternion.Euler(0f, 0f, roll * 30f);
bodyTransform.localRotation = Quaternion.Slerp(modelRotation, toRotation, Time.deltaTime * 10f);
}
else
{
// If roll-key is pressed allow only for rolling using horizontal input.
yzTransform.Rotate(new Vector3(0, 0, roll * rotationSpeed * Time.deltaTime));
}
}

void MoveAircraft()
{
transform.position += // something...
}
``````

That’s even easier… just make your plane prefab so that forward is down the +Z axis… then when you move it, you just move it by transform.forward * airspeed and it will move correctly.

In that sense, changes to pitch will be around the X axis, changes to roll will be around the Z axis, and yaw axis changes will be around the Y axis, and the Y axis is driven as a function of “how tight are you turning,” which couples roll with nose pitch.

It’s a SUPER simple flight model, but it’s fun on a touch screen with one finger. It’s what I put in my Pilot Kurt game here:

https://itunes.apple.com/us/app/pilot-kurt/id1153921946

and

It’s not super-useful on its own, but here is the entire flight model Monobehavior if you wanna take a look:

``````using UnityEngine;
using System.Collections;

public class FlightModelOriginal : FlightModel000
{
FlightModelOriginalParameters fmop;

public FlightControlInputs fci { get; private set; }

float MaxAltitude = 100.0f;

public static FlightModelOriginal AttachToStatePlayer ( FlightModelOriginalParameters fmop)
{
fmo.fmop = fmop;
return fmo;
}

void Awake()
{
fci = FlightControlInputs.Attach (gameObject);

TimeFilteredOutput = Vector3.zero;

STATE.PlayerFlightSpeed = 10.0f;
}

public void DestroyThyself()
{
fci.DestroyThyself ();
Destroy (this);
}

Vector3 TimeFilteredOutput;

IEnumerator NoseOverAndDown( GameObject player)
{
Quaternion q1 = player.transform.rotation;
Quaternion q2 = Quaternion.Euler (70, 0, 0);
float NoseOverTime = 1.0f;
for (float t = 0; t < NoseOverTime; t += Time.deltaTime)
{
float fr = t / NoseOverTime;
player.transform.rotation = Quaternion.Lerp ( q1, q2, fr);

player.transform.position += player.transform.forward *
STATE.PlayerFlightSpeed * Time.deltaTime;

yield return null;
}
}

IEnumerator Start()
{
GameObject player = STATE.pf.gameObject;

ServiceCeiling sc = FindObjectOfType<ServiceCeiling> ();
if (sc)
{
MaxAltitude = sc.transform.position.y;
}

while(true)
{
STATE.UpdateCountersAndTimers ();

if (GameModeManager.NeedSpeedIncreasing())
{
STATE.PlayerFlightSpeed += Time.deltaTime * 0.1f;
}

Vector3 rawOutput =fci.GetOutputRaw();

rawOutput += new Vector3( Input.GetAxis( "Horizontal"), Input.GetAxis ( "Vertical"));

if (SETTINGS.InvertXControls)
{
rawOutput.x = -rawOutput.x;
}
if (SETTINGS.InvertYControls)
{
rawOutput.y = -rawOutput.y;
}

TimeFilteredOutput = Vector3.Lerp(
TimeFilteredOutput, rawOutput,
fmop.ControlSnappiness * Time.deltaTime);

float Roll = -TimeFilteredOutput.x;

if (player.transform.position.y > MaxAltitude)
{
yield return StartCoroutine( NoseOverAndDown( player));
}

Roll *= fmop.RollMultiplier;
Roll *= Time.deltaTime;
player.transform.Rotate ( new Vector3( 0, 0, Roll));

float Turn = -player.transform.eulerAngles.z;
if (Turn < 180) Turn += 360;
if (Turn > 180) Turn -= 360;
Turn *= fmop.RollToTurnCoupling;
Turn *= Time.deltaTime;
player.transform.Rotate( new Vector3( 0, Turn, 0));

float Pitch = TimeFilteredOutput.y;

Pitch *= fmop.PitchMultiplier;
Pitch *= Time.deltaTime;

if (fmop.LimitPitchEnabled)
{
float xangle = player.transform.eulerAngles.x;
if (xangle > 180) xangle -= 360.0f;
if ((xangle < -fmop.LimitPitchAngle) &&
(Pitch < 0))
{
Pitch = 0;
}
if ((xangle >  fmop.LimitPitchAngle) &&
(Pitch > 0))
{
Pitch = 0;
}
}

player.transform.Rotate ( new Vector3( Pitch, 0, 0));

player.transform.position += player.transform.forward *
STATE.PlayerFlightSpeed * Time.deltaTime;

yield return null;
}
}
}
``````

You can pretty much delete a lot of that code and stick it on your camera in a scene with your terrain and use the default Unity input axes to control your airplane.

There is no notion of energy at this point. It just goes and goes, climbing or descending.

Yes. I understand that I have to move the parent along a forward vector, the problem is that the parent itself does not actually yaw and pitch. One child yaws and the child of that child does the pitching. So my question is: how do I from the parent move the aircraft so that forward is determined by the rotation of the children collectively?

Components of rotation are not commutative, that is, their order matters. Your keeping the axes of rotation as separate transforms is interesting, but they still need to be combined, generally by a quaternion multiply, to do something useful.

But again, that is not commutative, except for identity values, which are trivial and irrelevant here.

Oh ok. I guess I will go back to trying to achieve something similar to what i have within a single transform then. Thanks for the help!