Hello. I am developing a space shooter similar to this. In that game, the player’s ship will follow the crosshairs, but will not rotate along the z axis. How is it able to do that?
In my prototype I have been working on, I have a look at function thats attatched to the ship (where the look at target is the crosshair object, which is just an object that uses a drag script to follow the mouse around the screen). But, the ship will rotate around the z axis(technically its the y axis, because to use the drag object script, the crosshairs had to be positioned as if the player was looking at everything from above).
I have also tried using the built in Unity mouse look script, but to no avail. It goes haywire because of the objects vertical orientation, and when I try to modify the script to deal with the x/z axes instead of the x/y, it fails.
Thanks
Here is my prototype
An easy way to get pitch and yaw without roll is to put the ship inside an empty parent GameObject. You can then rotate the parent around the world Y axis to get yaw and tilt the child up and down around its local left-right axis (whatever you choose this to be). No roll can be introduced with this arrangement.
Would I still use the MouseLook script?
The game demo that you posted does not use any camera look at all. The camera is fixed behind the player.
I have noticed the “Drag” script being used for all kinds of things it should not be used for. In the case of this demo, you should not drag anything around. Your target position should be a Plane.Raycast using ScreenPointToRay. This will give you an accurate destination target.
Using the LookAt method of Transform is not the answer, you would want to use Quaternion.LookRotation(). This gives you what the target rotation should be, but will not force the transform to that rotation. You then use Quaternion.Slerp(from, to, speed * Time.deltaTime) to set your new rotation.
The box and cross hairs from the game are parented to the ship and never change. The ship should have a collider, but no rigidbody. You really are just looking for OnCollisionEnter to tell if something hit you.
How do I use ScreenPointToRay in conjunction with Plane.Raycast?
Hah, I just posted this in another thread.
You need to make the object look at the point where the mouse is on the plane that the object is.
1: Define a plane in the direction of the camera, at the point of the player.
2: Define a ray in the direction of the camera at the point of the mouse
3: Define a distance variable to handle the incoming intersection
4: Preform a Plane.Raycast on the plane from the ray and collect the distance.
5: Use the ray’s Origin plus the direction times the distance to get the point of intersection.
6: look at it.
function Update(){
var ray : Ray = Camera.main.ScreenPointToRay (Input.mousePosition);
var plane : Plane=new Plane(Camera.main.transform.forward, transform.position);
var dist : float=0.0;
plane.Raycast(ray, dist);
transform.LookAt(ray.origin + ray.direction * dist);
}
How would I use transform.LookAt along only one axis? That way, I could use andeeee’s idea about restricting the rotation to pitch and yaw, I would place this script into an empty game object and use transform.LookAt for only the y axis, and then put my ship inside this object, and use transform.LookAt for the x axis?
Ah, this is a slightly different problem. For this game, your camera should be on a fixed rail and moves at a fixed rate. That rate could change depending on if you are using a key to move faster.
The ship should be a fixed distance in front of the camera. The Plane.Raycast I had in my previous post is perfect, since it uses the position of the ship as a base.
However, there are some changes. You will not be using a LookAt at all. You need to simply calculate the difference between where the ship is sitting on the plane and the intersection of the mouse on that plane. All of your rotations would then be based off the distance it needed to move along that plane to make it “look” like it is actually flying.
OK, so I wrote the code out you would need. just the basic movement part.
var speed=10.0;
var UDLRspeed=1.0;
var cam : Transform;
var camDistance=20.0;
function Start(){
transform.position=cam.position + cam.forward * camDistance;
}
function Update(){
// find the point where we have our mouse in relation to our ship.
var ray : Ray = Camera.main.ScreenPointToRay (Input.mousePosition);
var plane : Plane=new Plane(Camera.main.transform.forward, transform.position + transform.forward);
var dist : float=0.0;
plane.Raycast(ray, dist);
// get the relative and world position of the mouse.
var worldMouse=ray.origin+ray.direction * dist;
var relativeMouse=transform.InverseTransformPoint(worldMouse);
//assign rotations based on the relative mouse position
transform.localEulerAngles.x=relativeMouse.y * 0.01;
transform.localEulerAngles.y=relativeMouse.x * 0.01;
transform.localEulerAngles.z=relativeMouse.x * 0.001;
// do world move of the player towards the world position of the mouse
transform.position=Vector3.Lerp(transform.position, worldMouse, UDLRspeed * Time.deltaTime);
// calculate the speed based off of if we have the left shift key down
var sp=speed;
if(Input.GetKey(KeyCode.LeftShift))sp=sp * 5;
// update the position of the camera and player based off wher the camera is looking.
cam.position+=camera.forward * speed;
transform.position+=camera.forward * speed;
}
There is a slight problem though. The ship object keeps getting further from the camera along the forward axis (even though both are moving), what is wrong? Is there any way to completely stop the movement (then I can just put the camera and the ship inside an empty object and move the object forward at a constant rate)?
Anything? I am sorry to be an annoyance.
Sorry for the late response. Yeah, that is a little freaky, you would think that * speed would be the same for both. Oh well… live and learn.
What I did was to get the offset from the camera, then every frame reset it back to the running distance.
I also took the time to set the rotations to be a little spiffier.
var speed=10.0;
var UDLRspeed=1.0;
var cam : Transform;
var camDistance=20.0;
function Start(){
transform.position=cam.position + cam.forward * camDistance;
}
function Update(){
// find the point where we have our mouse in relation to our ship.
var ray : Ray = Camera.main.ScreenPointToRay (Input.mousePosition);
var plane : Plane=new Plane(Camera.main.transform.forward, transform.position + transform.forward);
var dist : float=0.0;
plane.Raycast(ray, dist);
// get the relative and world position of the mouse.
var worldMouse=ray.origin+ray.direction * dist;
var relativeMouse=transform.InverseTransformPoint(worldMouse);
//assign rotations based on the relative mouse position
transform.localEulerAngles.x=-relativeMouse.y * 4;
transform.localEulerAngles.y=relativeMouse.x * 4;
transform.localEulerAngles.z=-relativeMouse.x * 1;
// do world move of the player towards the world position of the mouse
transform.position=Vector3.Lerp(transform.position, worldMouse, UDLRspeed * Time.deltaTime);
// calculate the speed based off of if we have the left shift key down
var sp=speed;
if(Input.GetKey(KeyCode.LeftShift))sp=sp * 5;
// update the position of the camera and player based off wher the camera is looking.
cam.position+=cam.forward * sp;
var camoffset=cam.InverseTransformPoint(transform.position);
camoffset.z=camDistance;
transform.position=cam.TransformPoint(camoffset);
}
Of course, one must learn to play with stuff. lest one will always rely on someone in a forum to tweak for you. 
True 
I do have another question, but it’s not scripting, it’s more conceptual. While the the ship is moving forward, if I instantiate a projectile (which has a script that moves it forward), even if the projectile speed is faster that the ships movement speed, the projectile disappears (I presume that the ship is passing it). What is wrong?