Spherical Gravity rotation and position - c#

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!

Related

Contoller script doesn't change direction when the character looks around

I'm using a controller script from the official Unity website to move my character around. I'm also using a script to turn the camera using the mouse. Everything works fine until the character looks around and faces a different direction. Then the WASD controls move them according to the original orientation. For example, if I turn 180 degrees W moves me backward and S moves me forward.
I've tried to figure this out using transform.forward but I don't really know what I'm doing.
The movement script:
CharacterController characterController;
public float speed = 6.0f;
public float jumpSpeed = 8.0f;
public float gravity = 20.0f;
private Vector3 moveDirection = Vector3.zero;
void Start()
{
characterController = GetComponent<CharacterController>();
}
void Update()
{
if (characterController.isGrounded)
{
// We are grounded, so recalculate
// move direction directly from axes
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0.0f, Input.GetAxis("Vertical"));
moveDirection *= speed;
if (Input.GetButton("Jump"))
{
moveDirection.y = jumpSpeed;
}
}
// Apply gravity. Gravity is multiplied by deltaTime twice (once here, and once below
// when the moveDirection is multiplied by deltaTime). This is because gravity should be applied
// as an acceleration (ms^-2)
moveDirection.y -= gravity * Time.deltaTime;
// Move the controller
characterController.Move(moveDirection * Time.deltaTime);
}
Thank you for any help :)
You can use Transform.TransformDirection to convert from local direction to world direction. Call that with the local direction you want to move and it will return the corresponding world direction which you can give to CharacterController.Move:
void Update()
{
if (characterController.isGrounded)
{
// We are grounded, so recalculate
// move direction directly from axes
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0.0f, Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection = moveDirection * speed;
if (Input.GetButton("Jump"))
{
moveDirection.y = jumpSpeed;
}
}
// Apply gravity. Gravity is multiplied by deltaTime twice (once here, and once below
// when the moveDirection is multiplied by deltaTime). This is because gravity should be applied
// as an acceleration (ms^-2)
moveDirection.y -= gravity * Time.deltaTime;
// Move the controller
characterController.Move(worldMoveDirection * Time.deltaTime);
}
In fact, the old documentation for CharacterController.Move used this very method!
void Update()
{
if (controller.isGrounded)
{
// We are grounded, so recalculate
// move direction directly from axes
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0.0f, Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection = moveDirection * speed;
if (Input.GetButton("Jump"))
{
moveDirection.y = jumpSpeed;
}
}
// Apply gravity
moveDirection.y = moveDirection.y - (gravity * Time.deltaTime);
// Move the controller
controller.Move(moveDirection * Time.deltaTime);
}
I's because Move uses world space coordinates but you generating local.
Try change
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0.0f, Input.GetAxis("Vertical"));
to
moveDirection = transform.right * Input.GetAxis("Horizontal") + transform.forward * Input.GetAxis("Vertical");

I want my character to move only in the direction that it is looking

I have a 3D game, where my camera is looking at all my terrain, and I have a character that moves with an Xbox controller. I want my character to only move in the direction that it is looking, not to the sides. I have the next code that makes my character move.
void Update()
{
MoveInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical"));
moveVelocity = MoveInput * MoveSpeed;
Vector3 PlayerDirection = Vector3.right * -Input.GetAxisRaw("RHorizontal") + Vector3.forward * -Input.GetAxisRaw("RVertical");
if (PlayerDirection.sqrMagnitude > 0.0f)
{
transform.rotation = Quaternion.LookRotation(PlayerDirection, Vector3.up);
}
The character moves with the left side of the controller, and with the right side, I can move the direction that is facing.
Currently, you're using the inputs as x and z components of a world space direction. It doesn't take into account the rotation of the character at all.
Instead, you should multiply the inputs and the corresponding local direction in world space, and then combine them. In your case, this might look like this:
MoveInput = (
transform.right * Input.GetAxisRaw("Horizontal")
+ transform.forward * Input.GetAxisRaw("Vertical")
).normalized;
moveVelocity = MoveInput * MoveSpeed;
Vector3 PlayerDirection = Vector3.right * -Input.GetAxisRaw("RHorizontal")
+ Vector3.forward * -Input.GetAxisRaw("RVertical");
if (PlayerDirection.sqrMagnitude > 0.0f)
{
transform.rotation = Quaternion.LookRotation(PlayerDirection, Vector3.up);
}
The normalized is so you don't move faster diagonally.
I found a solution, here is the code:
MoveInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical"));
moveVelocity = MoveInput * MoveSpeed;
Vector3 PlayerDirection = Vector3.right * Input.GetAxisRaw("Horizontal") + Vector3.forward * Input.GetAxisRaw("Vertical");
if (PlayerDirection.sqrMagnitude > 0.0f)
{
transform.rotation = Quaternion.LookRotation(PlayerDirection, Vector3.up);
}

How to rotate an object around itself?

I want to rotate a cube in Unity3D.When I push arrow left button on keyboard the cube have to rotate left.If I push up, the cube have to rotate up.But with my script the cube rotate left and then the left-side rotate up.
This is the current status:
That's what I want:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rotate : MonoBehaviour
{
public float smooth = 1f;
private Quaternion targetRotation;
// Start is called before the first frame update
void Start()
{
targetRotation = transform.rotation;
}
// Update is called once per frame
void Update()
{
if(Input.GetKeyDown(KeyCode.UpArrow)){
targetRotation *= Quaternion.AngleAxis(90, Vector3.right);
}
if(Input.GetKeyDown(KeyCode.DownArrow)){
targetRotation *= Quaternion.AngleAxis(90, Vector3.left);
}
if(Input.GetKeyDown(KeyCode.LeftArrow)){
targetRotation *= Quaternion.AngleAxis(90, Vector3.up);
}
if(Input.GetKeyDown(KeyCode.RightArrow)){
targetRotation *= Quaternion.AngleAxis(90, Vector3.down);
}
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, 10* smooth * Time.deltaTime);
}
}
You need to swap the order of your quaternion multiplication.
The way you have it now, the rotations are applied to the axes as they would be after the original rotation because you are effectively doing targetRotation = targetRotation * ...;.
However, you want to rotate the rotation around the world axes. You can do this by doing targetRotation = ... * targetRotation;:
void Update()
{
if(Input.GetKeyDown(KeyCode.UpArrow)){
targetRotation = Quaternion.AngleAxis(90, Vector3.right) * targetRotation;
}
if(Input.GetKeyDown(KeyCode.DownArrow)){
targetRotation = Quaternion.AngleAxis(90, Vector3.left) * targetRotation;
}
if(Input.GetKeyDown(KeyCode.LeftArrow)){
targetRotation = Quaternion.AngleAxis(90, Vector3.up) * targetRotation;
}
if(Input.GetKeyDown(KeyCode.RightArrow)){
targetRotation = Quaternion.AngleAxis(90, Vector3.down) * targetRotation;
}
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, 10* smooth * Time.deltaTime);
}
See How do I rotate a Quaternion with 2nd Quaternion on its local or world axes without using transform.Rotate? for more information.

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

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);

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)

Categories

Resources