Unity Spaceship Tutorial

So, say I was just starting out in Unity, and I wanted to make a space game. The first thing I want to program? the ship! The problem? I can’t program to save my life! (this is not me by the way, just a hypothetical situation ;)) So, if this is you, or maybe even if it’s not, read on!

ShipController(Realistic).js, a script I made with the purpose of controlling spaceships in mind. Note: you may use this free for commercial and non-commercial applications, however, please do not sell this in a package or by itself on the asset store or other publishing services without my consent.

Ok, the script can be found below. So how do you use it? Set up unity as such:

your spaceship, z facing forward, y up and x to the right. Add a rigid-body component. Attach this script.

What do all the variables mean? turnspeed: the rate of roll, pitch and yaw (more on that later). speed: self-explanitory. trueSpeed: the current coefficient for speed. strafeSpeed: the strafing rate. Ok, so, here’s how it works: pressing your power buttons turns up and down your trueSpeed value, it then adds force based on this value using speed as a multiplier. pressing your strafe axes causes the ship to go along the x or y axis. your other buttons add torque corresponding to roll, pitch (up and down) and yaw (left and right). pressing backspace automatically sets trueSpeed to 0 (useful for stopping).

So, how do you set up your axes?

First, go into Project Settings –> Input, then name some axes accordingly

Yaw, Pitch, Roll, Power, and Horizontal and Vertical for strafing. you can expand the amount of axes using size. Mine is set to 21. I recommend setting up the actual keys like this (Note, strafe is supposed to be w, a, s and d, do not be confused by the fact that it’s only pointing to d):














So now you are on your way to making a great space game! Tweak the values (note: you may need to try some very high values to get it to work), test the game, and if you come up with anything cool, please leave me a comment!

var turnspeed = 5.0;
var speed = 5.0;
private var trueSpeed = 0.0;
var strafeSpeed = 5.0;

function Update () {

	var roll = Input.GetAxis("Roll");
	var pitch = Input.GetAxis("Pitch");
	var yaw = Input.GetAxis("Yaw");
	var strafe = Vector3(Input.GetAxis("Horizontal")*strafeSpeed*Time.deltaTime, Input.GetAxis("Vertical")*strafeSpeed*Time.deltaTime, 0);

	var power = Input.GetAxis("Power");

	//Truespeed controls

	if (trueSpeed < 10 && trueSpeed > -3){
	trueSpeed += power;
	if (trueSpeed > 10){
	trueSpeed = 9.99;	
	if (trueSpeed < -3){
	trueSpeed = -2.99;	
	if (Input.GetKey("backspace")){
		trueSpeed = 0;

	rigidbody.AddRelativeTorque(pitch*turnspeed*Time.deltaTime, yaw*turnspeed*Time.deltaTime, roll*turnspeed*Time.deltaTime);

Published by


(stopsecretdesign.wordpress.com) I have been doing 3d for awhile now and have become skilled in both the worlds of 3d design and game development. As such, i have created a blog to show my artistic talent and share tutorials with others :)

89 thoughts on “Unity Spaceship Tutorial”

  1. Amazing. I’ve seen all kinds of code for moving a spaceship. I can hardly believe how the number of movement your 30 lines of code have. How do you control the camera and what are your setting for the rigidbody?

    1. Thanks! 😀
      I think I got my camera script from somewhere on here:
      You can probably find it using their search button.
      Glad you enjoy it, and I hope you can use it well in your games! 🙂
      For the rigid body, if you’re making a spaceship, you will want to uncheck ‘use gravity’, of course, and then you may want to turn up ‘drag’ and ‘angular drag’ to maybe something like ‘3’ and ‘5’ respectively? I guess it really depends on what you want the feel for your spaceship to be. Maybe 0 and 0 if you want to be like real space, 10 and 10 if you want to go unrealistic and fun. Note: if you turn up the drag, you should also turn up your speed variables. Have fun! 😉

  2. I am also curious to know about how you handle collisions with the asteroids. My spaceship jumps off of asteroids when colliding. :p

  3. Good job

    But I, I have a question can be far from the topic

    I’m new at unity and work on aspce war game and I have a problem in moving the spaceship on the terrain as it after a certain distance losing control of it (at the end of the terrain it Become as athing which fall from the table-top )

  4. hi i have problem in setting up this Yaw, Pitch, Roll, Power, please can you tell me how to do it correctly by input manager as iam new to unity

    1. For setting it up, go to the menu Edit –> Project Settings –> Input in Unity. Now change the name of horizontal to Yaw, and remove the alt negative and positive keys. Change the name of Vertical to Pitch, and delete the alt positive and negative keys. If you want to make a new one, change the ‘size’ at the top from 17 to 18, one more. Then call it ‘Roll’ or ‘Power’. Set the gravity and sensitivity to 3, and check ‘snap’. You can then input the positive and negative buttons you want. Repeat for the next one, setting size from 18 to 19, except in the next one, the controls should be copied over from 18, so you shouldn’t have to change much. Hope this helps!


      1. hrllo there.

        I need HELP please.

        i am trying to make a futuristic space racing game using Unity 3.5.

        i am new to scripting in unity and i think this is a good script for my cause but i have one problem: i have rigboddy on and gravity for it unchecked like you said, but i cant seem to get to grips wth setting up the axis from the point when you said the sentence “If you want to make a new one, change the ‘size’ at the top from 17 to 18, one more. Then call it ‘Roll’ or ‘Power’” (your reply to tims comment on the fifth of July 2012. can anyone help me please? i need help As Soon As Possible please.

        thank you and Kind Regards.

      2. hello waylonlathers / other people.

        first off, i think this script is perfect for my needs ( futuristic racing game set in space – for now).
        seconly: i have looked at your reply to the comment by tim to get an idea on what i should do and i understood evrything up untill when you said the sentence: ” If you want to make a new one, change the ‘size’ at the top from 17 to 18, one more. ”

        can anyone help me on this please? any helpfull information will be very apreciated.

        please reply As Soon As Possile please.

        Thank You in Advanced ad Kind Regards

        3D and 2D Model-and-Game Developer for my mini-company “Delta-Tech Productions”

        P.S. if anyone would like to know more about my mini-company please e-mail me at:

        thanks again

      3. Hello Delta-Tech. The axes in the script are ones that are not default to Unity, thus, merely importing the script and running it will NOT work. You must go into a menu in Unity that handles the Input. You must then make new axes. You can change the settings in the default axes to get roll pitch and yaw, or you can select the number at the top ‘Size’ and raise this number to create new axes.
        All that sentence means is that you should create new axes.

  5. Hey, nice script! You should use FixedUpdate to apply forces to rigid bodies. That will make your game slightly more performant and reactive.

  6. Cool thanks for the code! I have sort of got it half to work. I’m just struggling with the project settings >Input part.
    Do you perhaps have a more detailed explanation of these setting for us newbies please?

  7. My ship seems to fall right off the bottom of the screen, as if there is gravity pulling it down? Also new-ish to unity, not quite sure how to fix.

  8. I’m pretty new to Unity and scripting in general. Is there anything I need to change in the script or input settings to make it work? I’ve done all you’ve said without changing one thing and it will not move. Should I be scripting the rotation myself or does the code already cover that and I’m just being dumb?

    Any suggestions?

  9. Hi there..brilliant script mate ! Everything works perfectly for me except from one thing.. When my spaceship speeds up It goes up like an elevator not forward like a car or something that accelerates towards something else!! what do I have to modify to change this effect ??

    1. I actually just found the solution, although I still don’t know what caused this. All I did was to take the multiplication (truespeed*speed*time.deltatime) from the rigidbody,addrelativeforce and place it in the position of y axis with a negative sign in the front (-). I did that because when I tested the multi in all the different axis, x was accelerating towards the right, y was accelerating backwards and z was accelerating upwards. So I thought that my model might be rotated towards the wrong axis (like having the y axis parallel on top of the model) but even when I changed the rotation the problem still existed. With the negative sign before the multiplication everything turned back to normal.. If someone knows the root of the problem please let me know cause I still need to understand the code and not just use it without knowing what it does. Thanx in advance..

      1. I had some of the same stuff happening because I have my ship rotated 270 degrees on the x-axis to align it directly with the Y axis pointing up and the X axis pointing to the right. It’s a matter of translating it for your script.

        BTW, Thanks Waylon! Great script.

  10. your info on the input is not clear. Unity by default assigns several controls but none can be related to your yaw, pitch, power etc. please be more clear on this section. other than that most people wont have a problem with your script.

  11. I don’t remember changing the /edit/project settings/input, but there are
    19 axes
    1.Yaw pos button-left
    neg button-right
    2.Pitch -neg button -down
    pos button -up
    18.Roll- neg button q
    pos button w
    19-Power neg button z
    pos button a

    Just change the size to 19 (default is 15?) and put in these 4, remember to
    change the ‘Name’ to “Yaw”, Pitch, Roll, Power, don’t think you have to change
    anything else

  12. i am getting an error message saying this
    UnityException: Input Axis Roll is not setup.
    To change the input settings use: Edit -> Project Settings -> Input
    fly.Update () (at Assets/fly.js:8)
    what does this mean and how do i sort it out

  13. Thanks a lot for your code. I want to use this for a touch input space game. How Do I convert the movement to touch inputs.

    1. I’ve never done touch stuff before, but to get roll pitch and yaw in, you could have a moveable button like you see in first person controllers on the left that controls pitch and yaw, and a slider like control on the right for roll.

  14. Thanks a lot. Am wondering is it possible to use same input setting and can just use GUI texture to enable touch movements?

  15. Hi, I have followed the same above steps and also modified the input settings. My ship is very stubborn It doesn’t move. Any one got a clue?.

    1. Do I need to modify any gravity, Dead and Sensitivity in Input Manager. If so can you be kind enough to post some values. (I have read the previous comments and tried the values 😦 but my ship is very bad doesn’t move)

    2. I have added rigid body to my ship with Mass = 1, Drag = 3, Angular Drag = 5.
    Is there anything else need to be done for this values?

    3. Between Am using C# Script so I converted Java to c#, is that might be a problem, But in the editor it doesn’t show up any error.


    public class simpleMovement : MonoBehaviour

    public float turnspeed = 5.0f;
    public float speed = 5.0f;
    private float trueSpeed = 0.0f;
    public float strafeSpeed = 5.0f;

    void Update()

    float roll = Input.GetAxis(“Roll”);
    float pitch = Input.GetAxis(“Pitch”);
    float yaw = Input.GetAxis(“Yaw”);
    Vector3 strafe = new Vector3(Input.GetAxis(“Horizontal”)*strafeSpeed*Time.deltaTime, Input.GetAxis(“Vertical”)*strafeSpeed*Time.deltaTime, 0);

    float power = Input.GetAxis(“Power”);

    //Truespeed controls

    if (trueSpeed -3){
    trueSpeed += power;
    if (trueSpeed > 10){
    trueSpeed = (9.99f);
    if (trueSpeed < -3){
    trueSpeed = (-2.99f);
    if (Input.GetKey("backspace")){
    trueSpeed = 0;

    rigidbody.AddRelativeTorque(pitch*turnspeed*Time.deltaTime, yaw*turnspeed*Time.deltaTime, roll*turnspeed*Time.deltaTime);



    1. If you’re worried about the values, try using Input.GetAxisRaw instead of GetAxis. This will return a one value instantly when the positive button is pressed. Also, if you’re worried about the ship’s movement, try crazy values of speed like 100000. If the ship does move, then it’s just a matter of adjusting.

      1. I did what you said and it says Input.GetAxisRaw is not set up i have tried to remove and add back the rigibody and gravity but this error shows up when i do what you suggested with this comment. Befor there were no errors the ship just wouldn’t budge. I am confused as to what is wrong at this point i have change the code from c# to javascript numerous times and the ship will not move please help?

  16. Thanks a lot for your quick reply. I tried with various speed parameters and also tried with some crazy values. yet ship doesn’t seem to move.


    public int turnspeed = 5;
    public int speed = 5;
    private int trueSpeed = 0;
    private Transform mTransform;

    void Start()
    mTransform = transform;
    mTransform.position = new Vector3 (-3,-3,-1);

    void Update() {

    If I try with this it moves. I don’t understand why?, Any help would be much appreciated. Is it because I have not applied transfrom. translate or is it because of rigid body. AddRelative Torque. Please help me to solve this issue.

    1. Make sure the rigidbody’s rotation and position aren’t locked (there’s a set of 6 boxes for this under, I think it’s rigidbody constraints) and make sure it’s non-kinematic. I don’t know if I can help you much beyond that. Except try making a new scene, just adding a box with rigidbody to the scene and running that.

  17. Thanks, for you reply. Finally I figured out the problem. It is because of void Fixed Update. Now it works fine. It is because I should not use void Update if i used void update fixed it works. Feeling very better. Thanks a lot for your support. Now I need to figure out how to put touch controls to it, Have you got any links?

  18. Thanks a lot, Will deefnitely try. Between, I need to know how to control partcle system. If I touch gas button for few second the particle should appear and if we let off the gas button slowly particle system should fade off.

  19. {
    public GameObject asteroidPos;
    public GameObject asteroidPrefab;

    public float fieldRadius;
    public float size;
    public float movementSpeed;
    public float rotationSpeed;

    void Start()
    StartCoroutine(loopFunc()); // Asteroid Timer is called

    // Asteroid Timer for pupulating Asteroids in the Scene
    IEnumerator loopFunc()
    yield return new WaitForSeconds(3);// Asteroids are called for each (??) Seconds


    // Populating Asteroid
    void populateAsteroids()

    for(int i = 0; i 50)

    i = -5;


    GameObject newAsteroid = (GameObject)Instantiate(asteroidPrefab, Random.onUnitSphere* fieldRadius,Random.rotation);

    float size = Random.Range(0.3f, 2);
    newAsteroid.transform.localScale = Vector3.one * size;

    newAsteroid.rigidbody.velocity = Random.insideUnitSphere * movementSpeed;
    newAsteroid.rigidbody.angularVelocity = Random.insideUnitSphere * rotationSpeed;




    I have created this asteroid random populating script, after a deep research. The problem is , I need to destroy the object after few seconds, AM currently able to populate it for every few seconds.

    I do also want this asteroid to populate only in place where the spaceship moves how to do that. Please help, Thanks in advance.

    1. Whoa! Nice! For populating where the ship moves, have a Vector3 store the ship’s old position. Once the position changes a number of units, you can shift the asteroid field in the direction of the ship and repopulate. Also, you can use chunks, which I’m sure you can learn about on the internet (Minecraft uses chunks I think)

  20. When you said that you Set up unity as such:

    your spaceship, z facing forward, y up and x to the right. Add a rigid-body component. Attach this script.
    Do you change where it faces in blender or unity and how?

  21. Hi. I am a noob to unity and I wondered if you can tell me how to make the spaceship shoot and how i can detect the lazer/bullet thing to lower another ships damage. Thank you

  22. @waylonlathern

    Thanks for the script this was really useful.
    I had a similar problem as a few other folks here where the default script seemed to not move the ship (it actually DID move just imperceptibly slowly) even after pushing the speed values up to 85000. After removing the Time.deltaTime multiplication things started moving properly. Thanks again!

    1. Hi there Arakiel! Although it likely worked, I would not recommend the removal of this element. As far as I understand, Time.deltaTime keeps the ship moving at a constant speed. Without this, your ship’s speed is dependent on frame rate. http://docs.unity3d.com/Documentation/ScriptReference/Time-deltaTime.html good example. I would recommend instead multiplying by *10000 or something like that after the time.deltaTime. I want to make an updated version of this tutorial at some point 🙂

      1. Hey waylonlathern
        Thanks for that explanation. I went back and re-added the deltaTime and put some more effort into figuring out the problem. Finally realized that I was using an object with a Mass of 500, which is likely why my outcome was so different. Working great now, thanks!

  23. I have modified your script (very good and simple) to act as I think it may be usual in the space (with inertia)

    Here you have (sorry for some comment in Spanish). The script is written in C#

    using UnityEngine;
    using System.Collections;

    public class SpaceshipControl : MonoBehaviour {
    // source from https://stopsecretdesign.wordpress.com/2011/09/19/unity-spaceship-tutorial/

    public float turnspeed = 5.0f;
    public float speed = 5.0f;
    private float trueSpeed = 0.0f;
    public float strafeSpeed = 5.0f;

    public Vector3 strafe;

    // aplicamos los valores reales
    public float r_roll = 0.0f;
    public float r_pitch = 0.0f;
    public float r_yaw = 0.0f;
    public Vector3 r_strafe;
    public float r_power = 0.0f;
    public float r_h = 0.0f;
    public float r_v = 0.0f;

    public float valor_incremental = 0.1f; // valor incremental para los movimientos de la nave, salvo la energía y la velocidad
    public float valor_incremental_power = 0.01f; // la velocidad no se puede incrementar igual que el resto de parámetros, ha de ser más suave

    void Update()
    // recogemos las teclas
    float roll = 0.0f;
    float pitch = 0.0f;
    float yaw = 0.0f;

    float power = 0.0f;
    float h = 0.0f;
    float v = 0.0f;

    // Este código mantiene las inercias para que la nave se comporte como una nave en el espacio real

    roll = Input.GetAxis(“Roll”);
    if (roll != 0.0f)
    r_roll += GetRealValue(roll);

    pitch = Input.GetAxis(“Pitch”);
    if (pitch != 0.0f)
    r_pitch += GetRealValue(pitch);

    yaw = Input.GetAxis(“Yaw”);
    if (yaw != 0.0f)
    r_yaw += GetRealValue(yaw);

    h = Input.GetAxis(“Horizontal”);
    if (h != 0.0f)
    r_h += GetRealValue(h);

    v = Input.GetAxis(“Vertical”);
    if (v != 0.0f)
    r_v += GetRealValue(v);

    strafe = new Vector3(r_h * strafeSpeed * Time.deltaTime, r_v * strafeSpeed * Time.deltaTime, 0);

    power = Input.GetAxis(“Power”);
    if (power != 0.0f)
    // si el valor es negativo devolvemos el incremento en negativo y en otro caso en positivo
    if (power < 0.0f)
    r_power -= valor_incremental_power;
    r_power += valor_incremental_power;
    trueSpeed += r_power;


    // intentar reducir la complejidad del código
    private float GetRealValue(float valor)
    // si el valor es negativo devolvemos el incremento en negativo y en otro caso en positivo
    if (valor < 0.0f)
    return -1.0f * valor_incremental;
    return valor_incremental;

    void FixedUpdate()
    if (Input.GetKey("space")) // frenazo automático
    trueSpeed = r_power = 0;
    r_h = r_v = r_pitch = r_roll = r_yaw = 0.0f;

    rigidbody.AddRelativeTorque(r_pitch * turnspeed * Time.deltaTime, r_yaw * turnspeed * Time.deltaTime, r_roll * turnspeed * Time.deltaTime);
    rigidbody.AddRelativeForce(0, 0, trueSpeed * speed * Time.deltaTime);


      1. I have just grabbed Fernando’s version of this script and I think it is going to work for me… but… I don’t think I have added the axis correctly.

        Can someone please take a screenshot of their axis and the settings for each of them to make this work.

        Sorry I am very new to Unity and I hope this is not something I should already know!

  24. Hey! Just stumbled across this – pretty new to Unity. Got it working like a charm (including awesome planet skybox :D. My ship won’t go forward though! The power options do nothing. I tried adding a forward axis to the Z parameter on the strafe vector, but that had no effect. Ideas?

  25. Could anyone upload their project and scene with the inputs and script working? I am also having issues with getting the inputs setup correctly…if anyone out there can help please send me an email aovoian@gmail.com

  26. This script is fantastic. I was able to create a flight controller and begin prototyping immediately. How would you approach creating a toggle for Drag? Adding a small amount of drag makes the craft controllable in aerodynamic flight kind of way. Dropping the drag to 0 introduces a more Newtonian/0g situation. I want to toggle between the two in game. Any Ideas?

    1. Hi Justin! up where are the variables are, create a new variable that says
      var newtonian = false;
      Now, under the Update function, add the following code
      rigidbody.drag = 0;
      //This is just an example value, it doesn’t have to be four…
      rigidbody.drag = 4;

      Now, you need some way to switch the two, so let’s add some more code for switching,

      if (Input.GetKeyDown(“r”))
      newtonian = !newtonian;

      Hopefully that will work! 🙂

  27. First of all, thank you for this awesome script. It is working just fine for me, except for one thing…strafing! The other controls are working just fine. strafing isn’t entirely necesssary for what I’m trying to do but it would be nice to get it working. Anyone know what’s wrong? I’ve tweaked all the values in Input settings just to see if anything happens, and I’ve also cranked the strafe speed up. Any ideas? Input settings are as follows:

    Name Horizontal
    Negative Button d
    Positive Button a
    Gravity 3
    Dead .001
    Snap Checked
    Axis X Axis

    Vertical is set up the same way only with ‘w’ and ‘s’, and ‘y axis’ instead of ‘x axis’

    1. aaaaaaand I fixed it. In case anyone had trouble with this, I fixed it by making a new axis. When I did that, I noticed that the default “horizontal” that I was messing with was set to joystick and not button or key! So make sure you look at that.

  28. Hey, thanks once again for the script. I have modified this to make several vehicles, one of which is a pretty complex multipart tank (using hinge joints). I could use transform position/rotation scripts, but this gives a good physical feel to the tank.

  29. Thanks for the script! I wanted a to be able to damp individual axis and wrote this code up to complement your code (I used C# but should be easy to translate to other languages):

    if (EnableRotDamping == true)

    if (Input.GetAxis (“Pitch”) == 0)
    rigidbody.AddRelativeTorque (-rigidbody.angularVelocity.x*MotionRotDamping*Time.deltaTime, 0, 0);

    if (Input.GetAxis (“Yaw”) == 0)
    rigidbody.AddRelativeTorque (0,-rigidbody.angularVelocity.y*MotionRotDamping*Time.deltaTime, 0);

    if (Input.GetAxis(“Roll”) == 0)
    rigidbody.AddRelativeTorque (0, 0, -rigidbody.angularVelocity.z*MotionRotDamping*Time.deltaTime);


    if (EnableStrafeDamping == true)
    if (Input.GetAxis (“Horizontal”) == 0)
    rigidbody.AddRelativeForce (-rigidbody.velocity.x*MotionStrafeDamping*Time.deltaTime,0,0);
    if (Input.GetAxis (“Vertical”) == 0)
    rigidbody.AddRelativeForce (0,-rigidbody.velocity.y*MotionStrafeDamping*Time.deltaTime,0);

    if (EnableZTransDamping == true && TrueSpeed == 0)
    rigidbody.AddRelativeForce (0,0,-rigidbody.velocity.z*MotionZTransDamping*Time.deltaTime);

    1. forgot to add some control feedback to keep everything stable.

      added something like this to each damping command:

      if(rigidbody.angularVelocity.z -zeroControl)
      rigidbody.angularVelocity.z = 0;

  30. Super awesome man! Thank you for posting such simple and effective code! Still works on unity 4.6 even though it’s 3 years old 🙂 Good code never ages I guess!

    I’m working on mobile with a VR headset to put you in the cockpit of a spaceship, this script was the perfect thing for the movement I wanted, the Dive FPS controller just didn’t work after 2 hours of tweaking then I found this. A true time saver and super effective.

    For anyone else that might come here, if you want a tightly controlled ship I set my linear/angular drag to 3 & 5 like he says for arcade like feel, but my turn speed/speed/strafe speed are set to 500/100/400 respectively.

Comments and feedback are appreciated :)

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s