1st person space ship pitch and yaw isue - unity3d

I've been trying for some time now with different tutorials to get a nice firstperson (cockpit view) spaceship controll system. I tried using mouse only, keyboard only and combinations but I keep encountering the same problem with all tutorials. even this simple line of code does it:
transform.position += transform.forward * Time.deltaTime * 90f;
transform.Rotate( Input.GetAxis("Vertical"), Input.GetAxis("Horizontal"), 0.0f);
The problem I keep getting is that if I pitch its ok. it I yaw its ok. But If I do both (so I go diagonaly) it also rotates my ship on the Z axis and messes up my orientation. I tried locking the z rotation in the rigidbody but that does'nt help either. I tried making code myself alternating with apply torque and simply rotating, followed some tutorials including this one: Tutorial but keep getting the rotation problem.
What I want to make is a game that controlls like the old game Helbender
Does anyone of you know of a way that I can get spaceship controlls to work?
----EDIT-----
Got a bit further now. It doenst turn on my z axis anymore becouse I keep setting it to 0. Only problem now is that if I try to make a looping the ship flips around instead of nicely looping.
if (Input.GetKey("up"))
{
transform.Rotate(transform.right * -ShipPanSpeed * Time.deltaTime, Space.World);
}
if (Input.GetKey("down"))
{
transform.Rotate(transform.right * ShipPanSpeed * Time.deltaTime, Space.World);
}
if (Input.GetKey("left"))
{
transform.Rotate(transform.up * -ShipPanSpeed * Time.deltaTime,Space.World);
}
if (Input.GetKey("right"))
{
transform.Rotate(transform.up * ShipPanSpeed * Time.deltaTime,Space.World);
}
float z = transform.eulerAngles.z;
transform.Rotate(0, 0, -z);

You could always try to make one parent object for the Controls and then a child object (the spaceshit) that you can rotate for the pivot but not attach any movement beside rotation.
What i mean is that you can rotate the parent on the Y axis to make it rotate and move the transform forward or backward at the same time. If you want to pivot up or down you can transform forward at the sametime you transform up/down multiplied with the axis you want to pivot with
Example:
private void Update(){
//PARENT--------------------------------------------
// MOVING FORWARD AND BACKWARD
transform.position += transform.forward * Input.GetAxis("Vertical") * speed * Time.deltaTime();
// MOVING RIGHT AND LEFT
transform.position += transform.right * Input.GetAxis("Horizontal") * speed * Time.deltaTime();
//PIVOT UP AND DOWN
transform.position += transform.up * -Input.GetAxis("Mouse Y") * speed * Time.deltaTime();
//ROTATE AROUND THE Y AXIS
tranform.Rotate(0f, Input.GetAxis("Horizontal") * rotationspeed, 0f);
}
For the spaceship (child) for the pivot i would recommend you to make a emptyobject and set the chip to lookAt that object based on the input axis you use to move up/down and forward/backward.
Hope this helped or at least gave you a idea of how to make it :)

Related

Rotate Object around point and move it along sine function

First off: I am very new to Unity, as in VERY new.
I want to do the following: I want to rotate a cube around a stationary point (in my case a camera) with a radius that is adjustable in the inspector. The cube should always have its Z-axis oriented towards the camera's position. While the cube is orbiting around the camera, it should additionally follow a sine function to move up and down with a magnitude of 2.
I have some working code, the only problem is an increase in distance over time. The longer the runtime, the higher the distance between the cube and the camera.
Here is what I currently have:
void Awake()
{
cameraPosition = GameObject.FindGameObjectWithTag("MainCamera").transform;
transform.position = new Vector3(x: transform.position.x,
y: transform.position.y,
z: cameraPosition.position.z + radius);
movement = transform.position;
}
I instantiate some variables in the Awake()-method and set the cube's position to where it should be (do you instantiate in Awake()?). I'll use the Vector3 movement later in my code for the "swinging" of the cube.
void Update()
{
transform.LookAt(cameraPosition);
transform.RotateAround(cameraPosition.position, cameraPosition.transform.up, 30 * Time.deltaTime * rotationSpeed);
MoveAndRotate();
}
Here I set the orientation of the cube's z-axis and rotate it around the camera. 30 is just a constant i am using for tests.
void MoveAndRotate()
{
movement += transform.right * Time.deltaTime * movementSpeed;
transform.position = movement + Vector3.up * Mathf.Sin(Time.time * frequency) * magnitude;
}
To be quite frank, I do not understand this bit of code completely. I do however understand that this includes a rotation as it moves the cube along it's x-axis as well as along the world's y-axis. I have yet to get into Vector and matrices, so if you could share your knowledge on that topic as well I'd be grateful for that.
It seems like I have found the solution for my problem, and it is an easy one at that.
First of all we need the initial position of our cube because we need to have access to its original y-coordinate to account for offsets.
So in Awake(), instead of
movement = transform.position;
We simply change it to
initialPosition = transform.position;
To have more readable code.
Next, we change our MoveAndRotate()-method to only be a single line long.
void MoveAndRotate()
{
transform.position = new Vector3(transform.position.x,
Mathf.Sin(Time.time * frequency) * magnitude + initialPosition.y,
transform.position.z);
}
What exactly does that line then? It sets the position of our cube to a new Vector3. This Vector consists of
its current x-value
our newly calculated y-value (our height, if you want to say so) + the offset from our original position
its current z value
With this, the cube will only bop up and down with distancing itself from the camera.
I have also found the reason for the increase in distance: My method of movement does not describe a sphere (which would keep the distance the same no matter how you rotate the cube) but rather a plane. Of course, moving the cube along a plane will automatically increase the distance for some points of the movement.
For instantiating variables in Awake it should be fine, but you could also do it in the Start(){} Method that Unity provides if you wanted to.
For the main problem itself I'm guessing that calling this function every frame is the Problem, because you add on to the position.
movement += transform.right * Time.deltaTime * movementSpeed;
Would be nice if you could try to replace it with this code and see if it helped.
movement = transform.right * Time.deltaTime * movementSpeed;

Unity: GameObject bug in rotation axis

In the GIF above I am moving the plane with the mouse up and down. Watch how when I rotate the plane on its Z axis the plane still moves up and down even if the plane is side ways now. That is my bug. Why is this happening? What is wrong with my code? I think I am using the global axis and not the gameobjects axis. How do I fix this please.
x += Input.GetAxis("Mouse X") * xMouseSpeed * 0.02f;
y -= Input.GetAxis("Mouse Y") * yMouseSpeed * 0.02f;
if (Input.GetKey(KeyCode.Q))
{
rotZ += Time.deltaTime * 50f;
}
if (Input.GetKey(KeyCode.E))
{
rotZ -= Time.deltaTime * 50f;
}
Quaternion rotation = Quaternion.Euler(y, x, rotZ);
planeBodyToMove.localRotation = rotation;
What happens is that the localRotation is just the rotation in relation to the parent object.
The rotation of the transform relative to the transform rotation of the parent.
Or in other words: The localRotation is not local to the object itself but rather a rotation in the local space of the parent (or Unity world space if there is no parent). It does not mean that you rotate around your local Y axis necessarily. It applies the rotations in the parent's local space in the order Z, X, Y .. that is why sometimes you actually don't note the difference until you rotate Y!
As you can see here the same thing happens also without your code by just doing the rotation via the Inspector
Or to demonstrate it a bit better lets see what happens if we rotate it the way you actually want it to rotate:
as you can see as soon as one axis already is rotated, changing another axis now changes all three rotation values.
Solution
So how to solve this?
Usually I'm to lazy to do Quaternion calculations myself → I let the Transform do this for me ^^
Instead of storing the expected rotation in fields and apply it everytime by converting it into a Quaternion you can directly use Transform.Rotate which rotates the object actually using its own local axis:
// Just a question of taste but I would prefer to have
// values that belong together in one single struct instead of multiple fields
public Vector2 mouseSensitivity = Vector3.one;
private void Update()
{
var xDif = Input.GetAxis("Mouse X") * mouseSensitivity.x;
var yDif = - Input.GetAxis("Mouse Y") * mouseSensitivity.y;
var zDif = 0f;
if (Input.GetKey(KeyCode.Q))
{
zDif= Time.deltaTime * 50f;
}
else if (Input.GetKey(KeyCode.E))
{
zDif= -Time.deltaTime * 50f;
}
// Wihout the optional space parameter uses local space by default
planeBodyToMove.Rotate(new Vector3(xDif, yDif, zDif));
}
As you can see now each rotation is actually applied in the plane's local axis:

Unity2D: Rotate object keeping looking at front

I am trying to archive without success a z-axis rotation movement around a moving object keeping always "looking at front". So it should looks like this:
The closest I got was with:
transform.RotateAround(targetPosition, Vector3.forward, moveSpeed);
But it does not keeps looking "at front".
Could someone give me a hand with this?
Thank you in advance.
Best regards.
If your object ("Lightning Bolt") has no world rotation, i.e. aligned with the world axis as your example image seems to suggest, then the easiest is to simply set the world rotation to the Quaternion Identity:
transform.rotation = Quaternion.identity;
Note that the image wont rotate if its parent object rotates. It will essentially "Billboard" your lightning object. If you want to your lightning bolt to be aligned with a parent object, then try something like:
transform.rotation = transform.parent.rotation;
Fitst store the current rotation, then rotate around point, lastly apply the previous rotation.
var rot = transform.rotation;
transform.RotateAround(targetPosition, Vector3.forward, moveSpeed);
transform.rotation = rot;
A simple solution would just manipulate actual coordinates and ignore rotation ^^ If an object moves and you want it to keep rotating around it, just make it a child object.
This is a 3d solution where we rotate around Y:
void Start() { angle = 0.0f }
void Update() {
angle += speed * Time.deltaTime; //Your starting angle that will be modified every frame
CheckAngle(ref angle);
float x = Mathf.Cos(angle * Mathf.Deg2Rad) * Radius;
float z = Mathf.Sin(angle * Mathf.Deg2Rad) * Radius;
}
static void CheckAngle(ref float Angle) //It should probably return a value by it's name here tho not ref, not sure which is the correct way of doing this
{
if (Angle > 360) //You don't want your angle to go past the boundaries of an INT
Angle = 0;
}

Unity3d - Rotate Towards Space.World

I want you to turn the cube to the targeted angle. But as you will turn every angle, the concept of "Space.World" is confused. How can I integrate "Space.World" into the "RotateToward" function.
I need to use "localPosition & eulerAngles" in code ?
etc:
targetRotate = new Vector3(0,180,0);
transform.rotation = Quaternion.RotateTowards (getRotate (), Quaternion.Euler (targetRotate), rotateTime * Time.deltaTime);
Code in Gist

Move and rotate 2d object using virtual joystick

Here is my code for moving a 2D top-down object using the built in virtual joystick:
void Update ()
{
Vector2 moveVec = new Vector2(CrossPlatformInputManager.GetAxis("Horizontal"),
CrossPlatformInputManager.GetAxis("Vertical"));
Vector3 lookVec = new Vector3(CrossPlatformInputManager.GetAxis("Horizontal"),
CrossPlatformInputManager.GetAxis("Vertical"), 4000);
transform.rotation = Quaternion.LookRotation(lookVec, Vector3.back);
transform.Translate(moveVec * Time.deltaTime * speed);
}
Without the rotation code, the movement was perfect, after adding the rotation code the movement got all messed up, if the direction is down, it moves up.
But the rotation is exactly how it should.
Simply change the transform.Translate(moveVec * Time.deltaTime * speed); line to transform.Translate(moveVec * Time.deltaTime * speed, Space.World); : by default, the translation is made relatively to the transform own space (Space.Self).