Using the camera to follow a simplified 3d spaceship
Hi!
I'm new to Unity 3D, as in i'm on my first week. I got basic knowledge of C++, understanding the C# codes is doable, as in i can get a good geuss of what it's doing. To write anything usefull on my own is still a bigger challenge.
I succesfully completed the roll a ball and asteroids tutorial. I made my own scene. Searched some usefull assets. A ship model, this is not important now, i'm not using it yet. An earth material with a spin speed which i attached to a big sphere some distance of world origin. This is purely so you can see actually something when launched. I put it in face of the camera so you can see it on launch and when controls are used it's easy to tell they work. I added really simple lighting with a directional light and added a skybox background to actually make it a space scene lol.
I made a beam, or a cube which i made 1 unit longer in the X axis, to function as my simplified ship. I got the controls partly functioning and implemented, so far i can "strafe" up, down, left, right, and move for- and backwards. Which, for educational purposes at the moment suits my need. I spent some times into figuring out how to yaw the direction of my ship. I succesfully managed to do so with some if statements and a transform.Rotate like:
if (Input.GetKey("q"))
{
rollAmount += rollSpeed;
}
else if (Input.GetKey("e"))
{
rollAmount -= rollSpeed;
}
transform.Rotate(0, rollAmount * Time.deltaTime, 0);
and corresponding floats for rollSpeed and rollAmount. About this part i am not sure why, but it works perfectly. I know I choose which axis to adjust in the (0, 0, 0) part. I geuss that on input of given key, the float variable is increased or decreased which then in turn adjust the rollAmount. I just don't understand what the role of Rollspeed is. Is it unnecesarry?
using UnityEngine;
public class PlayerShipController :
MonoBehaviour {
public Rigidbody rb;
public float speed;
float rollAmount = 0.9f;
float rollSpeed = 0.9f;
void Start()
{
rb = GetComponent();
}
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
float moveUpDown = Input.GetAxis("UpDown");
Vector3 movement = new Vector3(moveHorizontal, moveUpDown,
moveVertical);
rb.AddForce(transform.forward = movement * speed * Time.deltaTime);
if (Input.GetKey("q"))
{
rollAmount += rollSpeed;
}
else if (Input.GetKey("e"))
{
rollAmount -= rollSpeed;
}
transform.Rotate(0, rollAmount * Time.deltaTime, 0);
} }
this is the playercontroller script as is. I know it must look horrible lol.
Anyway it works so that's great lol.
Buuut, being able to yaw the ship also means that i can not use the camera script from the roll a ball tutorial anymore. Since it takes the offset value, which is the distance between camera and player, and maintains this. it does not treat rotation on any kind of axis.
I first wanted to make my camera a child of the ship, which does work. except for the fact that when i press the keys to move the ship, the camera flashes in that direction untill key is let loose. it will imply the motion intended, just the camera also starts looking there which it should not. I want my camera to rotate and face accordingly to what my simplified ship points at.
I tried checking in my scene view wether my camera actually jumps it rotation values when moving but it didn't allow me to control it the same way as in scene view. I however clicked on the camera gameobject in hierarchy and still confirmed the rotation values of my camera jump on the Y value when using the strafe keys. or Z axis when moving up and down. Why does this happen? I don't understand it well enough yet to make a camera script that follows every rotation while maintaining that offset and theoretically having the camera as a child object should for now be sufficient. i started wondering wether there were camera controls of unity interfering with the game? because i do use the W,S Q,E and up, down, left and right keys. but i could not find evidence for this really quickly.
which leads me to believe i'm doing something wrong. I know this is not the way to approach a game like that. but its not intended to be a game, its to get a better understanding.
I would appreciate any help!
the camera controller script as off roll-a-ball tutorial.
using UnityEngine; using System.Collections;
public class CameraController : MonoBehaviour {
public GameObject player;
private Vector3 offset;
void Start()
{
offset = transform.position - player.transform.position;
}
void LateUpdate()
{
transform.position = player.transform.position + offset;
} }
Sincerely,
Hey guys, actually writing this question got my the answer myself. I applied the same if commands to the camera script. It works like a charm, it follows the ship's facing perfect so far.
edit:
it does not, now the camera rotates independently lol I take a geuss at that i can fix this by referencing to the ships rigidbody transform values in the camera script and apply its new rotation to match the ships rotation on each frame?
Answer by Vandive · Apr 08, 2016 at 12:04 PM
You can set the cameras parent to the ship you want to have the camera on. It will rotate with the ship and move with it.
that's not correct. I explained that when I try to make the camera follow my ship that way, it only works partially. The controls for the ship seem to influence the camera's rotation value in a buggy way. Now i tried both having the ship and camera as parent. ( on 2 different tries ofcourse, one with camera parent to ship and one the other way around.
actually to explain it better, since i have some ideas of my own:
Vector3 movement = new
Vector3(moveHorizontal, moveUpDown,
moveVertical);
rb.AddForce(transform.forward = movement * speed * Time.deltaTime);
this is what makes my ship strafe in any of six directions. I used this script from the 2d space shooter tutorial. Originally designed to use rb.velocity rather than AddForce. For the sake of my "boring" space game obviously i want more space like physics. Hence i used AddForce. The only type of transform i logically thought of as usefull was transform forward. This leads me to believe that, when i press a key to move it on another axis than the blue axis. It forces the ship momentarily in that direction, or for as long as the key is pressed in this case. The only key that works properly is the strafe forward key, the up arrow. I assume because that's also where i faced the camera towards.
basically imagine a screen seeing a planet, the view you see is intended to be from a ship's cockpit first person view, all that's missing in that sense is the HUD. now i press the left arrow key. at this moment, the camera rotates about 90 degrees to the left maybe more maybe less i haven't checked for sure. but it does add the motion I want. when i let loose the key. You see the camera rotate back to its intended viewpoint, and can tell that you are strafing to the left because the planet moves to the right.
This only happens when i call a movement on those six axes. actually the only thing working correctly now is when i yaw left or right, effectively rotating the ship and correspondingly the camera on its Y axis.( I say it because my ship turns, and with offset and the right amount of rotation my camera matches exactly ). I did this by making a call to the public gameobject PlayerShip ( spaceship ) and set the camera's rotation to match.
Now it just seems to me that my movement script is faulty and the cause, can anyone confirm this based on the information i provide?
sincerely,
Answer by sanderschellekens · Apr 09, 2016 at 12:20 PM
As seen in the comments i was suspecting my old movement script to be the cause. This was correct.
> using UnityEngine; using
> System.Collections; public class
> Fly: MonoBehaviour {
> //The purpose of this script is to simulate Newtonian phy
> private float maxThrust = 10; //The maximum Thrust provided by the
> thruster(s) at full throttle
> private float rollWeight = 1; //This float and the next two only
> serve to adjust sensitivity
> private float pitchWeight = 1;//of the controls, and to allow
> calibration for more massive ships.
> private float yawWeight = 1;//Set these 3 floats to the mass of
> the rigidbody for sensitive controls
>
> // Update is called once per frame
>
> void FixedUpdate ()
> {
> float yaw = yawWeight*Input.GetAxis("Yaw");
> float roll = rollWeight*Input.GetAxis("Roll");
> float pitch = pitchWeight*Input.GetAxis("Pitch");
> Vector3 Rotation = new Vector3(pitch, roll, yaw);
> rigidbody.AddRelativeTorque(Rotation);
> float throttle = maxThrust *Input.GetAxis("Thrust");
> rigidbody.AddRelativeForce(Vector3.forward*throttle);
> System.Console.WriteLine("input is "+
> yaw.ToString()+",
> "+pitch.ToString()+",
> "+roll.ToString());
> } }
http://pastebin.com/Y7QS6Ncb ( get it here ) with thanks to James Biederbeck:
http://jamesbiederbeck.tumblr.com/post/33856049838/controlling-a-spaceship-with-newtonian-physics-in
This script truly only throttles on the blue axis. Rather than fixing the blue axis in the direction of pressed movement key. ( this happened definitely because of the transform.forward over all three axis.)
It works like a charm now, without any script for the camera as it should be!
Hope this helps anyone trying the same in future, these codes are compatible with unity 5.3 except for the getComponent call. I added a void Start function to add a rb=getComponent<Rigidbody>.();
and a rigidbody rb;
in the class and changed the "rigidbody." inrigidbody.AddRelativeForce(Vector3.forward*throttle);
to rb.AddRelativeForce(Vector3.forward*throttle);
This however doesn't add realistic throttle, as its a relative force? If i put the thrust value rather really high it shows my ship almost instantly at max speed it seems. it's just unity physics that handle the ships drifting through space realistically after the force is not applied anymore. And it does not yet feature strafing movements but i will implement these soon.
I could change these in an AddForce but more interestingly would be if i use AddTorgue? Or am i wrong at this?
also, i do not fully understand this part of the code:
> System.Console.WriteLine("input is "+
> yaw.ToString()+",
> "+pitch.ToString()+",
> "+roll.ToString());
I think this adds a line to my script? or in the game when called. equalling input = yaw.tostring+pitch.tostring+rolltostring? but to what purpose? or how should i "see" this because i am not sure of how i should.
sincerely,
Your answer
![](https://koobas.hobune.stream/wayback/20220612074426im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
The character must always facing the camera 1 Answer
I build a own game but i have a cam problem 0 Answers
Camera Follow Position and Rotation 0 Answers
my camera wont stay with my player after assigning the player as a target 0 Answers
What does the other in OnTriggerEnter/Stay/Exit mean? 0 Answers