I’m working on a custom gravity system for my game. I’m trying to get my character to walk on walls and rotate to the direction the normal the character is standing on is facing.
So far I have it semi working. When the player comes across a wall, the gravity switches, and the player is standing on the wall.
Here is my custom gravity script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Gravity : MonoBehaviour
{
[SerializeField] Transform raycaster;
public Vector3 upDirection;
public bool isGrounded;
public Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
upDirection = Vector3.up;
}
private void FixedUpdate()
{
Vector3 raycastPos = raycaster.position + (raycaster.up * 1.5f);
RaycastHit down_hit;
Physics.Raycast(raycastPos, -raycaster.up, out down_hit);
RaycastHit forward_hit;
Physics.Raycast(raycastPos, raycaster.forward, out forward_hit);
RaycastHit back_hit;
Physics.Raycast(raycastPos, -raycaster.forward, out back_hit);
RaycastHit right_hit;
Physics.Raycast(raycastPos, raycaster.right, out right_hit);
RaycastHit left_hit;
Physics.Raycast(raycastPos, -raycaster.right, out left_hit);
if (down_hit.collider != null)
{
Debug.DrawLine(raycastPos, down_hit.point, Color.green);
}
if(forward_hit.collider != null)
{
Debug.DrawLine(raycastPos, forward_hit.point, Color.blue);
}
if(back_hit.collider != null)
{
Debug.DrawLine(raycastPos, back_hit.point, Color.cyan);
}
if (right_hit.collider != null)
{
Debug.DrawLine(raycastPos, right_hit.point, Color.red);
}
if (left_hit.collider != null)
{
Debug.DrawLine(raycastPos, left_hit.point, Color.yellow);
}
if (Vector3.Distance(forward_hit.point, raycastPos) < 1f && forward_hit.collider != null)
{
rb.velocity = Vector3.zero;
upDirection = forward_hit.normal;
transform.position = forward_hit.point;
}
else if(Vector3.Distance(back_hit.point, raycastPos) < 1f && back_hit.collider != null)
{
rb.velocity = Vector3.zero;
upDirection = back_hit.normal;
transform.position = back_hit.point;
}
else if (Vector3.Distance(right_hit.point, raycastPos) < 1f && right_hit.collider != null)
{
rb.velocity = Vector3.zero;
upDirection = right_hit.normal;
transform.position = right_hit.point;
}
else if (Vector3.Distance(left_hit.point, raycastPos) < 1f && left_hit.collider != null)
{
rb.velocity = Vector3.zero;
upDirection = left_hit.normal;
transform.position = left_hit.point;
}
else if (Vector3.Distance(down_hit.point, raycastPos) < 1f && down_hit.collider != null)
{
rb.velocity = Vector3.zero;
upDirection = down_hit.normal;
transform.position = down_hit.point;
}
if (transform.position == down_hit.point)
{
isGrounded = true;
}
else
{
isGrounded = false;
}
if (!isGrounded)
{
rb.velocity = -upDirection * 9.81f;
}
}
}
However, I’m having trouble rotating the character. I want the player to turn left and right, but with my current system, I am unable to figure out how to do so.
Rotation is handled in the PlayerMovement script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
Gravity gravity;
[SerializeField] float speed;
[SerializeField] float turnSpeed;
void Start()
{
gravity = GetComponent<Gravity>();
}
void Update()
{
float forwardMove = Input.GetAxis("Vertical") * speed * Time.deltaTime;
float sidewaysMove = Input.GetAxis("Horizontal") * speed * Time.deltaTime;
float turnX = Input.GetAxis("Mouse X") * turnSpeed;
transform.Rotate(new Vector3(0, 360, 0) * turnX * Time.deltaTime);
transform.rotation = Quaternion.FromToRotation(Vector3.up, gravity.upDirection);
transform.Translate(transform.forward * forwardMove + transform.right * sidewaysMove, Space.World);
}
}
Does anyone have any suggestions on what to do? I tried to multiply Quaternion.FromToRotation(Vector3.up, gravity.upDirection)
with transform.rotation
, but that only worked when the player’s up direction was world up.