- Home /
3D character mesh ignoring transform values and rotating without the rig
Just as a precursor, I am a beginner, so my apologies if this is a stupid question; So I am making an FPS game and for the player I created a model in blender, the model consists of four separate meshes (arms, legs, torso, and head) and the entire player is rigged. When I imported the model into my game, I thought it was odd that each mesh had the mesh filter and renderer components rather than a skinned mesh renderer, but I removed them and added one. The issue is when I assign a root bone in the skinned mesh my player rotates in a weird way and begins ignoring my transform values, so I can't rotate it back. Furthermore, my rig/player are not moving with my collider (I'll attach my playerMovement script as well in case that may be relevant) My rig should be functioning, and I set the root bone to the final piece of the spine (inside the head), any help would be greatly appreciated. Thanks in advance.
using System;
using UnityEngine;
public class PlayerMovement : MonoBehaviour {
public Transform playerCam;
public Transform orientation;
private Rigidbody rb;
private float xRotation;
private float sensitivity = 50f;
private float sensMultiplier = 1f;
public float moveSpeed = 4500;
public float maxSpeed = 20;
public float counterMovement = 0.175f;
private float threshold = 0.01f;
public float maxSlopeAngle = 35f;
public float jumpForce = 550f;
public float slideForce = 400;
public float slideCounterMovement = 0.2f;
public float wallrunForce,maxWallSpeed;
public float maxWallRunCameraTilt, wallRunCameraTilt;
float x;
float y;
bool jumping;
bool sprinting;
bool crouching;
public bool grounded = true;
bool isWallRight, isWallLeft;
bool isWallRunning;
public LayerMask whatIsGround;
public LayerMask whatIsWall;
private Vector3 crouchScale = new Vector3(1, 0.5f, 1);
private Vector3 playerScale;
private Vector3 normalVector = Vector3.up;
private Vector3 wallNormalVector;
void Awake()
{
rb = GetComponent<Rigidbody>();
}
void Start()
{
playerScale = transform.localScale;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
private void FixedUpdate()
{
Movement();
}
private void Update()
{
MyInput();
CheckForWall();
Look();
WallRunInput();
if (Input.GetKeyDown(KeyCode.Alpha0))
{
Debug.Break();
}
}
private void MyInput()
{
x = Input.GetAxisRaw("Horizontal");
y = Input.GetAxisRaw("Vertical");
jumping = (grounded || isWallRunning) && Input.GetKey(KeyCode.Space);
crouching = Input.GetKey(KeyCode.LeftShift);
if (Input.GetKeyDown(KeyCode.LeftShift))
{
StartCrouch();
}
if (Input.GetKeyUp(KeyCode.LeftShift))
{
StopCrouch();
}
}
private void StartCrouch()
{
transform.localScale = crouchScale;
transform.position = new Vector3(transform.position.x, transform.position.y - 0.5f, transform.position.z);
if (rb.velocity.magnitude > 0.5f)
{
if (grounded)
{
rb.AddForce(orientation.transform.forward * slideForce);
}
}
}
private void StopCrouch()
{
transform.localScale = playerScale;
transform.position = new Vector3(transform.position.x, transform.position.y + 0.5f, transform.position.z);
}
private void Movement()
{
rb.AddForce(Vector3.down * Time.deltaTime * 10);
Vector2 mag = FindVelRelativeToLook();
float xMag = mag.x, yMag = mag.y;
CounterMovement(x, y, mag);
if (jumping)
{
OnJump();
}
float maxSpeed = this.maxSpeed;
if (crouching && grounded )
{
rb.AddForce(Vector3.down * Time.deltaTime * 3000);
return;
}
if (x > 0 && xMag > maxSpeed) x = 0;
if (x < 0 && xMag < -maxSpeed) x = 0;
if (y > 0 && yMag > maxSpeed) y = 0;
if (y < 0 && yMag < -maxSpeed) y = 0;
float multiplier = 1f, multiplierV = 1f;
if (!grounded)
{
multiplier = 0.5f;
multiplierV = 0.5f;
}
if (grounded && crouching) multiplierV = 0f;
rb.AddForce(orientation.transform.forward * y * moveSpeed * Time.deltaTime * multiplier * multiplierV);
rb.AddForce(orientation.transform.right * x * moveSpeed * Time.deltaTime * multiplier);
}
private void OnJump()
{
if (grounded)
{
rb.AddForce(Vector2.up * jumpForce * 1.5f);
rb.AddForce(normalVector * jumpForce * 0.5f);
Vector3 vel = rb.velocity;
if (rb.velocity.y < 0.5f)
rb.velocity = new Vector3(vel.x, 0, vel.z);
else if (rb.velocity.y > 0)
rb.velocity = new Vector3(vel.x, vel.y / 2, vel.z);
}
if ( !grounded )
{
rb.AddForce(orientation.forward * jumpForce * 1f);
rb.AddForce(Vector2.up * jumpForce * 1.5f);
rb.AddForce(Vector2.up * jumpForce * 1.5f);
rb.AddForce(normalVector * jumpForce * 0.5f);
rb.velocity = Vector3.zero;
}
if (isWallRunning)
{
if (isWallLeft && Input.GetKey(KeyCode.Space) || isWallRight && Input.GetKey(KeyCode.Space))
{
rb.AddForce(Vector2.up * jumpForce * 0.5f);
rb.AddForce(normalVector * jumpForce * 0.15f);
}
if (isWallRight || isWallLeft && Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D))
{
rb.AddForce(orientation.forward * jumpForce * 10f);
}
if (isWallRight && Input.GetKey(KeyCode.A))
{
rb.AddForce(-orientation.right * jumpForce * 1.2f);
}
if (isWallLeft && Input.GetKey(KeyCode.D))
{
rb.AddForce(orientation.right * jumpForce * 3.2f);
}
rb.AddForce(orientation.forward * jumpForce * 1f);
}
}
private float desiredX;
private void Look()
{
float mouseX = Input.GetAxis("Mouse X") * sensitivity * Time.fixedDeltaTime * sensMultiplier;
float mouseY = Input.GetAxis("Mouse Y") * sensitivity * Time.fixedDeltaTime * sensMultiplier;
Vector3 rot = playerCam.transform.localRotation.eulerAngles;
desiredX = rot.y + mouseX;
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
playerCam.transform.localRotation = Quaternion.Euler(xRotation, desiredX, wallRunCameraTilt);
orientation.transform.localRotation = Quaternion.Euler(0, desiredX, 0);
if (Math.Abs(wallRunCameraTilt) < maxWallRunCameraTilt && isWallRunning && isWallRight)
wallRunCameraTilt += Time.deltaTime * maxWallRunCameraTilt * 2;
if (Math.Abs(wallRunCameraTilt) < maxWallRunCameraTilt && isWallRunning && isWallLeft)
wallRunCameraTilt -= Time.deltaTime * maxWallRunCameraTilt * 2;
if (wallRunCameraTilt > 0 && !isWallRight && !isWallLeft)
wallRunCameraTilt -= Time.deltaTime * maxWallRunCameraTilt * 2;
if (wallRunCameraTilt < 0 && !isWallRight && !isWallLeft)
wallRunCameraTilt += Time.deltaTime * maxWallRunCameraTilt * 2;
}
private void CounterMovement(float x, float y, Vector2 mag)
{
if (!grounded || jumping) return;
if (crouching)
{
rb.AddForce(moveSpeed * Time.deltaTime * -rb.velocity.normalized * slideCounterMovement);
return;
}
if (Math.Abs(mag.x) > threshold && Math.Abs(x) < 0.05f || (mag.x < -threshold && x > 0) || (mag.x > threshold && x < 0))
{
rb.AddForce(moveSpeed * orientation.transform.right * Time.deltaTime * -mag.x * counterMovement);
}
if (Math.Abs(mag.y) > threshold && Math.Abs(y) < 0.05f || (mag.y < -threshold && y > 0) || (mag.y > threshold && y < 0))
{
rb.AddForce(moveSpeed * orientation.transform.forward * Time.deltaTime * -mag.y * counterMovement);
}
if (Mathf.Sqrt((Mathf.Pow(rb.velocity.x, 2) + Mathf.Pow(rb.velocity.z, 2))) > maxSpeed)
{
float fallspeed = rb.velocity.y;
Vector3 n = rb.velocity.normalized * maxSpeed;
rb.velocity = new Vector3(n.x, fallspeed, n.z);
}
}
public Vector2 FindVelRelativeToLook()
{
float lookAngle = orientation.transform.eulerAngles.y;
float moveAngle = Mathf.Atan2(rb.velocity.x, rb.velocity.z) * Mathf.Rad2Deg;
float u = Mathf.DeltaAngle(lookAngle, moveAngle);
float v = 90 - u;
float magnitue = rb.velocity.magnitude;
float yMag = magnitue * Mathf.Cos(u * Mathf.Deg2Rad);
float xMag = magnitue * Mathf.Cos(v * Mathf.Deg2Rad);
return new Vector2(xMag, yMag);
}
private bool IsFloor(Vector3 v)
{
float angle = Vector3.Angle(Vector3.up, v);
return angle < maxSlopeAngle;
}
private bool cancellingGrounded;
private void OnCollisionStay(Collision other)
{
int layer = other.gameObject.layer;
if (whatIsGround != (whatIsGround | (1 << layer)))
{
return;
}
for (int i = 0; i < other.contactCount; i++)
{
Vector3 normal = other.contacts[i].normal;
if (IsFloor(normal))
{
grounded = true;
cancellingGrounded = false;
normalVector = normal;
CancelInvoke(nameof(StopGrounded));
}
}
float delay = 3f;
if (!cancellingGrounded)
{
cancellingGrounded = true;
Invoke(nameof(StopGrounded), Time.deltaTime * delay);
}
}
private void StopGrounded()
{
grounded = false;
}
private void WallRunInput()
{
if (Input.GetKey(KeyCode.D) && isWallRight) StartWallrun();
if (Input.GetKey(KeyCode.A) && isWallLeft) StartWallrun();
}
private void StartWallrun()
{
rb.useGravity = false;
isWallRunning = true;
if (rb.velocity.magnitude <= maxWallSpeed)
{
rb.AddForce(orientation.forward * wallrunForce * Time.deltaTime);
if (isWallRight)
rb.AddForce(orientation.right * wallrunForce / 5 * Time.deltaTime);
else
rb.AddForce(-orientation.right * wallrunForce / 5 * Time.deltaTime);
}
}
private void StopWallRun()
{
isWallRunning = false;
rb.useGravity = true;
}
private void CheckForWall()
{
isWallRight = Physics.Raycast(transform.position, orientation.right, 10f, whatIsWall);
isWallLeft = Physics.Raycast(transform.position, -orientation.right, 10f, whatIsWall);
if (!isWallLeft && !isWallRight) StopWallRun();
}
}
Your answer
Follow this Question
Related Questions
Retargeting FPS hands animation to another model 0 Answers
My player's camera displays jerky objects 2 Answers
Objects not jumpable on 2 Answers
Best way for rigidbody enemy? 1 Answer