Hello Community,
UNITY VERSION 2022.3.11f1
3D URP project
I am working on a simple player controller script and I am experiencing difficulty determining why the velocity is behaving in unintended ways.
Two Issues:
1 - When I rotate the player Rigidbody while moving forward - the velocity/direction snaps to the worlds x-axis.
The yellow line is Velocity
The red line is acting forces (pushes based on key (W) input and direction with mouse input)
Video Demo : https://clipchamp.com/watch/kpePTVpR73s
Question - Why would a velocity snap to a world axis like that and how can I start to resolve?
2 - When I hit the space key to apply a impulse force in the y direction there is a force being applied in the z world axis direction that is pushing the Rigidbody and I have spend a lot of time commenting out other acting forces and looking through the UI to find what might be acting.
again
The yellow line is Velocity
The red line is acting forces (pushes based on key (W) input and direction with mouse input)
Video Demo : https://clipchamp.com/watch/phAYs1v4ULU
Question - Why would the velocity be immediately angled to the z direction when the impulse is set world y and why is there a deflection at the end of the arc path as though the rigidbody is colliding against an invisible wall?
Asset structure
CAMERA
Parent - CameraHolder - MoveCamera Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveCamera : MonoBehaviour
{
public Transform cameraPosition;
// Update is called once per frame
void Update()
{
transform.position = cameraPosition.position;
}
}
Child - PlayerCam (main camera) - PlayerCam script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCam : MonoBehaviour
{
public float sensX;
public float sensY;
public Transform orientation;
float xRotation;
float yRotation;
// Start is called before the first frame update
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
// Update is called once per frame
void Update()
{
// Get Mouse Input
float mouseX = Input.GetAxisRaw("Mouse X") * Time.deltaTime * sensX;
float mouseY = Input.GetAxisRaw("Mouse Y") * Time.deltaTime * sensY;
yRotation += mouseX;
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
transform.rotation = Quaternion.Euler(xRotation, yRotation, 0);
orientation.rotation = Quaternion.Euler(0, yRotation, 0);
}
}
PLAYER
Parent - Player - Rigidbody - Player Movement Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[Header("Movement")]
public float moveSpeed;
float horizontalInput;
float verticalInput;
Vector3 moveDirection;
Rigidbody rb;
public float groundDrag;
public float jumpForce;
public float jumpCooldown;
public float airMultiplier;
bool readyToJump = true;
[Header("Keybinds")]
public KeyCode jumpKey = KeyCode.Space;
[Header("Ground Check")]
public float playerHeight;
public LayerMask whatIsGround;
public Transform orientation;
bool grounded;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
rb.freezeRotation = true;
}
// Update is called once per frame
void Update()
{
}
private void FixedUpdate()
{
MovePlayer();
Debug.DrawRay(rb.position, rb.velocity, Color.yellow);
Debug.DrawRay(rb.position, rb.GetAccumulatedForce(), Color.red);
// Ground Check
grounded = Physics.Raycast(transform.position, Vector3.down, playerHeight * 0.5f + 0.2f, whatIsGround);
MyInput();
SpeedControl();
// Handle drag
if (grounded)
rb.drag = groundDrag;
else
rb.drag = 0;
}
private void MyInput()
{
horizontalInput = Input.GetAxis("Horizontal");
verticalInput = Input.GetAxis("Vertical");
if (Input.GetKey(jumpKey) && readyToJump && grounded)
{
readyToJump = false;
Jump();
Invoke(nameof(ResetJump), jumpCooldown);
}
}
private void MovePlayer()
{
// Calculate movement direction
moveDirection = orientation.forward * verticalInput + orientation.right * horizontalInput;
Debug.Log("Orientation --- " + orientation.position);
Debug.Log("Orientation --- " + orientation.forward);
Debug.DrawLine(rb.position, moveDirection, Color.green);
// On Ground
if (grounded)
rb.AddForce(moveDirection.normalized * moveSpeed * 10f, ForceMode.Force);
else if (!grounded)
rb.AddForce(moveDirection.normalized * moveSpeed * 10f * airMultiplier, ForceMode.Force);
}
private void SpeedControl()
{
Vector3 flatVelocity = new Vector3(rb.velocity.x, 0f, rb.velocity.y);
// Limit velocity if needed
if(flatVelocity.magnitude > moveSpeed)
{
Vector3 limitedVelocity = flatVelocity.normalized * moveSpeed;
rb.velocity = new Vector3(limitedVelocity.x, rb.velocity.y, limitedVelocity.z);
}
}
private void Jump()
{
// Reset Y Velocity
rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
rb.AddForce(transform.up * jumpForce, ForceMode.Impulse);
}
private void ResetJump()
{
readyToJump = true;
}
}
Child - PlayerObj - Capsule Collider
Child - Orientation - just transform for orientation
Child - CameraPos - just transform for position