Keyboard Camera Movement - how to go forward/backward with a rotated transform?

I have a GameObject with a camera component. I’ve attached the following script. I also have a Plane for a the ground.

Everything is working as expected with the exception of the up and down arrow keys. The are working correctly as coded, that much I understand. The GO transform is rotated a bit so “transform.forward” is pointing down a bit so going forward takes you through the Plane and backward take you out of the plane.

My question is how do I change the code so the camera moves “correctly”. I would like the up and down keys to move you along the Plane same as the left and right keys do, regardless of the transforms rotation x.

using UnityEngine;
using System.Collections;

[RequireComponent (typeof (Camera))]
public class WorldEditorCamera : MonoBehaviour {
	public Camera cam;

	private float _zoom = 20.0f;
	private float _mouseZoomSpeed = 80.0f;
	
	private float _orbitXSpeed = 240.0f;
	private float _orbitYSpeed = 123.0f;
	private int _orbitYMin = 35;
	private int _orbitYMax = 85;
	private float _orbitX = 22.0f;
	private float _orbitY = 33.0f;

	private Transform _transform;
	private Vector3 _position;
	private Light _light;

	public void Start () {
		_transform = transform;
		_transform.localPosition = new Vector3(0f, 20f, 0f);
		_position = _transform.position;

		_orbitX = 22f;
		_orbitY = 33f;
		
		cam = gameObject.GetComponent<Camera>();

		// Make the rigid body not change rotation
		if (GetComponent<Rigidbody>())
			GetComponent<Rigidbody>().freezeRotation = true;
	}

	public void Update () {
		// Update position
		if(Input.GetKey(KeyCode.RightArrow)) {
			_position += _transform.right * _orbitXSpeed * Time.deltaTime;
		}
		if(Input.GetKey(KeyCode.LeftArrow)) {
			_position -= _transform.right * _orbitXSpeed * Time.deltaTime;
		}
		if(Input.GetKey(KeyCode.UpArrow)) {
			_position += _transform.forward * _orbitXSpeed * Time.deltaTime;
		}
		if(Input.GetKey(KeyCode.DownArrow)) {
			_position -= _transform.forward * _orbitXSpeed * Time.deltaTime;
		}

		// Update rotation
		if (Input.GetKey(KeyCode.A)) {
			_orbitX += _orbitXSpeed * 0.02f;
		}
		else if (Input.GetKey(KeyCode.D)) {
			_orbitX -= _orbitXSpeed * 0.02f;
		}
		if (Input.GetKey(KeyCode.W)) {
			_orbitY += _orbitYSpeed * 0.02f;
		}
		else if (Input.GetKey(KeyCode.S)) {
			_orbitY -= _orbitYSpeed * 0.02f;
		}
		_orbitY = ClampAngle(_orbitY, _orbitYMin, _orbitYMax);

		// Update zoom
		_zoom += -Input.GetAxis("Mouse ScrollWheel") * _mouseZoomSpeed * 0.02f;
		_zoom = Mathf.Clamp(_zoom, 15, 100);
	}
	
	public void LateUpdate () {
		Quaternion rotation = Quaternion.Euler(_orbitY, _orbitX, 0.0f);
		Vector3 position = rotation * new Vector3(0.0f, 0.0f, -_zoom) + _position;
		
		_transform.rotation = rotation;
		_transform.position = position;
	}
	
	public static float ClampAngle (float angle, float min, float max) {
		if (angle < -360.0f)
			angle += 360.0f;
		if (angle > 360.0f)
			angle -= 360.0f;
		return Mathf.Clamp (angle, min, max);
	}
}

use Vector3.up instead of transform.up for a “Straight up” vector.

Also in ClampAngle you should use modulus

angle = angle % 360;
return Mathf.Clamp (angle, min, max);

Thanks for the fix with the clamp.

I’m looking for the “Up Arrow” to move the camera forward level with the Plane, not up/down into the air. It still has to reference the transform somehow because the player could have used the “A” or “W” keys to rotate the camera.