Midair Strafing

I’m making a flying game where the ship has hovering style controls. I want to have it be able to strafe left and right while hovering. The problem is, if I strafe left and right while the ship is banked (i.e. during a turn) then it strafes up or down as well. If I set the transform.translate to be relative to world space then it doesn’t have that problem, but then it will always go left and right relative to the world and not the direction of the ship.

So the question is, how can I make the ship strafe right or left relative to the way it is facing while keeping it’s height constant relative to the ground.

Note: This is not physics based. I am not using a rigidbody and I would prefer to keep it that way.

Any help would be greatly appreciated.

Couldn’t you save the world Y position, have it strafe relative to the ship, then set the world Y position back to what you saved?

The best way to split the movements is to split the objects: make an empty object which will effectively turn, strafe and move forth/back, and child to it another object which will fake the banking. If it’s a first person game, you should child the camera to the inner object; if the camera is external, child the 3d ship model to the inner object. You can place the control script in the external object, find the inner one with Find(“innerName”) and tilt it around Z when banking with localEulerAngles:

var bankSpeed: float = 2.0; // set the bank speed

function Update(){
  var bankAng = 0.0;
  ... // do the main object movement, and set bankAng to the desired banking angle
  var inner:Transform = Find("Inner"); // get child object called "Inner"
  inner.localEulerAngles.z = Vector3.Lerp(inner.localEulerAngles.z, bankAng, Time.deltaTime * bankSpeed);
}

EDITED: That’s a simple example on how to bank in the correct order (avoid Rotate: it accumulates errors and the model may get more and more skewed):

function Update(){
	var v = Input.GetAxis("Vertical");
	var h = Input.GetAxis("Horizontal");
        // move the external object using v and h then do the banking:
	var inner = transform.Find("Inner");
	inner.localEulerAngles.x = v*15; // forth/back banking first!
	inner.localEulerAngles.z = -h*15;  // left/right
}

Could you not take the cross product of your ships forward vector and a world up vector to get one direction. Then flip it to get the other direction?

Edit: Something like the following. Give it a try I’m not sure if it will work. You may have to swap the directions because the cross product depends on the hand rule of the world coordinate system.

Vector3 leftDirection = Vector3.Cross(this.transform.forward, Vector3.up).normalized;
        Vector3 rightDirection = -leftDirection;