Why is my character falling/leaning over on mouse click in unity? - unity3d

My character using CharacterController seems to be falling over! Is it the rotation that's the issue? I've been hitting my head against the wall for a few days trying to get this solved. any thoughts?
an small vid of what's happening: https://imgur.com/a/AyPvLtm
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
[RequireComponent(typeof(CharacterController))]
public class Player : MonoBehaviour
{
[SerializeField] private float playerSpeed = 10f;
[SerializeField] private float rotationSpeed = 8f;
public float SpeedChangeRate = 10.0f;
private Camera mainCamera;
private Vector3 targetPosition;
private CharacterController characterController;
private Coroutine coroutine;
private int groundLayer;
private void Awake() {
mainCamera = Camera.main;
characterController = GetComponent<CharacterController>();
groundLayer = LayerMask.NameToLayer("Ground");
}
void Update()
{
if (Mouse.current.leftButton.isPressed) Move();
}
private void Move() {
Ray ray = mainCamera.ScreenPointToRay(Mouse.current.position.ReadValue());
Physics.Raycast(ray: ray, hitInfo: out RaycastHit hit);
if (hit.collider && hit.collider.gameObject.layer.CompareTo(groundLayer) == 0) {
if (coroutine != null) StopCoroutine(coroutine);
coroutine = StartCoroutine(PlayerMoveTowards(hit.point));
targetPosition = hit.point;
}
}
private IEnumerator PlayerMoveTowards(Vector3 target) {
while (Vector3.Distance(transform.position, target) > 0.1f) {
Vector3 destination = Vector3.MoveTowards(transform.position, target, playerSpeed * Time.deltaTime);
Vector3 direction = target - transform.position;
Vector3 movement = direction.normalized * playerSpeed * Time.deltaTime;
characterController.Move(movement);
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction.normalized), rotationSpeed * Time.deltaTime);
yield return null;
}
}
}

The reason is that at close distances, the difference between the main player's Target and Pivot point becomes very small and the height will be effective in determining the direction. Just set the direction Y to 0 to solve the problem.
Vector3 direction = target - transform.position;
direction.y = 0;

Figured this out.
It was my capsule collider. I had it set to the X-Axis, causing the collider to be rotated 90 degrees.
So my character would move and then flip to the side. Updating the collider direct to be on the Y-Axis fixed the problem.

Related

Camera keeps rotating

I am trying to make a first-person game in Unity but I keep having issues with my character controller. The player keeps rotating when it collides with objects that have physics (Or rigidbody)
It doesn't rotate when it collides with objects that don't have physics.
It's not my mouse because my MouseX and Y Values aren't changing.
Here is the code for the Player
using System.Collections.Generic;
using UnityEngine;
using Unity.Netcode;
public class PlayerControllerRB : MonoBehaviour
{
public float speed = 10f;
public float jumpHeight = 4.65f;
[SerializeField] private Rigidbody rb;
private PlayerInput playerInput;
private PlayerInput.OnFootActions onFoot;
[SerializeField] private Camera cam;
public float xSensitivity = 8f;
public float ySensitivity = 8f;
private float xRotation;
private float yMovement;
private float hMovement;
[SerializeField] private Transform Feet;
[SerializeField] public LayerMask Ground;
private void Awake()
{
rb = GetComponent<Rigidbody>();
playerInput = new PlayerInput();
onFoot = playerInput.onFoot;
onFoot.Jump.performed += ctx => Jump();
}
private void Start()
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
#region
private void OnEnable()
{
playerInput.Enable();
onFoot.Enable();
}
private void OnDisable()
{
playerInput.Disable();
onFoot.Disable();
}
#endregion
private void FixedUpdate()
{
ProcessMove(onFoot.Movement.ReadValue<Vector2>());
}
private void Update()
{
ProcessLook(onFoot.Look.ReadValue<Vector2>());
}
void ProcessMove(Vector2 input)
{
Vector3 MoveDirection = Vector3.zero;
hMovement = input.x;
yMovement = input.y;
MoveDirection = transform.forward * yMovement + transform.right * hMovement;
//MoveDirection.y = rb.velocity.y;
Debug.Log(MoveDirection * speed);
rb.AddForce(MoveDirection * speed, ForceMode.Acceleration);
}
void Jump()
{
Ray ray = new Ray(Feet.position, Vector3.down);
RaycastHit info;
if(Physics.Raycast(ray, out info, 0.3f, Ground))
{
rb.AddForce(Vector3.up * jumpHeight, ForceMode.Impulse);
}
}
void ProcessLook(Vector2 input)
{
float MouseY = input.y;
float MouseX = input.x;
xRotation -= (MouseY * Time.deltaTime) * ySensitivity;
xRotation = Mathf.Clamp(xRotation, -80f, 80f);
cam.transform.localRotation = Quaternion.Euler(xRotation, 0, 0);
transform.Rotate(Vector3.up * (MouseX * Time.deltaTime) * xSensitivity);
}
}
I tried freezing the y rotation but then I get a jittry camera.
Can anyone help me? It would also be nice if you had any recommendations to improve the controller.
Please comment if you need any more information. Sorry if the post is junk, I'm new to Stackoverflow
Well, you said It doesn't rotate when it collides with objects that don't have physics. In order to use the colliders one of them has to have a rigibody component. So if that's the case maybe is the script that is inside the oncollisionenter causing the problems. But I don't see any oncollisionenter script here

cinemachine makes my camera movement laggy in unity

I'm curently using cinemachine to make a third person camera. My player's movements work and i wanted him to look in the direction he is moving but taking in consideration the rotation of the camera. It works when i don't move the camera while moving the player but when i move the camera the rotations of my player are laggy moreover every movement of my camera seems to be laggy too. Sorry for my english i hope it's clear here is my code :
public class ThirdPersonScript : MonoBehaviour
{
[SerializeField] private float speed;
[SerializeField] private float jumpForce;
[SerializeField] private Transform feet;
[SerializeField] private LayerMask floorMask;
[SerializeField] private Transform cam;
private Vector3 direction;
private Rigidbody rb;
private bool canJump;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
direction = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
direction = Quaternion.AngleAxis(cam.rotation.eulerAngles.y, Vector3.up) * direction;
if (direction.magnitude > 1.0f)
{
direction = direction.normalized;
}
direction *= speed;
canJump = Input.GetKeyDown(KeyCode.Space) ? true : false;
}
void FixedUpdate()
{
if (Physics.CheckSphere(feet.position, 0.1f, floorMask))
{
if (canJump)
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
else
rb.velocity = new Vector3(direction.x, 0, direction.z);
}
else
rb.velocity = new Vector3(direction.x, rb.velocity.y, direction.z);
if (direction != Vector3.zero)
{
Quaternion targetRotation = Quaternion.LookRotation(direction);
targetRotation = Quaternion.RotateTowards(transform.rotation, targetRotation, 1080*Time.fixedDeltaTime);
rb.MoveRotation(targetRotation);
}
}
}
and a screenshot of my cinemachine settings and my hierarchy :
Try change the direction in LateUpdate() but not Update() :
void LateUpdate()
{
direction = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
direction = Quaternion.AngleAxis(cam.rotation.eulerAngles.y, Vector3.up) * direction;
if (direction.magnitude > 1.0f)
{
direction = direction.normalized;
}
direction *= speed;
canJump = Input.GetKeyDown(KeyCode.Space) ? true : false;
}
LateUpdate is called after all Update functions have been called. This is useful to order script execution. For example a follow camera should always be implemented in LateUpdate because it tracks objects that might have moved inside Update.
https://docs.unity3d.com/ScriptReference/MonoBehaviour.LateUpdate.html

How to addforce to mouse location with a player movement script?

I have two codes that both work fine by themselves but they don't work together. One code moves the player up, down, left, right. The other code rotates the sprite and will launch the sprite facing the direction of the mouse. I can not get both of these codes to work at the same time. Please could use some help.
1st Script is Movement
public float moveSpeed;
private Rigidbody2D rb;
private Vector2 moveVelocity;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
Vector2 moveInput = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
moveVelocity = moveInput.normalized * moveSpeed;
}
void FixedUpdate()
{
rb.MovePosition(rb.position + moveVelocity * Time.deltaTime);
}
2nd Script is Launching
// Movement
public float thrust = 10f;
public Rigidbody2D rb;
//Aiming
public Camera cam;
Vector2 mousePos;
void Update()
{
//aiming
mousePos = cam.ScreenToWorldPoint(Input.mousePosition);
}
void FixedUpdate()
{
Move();
//aim
Vector2 lookDirection = mousePos - rb.position;
float angle = Mathf.Atan2(lookDirection.y, lookDirection.x) * Mathf.Rad2Deg;
rb.rotation = angle;
}
void Move()
{
if (Input.GetMouseButtonDown(0))
{
rb.AddRelativeForce(Vector2.right * thrust, ForceMode2D.Impulse);
}
}

Jump in using Rigidbody or Character controller

i have been recreating my jump code, i have it all done but i can't add force or anything else.
Here's my code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class pBeh : MonoBehaviour
{
CharacterController characterController;
public float MovementSpeed = 1;
public float Gravity = 9.8f;
private float velocity = 0;
private Camera mainCam;
public Rigidbody rb;
public float jumpSpeed = 5.2f;
private Vector3 movingDirection = Vector3.zero;
public CharacterController controller;
public float speed;
float turnSmoothVelocity;
public float turnSmoothTime;
public bool canJump = false;
private void Start()
{
characterController = GetComponent<CharacterController>();
mainCam = Camera.main;
}
void Update()
{
// player movement - forward, backward, left, right
float horizontal = Input.GetAxis("Horizontal") * 10;
float vertical = Input.GetAxis("Vertical") * 10;
Vector3 camRightFlat = new Vector3(mainCam.transform.right.x, 0,
mainCam.transform.right.z).normalized;
Vector3 camForwardFlat = new Vector3(mainCam.transform.forward.x, 0,
mainCam.transform.forward.z).normalized;
characterController.Move((camRightFlat * horizontal + camForwardFlat * vertical)
* Time.deltaTime);
// Gravity
if (characterController.isGrounded)
{
velocity = 0;
}
else
{
velocity -= Gravity * Time.deltaTime;
characterController.Move(new Vector3(0, velocity, 0));
}
if (canJump == true && Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("Jumped");/*
transform.Translate(Vector3.up * 5.0f * Time.deltaTime);
rb.AddRelativeForce(Vector3.up * 8.0f);
rb.AddForce(Vector3.up * 8.0f)
i have tried a lot more, but it just doesn't work.
The sphere (Player) does nothing or shakes.
*/
}
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.tag == "enemy")
{
SceneManager.LoadScene("SampleScene");
}
}
void FixedUpdate()
{
if ((controller.collisionFlags & CollisionFlags.Below) != 0)
{
//Debug.Log("ground");
canJump = true;
}
else
{
canJump = false;
}
}
As i said it works just fine i just can't find reason why i cannot jump.
I have all character controller right and rigidbody too. If you could help i would be happy.
Btw i am beginner so i copied movement to be same as camera. Thanks!
From what I know, rigidbody and character controller do not work together (on the same object) so you have to choose one or the other, if you are using rigidbody then a ground check or similiar stuff would not be necessary since rigidbody is using unity physicis system so a lot of the stuff would be already done for you to simulate physics but you should still read thru the document

How do i make my character move in the direction of the camera (Unity)

In Unity I want to make it so that when I hold w, instead of going in a single direction I want it to go forward in the direction of my camera how do I do that? (Sorry I'm new to unity)
EDIT: The movement script is:
using UnityEngine;
using System.Collections;
public class Player_Movement : MonoBehaviour {
public float speed = 6.0F;
public float jumpSpeed = 8.0F;
public float gravity = 20.0F;
private Vector3 moveDirection = Vector3.zero;
void Update() {
CharacterController controller = GetComponent<CharacterController>();
if (controller.isGrounded) {
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= speed;
if (Input.GetButton("Jump"))
moveDirection.y = jumpSpeed;
}
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
}
}
As indicated by #lockstock, the direction the camera is facing can be retrieved from its transform. Here is an example below if you want to know how to use it.
public class Player_Movement : MonoBehaviour
{
public float speed = 6.0F;
public float jumpSpeed = 8.0F;
public float gravity = 20.0F;
// Drag & Drop the camera in this field, in the inspector
public Transform cameraTransform ;
private Vector3 moveDirection = Vector3.zero;
void Update() {
CharacterController controller = GetComponent<CharacterController>();
if (controller.isGrounded) {
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
moveDirection = cameraTransform.TransformDirection(moveDirection);
moveDirection *= speed;
if (Input.GetButton("Jump"))
moveDirection.y = jumpSpeed;
}
moveDirection.y -= gravity * Time.deltaTime;
controller.Move(moveDirection * Time.deltaTime);
}
}
This scripts works without any error. I've tested it in Unity myself.
The forward direction of the camera is obtained by using Camera.main.transform.forward
turn your player so the blue axis is facing the same direction as the blue axis on the camera. then drag and drop the camera onto the player. now when you move the player, the camera will follow, and stay behind the player