How rotate spaceship from y-axis to left in unity 3D - c#

I am starting a new unity3d project and i want to know how to rotate moving forward spaceship from y-axis to left and right.
void Update(){
transform.position += transform.forward * Time.deltaTime * 10f;
if(input.Getkey(KeyCode.LeftArrow))
{
//code for rotate ;
}
}
I want that when I press arrow left key then spaceship rotates from y-axis to left until the arrow key released.

You can use Transform.Rotate(Vector3).
void Update()
{
if (Input.GetKey(KeyCode.LeftArrow))
transform.Rotate(transform.forward * 3);
if (Input.GetKey(KeyCode.RightArrow))
transform.Rotate(transform.forward * -3);
}

I dont really know if i understand the question, but I think this may help you.
void Update () {
if (Input.GetKeyDown (KeyCode.Space)){
transform.Rotate (new Vector3(Time.deltaTime * 0, 1, 0));
}
where the first 0 is for x-axis, number 1 is for y-axis and the other 0 is for z-axis

You'll want declare the speed and rotation speed as floats so you can easily change them later, but here you go. I did both left and right.
float speed = 10.0f;
float rotateSpeed = 2.0f;
void Update(){
transform.position += transform.forward * Time.deltaTime * speed;
if(Input.GetKeyDown(KeyCode.LeftArrow))
{
//code for rotate
transform.Rotate(vector3.left * Time.deltaTime * rotateSpeed);
}
else if(Input.GetKeyDown(KeyCode.RightArrow))
{
transform.Rotate(vector3.right * Time.deltaTime * rotateSpeed);
}
}
If you want to rotate the ship relative to the world then use:
transform.Rotate(vector3.left * Time.deltaTime * rotateSpeed, Space.World);

Related

Spherical Gravity rotation and position

I'm trying to make a game using planet gravity physics. I'm stuck in rotating player.
private void FixedUpdate()
{
ProcessInput();
Vector3 gravityUp = (transform.position - gravityTarget.position).normalized;
Vector3 bodyUp = transform.up;
rb.AddForce(gravityUp * gravity);
Quaternion targetRotation = Quaternion.FromToRotation(bodyUp , gravityUp) * transform.rotation;
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation , 50 * Time.fixedDeltaTime);
transform.rotation =targetRotation;
Quaternion desRot = Quaternion.LookRotation(moveDir);
desRot = Quaternion.RotateTowards(transform.rotation, desRot , 360 * Time.deltaTime);
transform.rotation = desRot;
}
private void Update()
{
rb.MovePosition(rb.position + transform.TransformDirection(moveDir) * 15f * Time.deltaTime);
}
private void ProcessInput()
{
moveDir = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")).normalized;
}
Lets say I pressed Left Arrow and wanted to player to go left and turn left at the same time. The problem is transform.TransformDirection(moveDir). When I make the player turn to the left, player starts the move its left side instead of the world position. If I only use moveDir for positioning, it goes out of the world. How can I make this work?
You can see the video here!
Thanks for helping!

Why does transform.forward when equal to 0 when multiplied not equal to 0?

Im making movement for my camera in unity. The starting position for my camera is 0,0,0. When i press the W key the code i take the current position and multiply it by a movement speed and equal it to another vector 3 to then update the postion of the position of the camera. It works great but i cant understand why when i think about.
If my camera is initialised at 0,0,0 then why does transform.forward * movementSpeed not always eqaul 0?
This is the same for all directions i just used W as an example
Any help would be greatly appreciated as im new to unity. Thanks
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraMovement : MonoBehaviour
{
private Vector3 newPosition;
[SerializeField] private float movementSpeed;
[SerializeField] private float movementTime;
// Start is called before the first frame update
void Start()
{
newPosition = transform.position;
Debug.Log(transform.position); //prints 0.0,0.0,0.0
Debug.Log(transform.forward * movementSpeed); //prints 0.0,0.0,0.3
}
// Update is called once per frame
void Update()
{
handleKeyboardInput();
}
void handleKeyboardInput()
{
if (Input.GetKey(KeyCode.W))
{
newPosition += (transform.forward * movementSpeed);
}
if (Input.GetKey(KeyCode.A))
{
newPosition += (transform.right * -movementSpeed);
}
if (Input.GetKey(KeyCode.S))
{
newPosition += (transform.forward * -movementSpeed);
}
if (Input.GetKey(KeyCode.D))
{
newPosition += (transform.right * movementSpeed);
}
transform.position = Vector3.Lerp(transform.position, newPosition, Time.deltaTime * movementTime);
}
}
The reason your code works is becuase transform.forward and transform.right refer to the forward and right directions of you player. When you add transform.forward * speed to your newPosition, you are adding the forward direction of the player but with a magnitude (length) of your speed.
If you want to try to understand it better, you can use print(transform.forward) or print(transform.forward * speed) or do Debug.drawRay(transform.position, transform.forward)
Your code is multiplying transform.forward(0,0,1) or transform.right, both of them are not zero vectors, instead they represent the specified direction.
Vector3.forward is (0,0,1) if you want zero use Vector3.zero.

Move toward transform.forward, ignoring rotation

This code is attached to a camera:
transform.position += Input.GetAxis("Vertical") * transform.forward * mod;
transform.position += Input.GetAxis("Horizontal") * transform.right * mod;
I've used .forward and .right because the player is able to rotate the camera on the Y axiz, thus no matter which way the camera is facing the forward key will always move the camera relatively forward, the left key will move it relatively left and so on. Just to clarify - I want it to move in local space, not world space so forward is the direction it's facing, not necessarily Vector3(0,0,1).
The camera is free roaming and has no parent or target to follow.
The problem is the camera has an X rotation of 45 to look down. Using transform.forward will thus modify it's height. There is also some scroll code to change the cameras height so I don't want to set the hight to a fixed value. How can I limit the movement to X and Z only, preferably without parenting it it an empty?
Update: this code works but it's not pretty, I'm sure there is a more elegant solution using Vector3.Project, as xyLe_ is suggesting. If I figure it out I'll add to his answer.
mod = Time.deltaTime * 30;
float yPos = transform.position.y;
pos = transform.position;
pos += Input.GetAxis("Vertical") * transform.forward * mod;
pos.y = yPos;
pos += Input.GetAxis("Horizontal") * transform.right * mod;
pos += Input.GetAxis("Mouse ScrollWheel") * transform.up * mod * -30;
I might talk nonsense right now, but it seems pretty simple to me:
Vector3 desiredDirection = Vector3.Normalize(new Vector3(transform.forward.x, transform.position.y, transform.forward.z))
Just project transform.forward onto the x-z plane that is settled at the height of transform.position.y. Doing this (usually) results in a slightly shorter vector, so you have to renormalize it.
To visualize:
If I understand you correctly, transform.forward corresponds to the black vector and you want to have the green vector. By setting the y component of the black vector to the y component of the red dots positions y component, you get the purple vector, which has to be renormalized.
Even though this has been solved, the solution below should help other people having this problem.
Here is is a proper way to move toward transform.forward while ignoring its rotation:
1.Get the transform.forward.
2.Convert it to Local Space with InverseTransformDirection
3.Set the y axis to 0;
4.Normalize it with dir.Normalize();
5.Append the new pos to transform.position.
public float mod = 2;
void Update()
{
//Get Forward face
Vector3 dir = transform.forward;
//Convert to local Space
dir = transform.InverseTransformDirection(dir);
//Reset/Ignore y axis
dir.y = 0;
dir.Normalize();
//Append the new pos to the `transform.position`.
transform.position += dir * Input.GetAxis("Vertical") * mod;
transform.position += Input.GetAxis("Horizontal") * transform.right * mod;
}
Another Method(Not Recommended):
Since the camera is tilted to 45 angle:
1.Rotate it to -45
2.Move the camera normally
3.Rotate it back to 45
public float startingOffset = 45;
public float mod = 2;
// Update is called once per frame
void Update()
{
//Rotate it to -45
transform.Rotate(new Vector3(-startingOffset, 0, 0));
// Move the camera normally
transform.position += Input.GetAxis("Vertical") * transform.forward * mod;
transform.position += Input.GetAxis("Horizontal") * transform.right * mod;
//Rotate it back to 45
transform.Rotate(new Vector3(startingOffset, 0, 0));
}
Both these should work but the preferred way should be the first one.

InControl - How to Rotate Player Smoothly

I'm using the InControl input manager for my project. I'm using input from the right stick to rotate my player object, but I want the player to be rotated smoothly rather than instantaneously.
Here's my current code:
void FixedUpdate()
{
var device = InputManager.ActiveDevice;
MoveThePlayer(device.LeftStick.X, device.LeftStick.Y);
RotateThePlayer(device.RightStick.X, device.RightStick.Y);
}
void MoveThePlayer(float movex, float movey)
{
body.velocity = new Vector2(movex * speed, movey * speed);
}
void RotateThePlayer(float movex, float movey)
{
float heading = Mathf.Atan2(movey, movex);
transform.rotation = Quaternion.Euler(0f, 0f, heading * Mathf.Rad2Deg);
}
Lerps are your friend.
transform.Rotate() your player towards the angle you want by using Time.deltaTime
Example:
transform.Rotate(0, 0, (angleIWantToBeAt - transform.eulerAngles.z) * Time.deltaTime * speedMultiplier)

Resetting Position Relative to Rotation

Currently I have the following two issues:
The first issue being that when I reset my camera position I have to also reset my camera rotation. This is due to the fact that my camera
offset is set to a position slightly off of my player on the z and y
axis and obviously those values should change depending on my cameras
rotation although I am unsure how to figure out what those values
should be.
My second issue is that my rotation uses a raycast to find the middle of
the screen and determine its rotation origin although it seems to be
slightly off the middle of the screen as when it rotates the rotation
origin moves as well, if it is indeed in the middle of the screen
shouldn't it be completely still? Also is there a better and less
expensive way of achieving my desired rotation?
Relevant piece of code:
void RotateCamera()
{
//Find midle of screen
Ray ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2, 0));
RaycastHit hitInfo;
//Checks if ray hit something
if (Physics.Raycast(ray, out hitInfo))
{
//Rotate left and right
if (Input.GetKey(KeyCode.RightArrow))
{
transform.RotateAround(hitInfo.point, -Vector3.up, rotationSpeed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.RotateAround(hitInfo.point, Vector3.up, rotationSpeed * Time.deltaTime);
}
}
//Draws Raycast
Debug.DrawRay(ray.origin, ray.direction * 100, Color.yellow);
}
void ResetCameraPosition()
{
//Reset and lock camera position
transform.rotation = Quaternion.identity;
transform.position = player.transform.position + cameraOffset;
}
Image displaying what I mean
Use Camera.ScreenToWorldPoint to create a 'target' in the middle of the screen around which to pivot. Remove all the raycasting stuff as you don't need it and replace the relevant bits with:
float rotationSpeed = 45; // or whatever speed
float distance = 5f; // or whatever radius for the orbit
Vector3 target = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width / 2, Screen.height / 2, distance));
if (Input.GetKey(KeyCode.RightArrow))
{
transform.RotateAround(target , -Vector3.up, rotationSpeed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.RotateAround(target , Vector3.up, rotationSpeed * Time.deltaTime);
}

Categories

Resources