How to player look in direction of movement but have the transform’s up vector point in the direction of gravity?
I want to make a game that utilizes physics like Super Mario Galaxy where the player can run on irregular shaped objects which game engines don’t have.
I used this script to control gravity and also control the player but the problem is my character can move on any object but still doesn’t point in the direction of movement.
I can’t get a clear understanding of interpolation so I don’t know what to do?
This is the whole script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
public class PlayerControl : MonoBehaviour
{
public GameObject teleportDestination;
public GameObject orbit;
public Rigidbody Rb;
public int life = 3;
public bool canJump = false;
public bool jump = false;
public float MovementSpeed = 2f;
public bool ApplyGravity = true;
public bool ApplyParallelGravity = false;
public bool IsMoving = false;
public bool shouldFall = false;
public bool isGrounded = true;
public float distanceToGround;
public Vector3 Groundnormal;
public Camera camera;
public bool cameraControl = false;
public int moveX;
public int moveZ;
public Vector3 _direction;
public Quaternion newRotation;
public Vector3 gravityUp;
public Vector3 dir;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
public void Update()
{
camera = gameObject.GetComponentInChildren<Camera>();
Application.targetFrameRate = 100;
print(life);
if (life == 0)
{
Thread.Sleep(3);
StartCoroutine(RespawnWait());
}
if (life < 0)
{
Thread.Sleep(3);
StartCoroutine(RespawnWait());
}
if (life > 0)
{
if (shouldFall == true)
{
Rb.velocity = -transform.up;
}
RaycastHit hit = new RaycastHit();
if (Physics.Raycast(transform.position, -transform.up, out hit, 10))
{
distanceToGround = hit.distance;
Groundnormal = hit.normal;
if (distanceToGround == 0.2f)
{
isGrounded = true;
}
else
{
isGrounded = false;
}
}
if (gameObject)
{
if (ApplyGravity == true)
{
gravityUp = (gameObject.transform.position - new Vector3(651, 46, 476));
Vector3 bodyUp = transform.up;
newRotation = Quaternion.FromToRotation(bodyUp, gravityUp) * transform.rotation;
transform.rotation = Quaternion.Slerp(transform.rotation, newRotation, 50 * Time.deltaTime);
Thread.Sleep(1);
Rb.velocity += ((-gravityUp * 10) * Rb.mass);
}
if (ApplyParallelGravity == true)
{
ApplyGravity = false;
gravityUp = orbit.transform.up * 10;
Vector3 bodyUp = transform.up;
newRotation = Quaternion.FromToRotation(bodyUp, gravityUp) * transform.rotation;
transform.rotation = Quaternion.Slerp(transform.rotation, newRotation, 50 * Time.deltaTime);
Rb.velocity += -gravityUp;
}
if (orbit.GetComponent<GravityArea>())
{
MovementSpeed = 30.0f;
}
if (orbit.GetComponent<SphericalGravityArea>())
{
MovementSpeed = 3000.0f;
}
}
if (Input.GetKeyDown(KeyCode.E))
{
transform.position = teleportDestination.transform.position;
}
if (Input.GetKeyDown(KeyCode.Space))
{
ApplyGravity = false;
jump = true;
if (jump == true)
{
if (canJump == true)
{
if (isGrounded == true)
{
Rb.AddForce(transform.up * 40000 * 1.2f * Time.deltaTime);
MovementSpeed = 5.0f;
}
}
}
}
var mvfrwrd = false;
if (gameObject)
{
if (Input.GetKey(KeyCode.UpArrow))
{
mvfrwrd = true;
if (mvfrwrd == true)
{
moveZ = 1;
}
}
if (Input.GetKeyUp(KeyCode.UpArrow))
{
moveZ = 0;
StartCoroutine(MoveWait());
Rb.velocity += Vector3.zero;
mvfrwrd = false;
}
}
var mvbkwrd = false;
if (gameObject)
{
if (Input.GetKey(KeyCode.DownArrow))
{
mvbkwrd = true;
if (mvbkwrd == true)
{
moveZ = -1;
}
}
if (Input.GetKeyUp(KeyCode.DownArrow))
{
moveZ = 0;
StartCoroutine(MoveWait());
Rb.velocity += Vector3.zero;
mvbkwrd = false;
}
}
var mvlft = false;
if (gameObject)
{
if (Input.GetKey(KeyCode.LeftArrow))
{
mvlft = true;
if (mvlft == true)
{
moveX = -1;
}
}
if (Input.GetKeyUp(KeyCode.LeftArrow))
{
moveX = 0;
StartCoroutine(MoveWait());
Rb.velocity += Vector3.zero;
mvbkwrd = false;
}
}
var mvrght = false;
if (gameObject)
{
if (Input.GetKey(KeyCode.RightArrow))
{
mvrght = true;
if (mvrght == true)
{
moveX = 1;
}
}
if (Input.GetKeyUp(KeyCode.RightArrow))
{
moveX = 0;
StartCoroutine(MoveWait());
Rb.velocity += Vector3.zero;
mvbkwrd = false;
}
}
}
dir = new Vector3(moveX, 0, moveZ);
dir.Normalize();
if (dir != Vector3.zero)
{
transform.forward = dir;
Quaternion newRot = Quaternion.FromToRotation(dir, gravityUp);
transform.rotation = Quaternion.Slerp(newRot, newRotation, 50 * Time.deltaTime);
}
if (moveX == -1)
{
Rb.velocity += -transform.right * MovementSpeed;
}
if (moveX == 1)
{
Rb.velocity += transform.right * MovementSpeed;
}
if (moveZ == -1)
{
Rb.velocity += -transform.forward * MovementSpeed;
}
if (moveZ == 1)
{
Rb.velocity += transform.forward * MovementSpeed;
}
}
IEnumerator RespawnWait()
{
yield return new WaitForSeconds(3f);
life = 3;
ApplyGravity = false;
transform.position = new Vector3(646, 69, 472);
yield return new WaitForSeconds(1f);
ApplyGravity = true;
}
IEnumerator MoveWait()
{
yield return new WaitForSeconds(1f);
}
}
I had a problem with an if statement, if the player looks in the direction of movement the up vector of the transform won’t look in up direction of gravity, if the transforms up vector looks in the direction of gravity the player won’t look in the direction of movement.
This is the if statement:
if (dir != Vector3.zero)
{
transform.forward = dir;
Quaternion newRot = Quaternion.FromToRotation(dir, gravityUp);
transform.rotation = Quaternion.Slerp(newRot, newRotation, 50 * Time.deltaTime);
}
I could just add this thread of code to the if statement:
transform.up = gravityUp;
But setting the direction of the up vector or lerping it cause a certain glitch to happen
So I wanted to try slerping the transform’s rotation.
What could I do to fix this