Box spins when on ground and going forward

50 views Asked by At

I am trying to create a moving box that can jump, go forward/backward and right/left. But when this box is touching or has touched something with a collider, it starts spinning and doesn't allow me to move it/not a lot, so it starts going in circles (tiny ones).

The box has 3 components:
1 - Box collider which is not set to trigger
2 - Rigidbody which doesn't use gravity (I do it in my script)
3 - My script to move the player

enter image description here enter image description here

This is my custom script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(Collider))]

public class PlayerMovement : MonoBehaviour {
    public float moveSpeed = 9f;
    public float airMoveSpeed = 0.6f;
    public float jumpSpeed = 8f;
    public float gravity = 20f;
    public float groundDrag = 6f;
    public float airDrag = 4f;
    public Camera playerCamera;
    public float sensitivity = 2f;
    public float lookXLimit = 45f;
    public GroundCheck groundCheck;

    Vector3 moveDirection = Vector3.zero;
    Rigidbody rb;
    float rotationX = 0;
    bool isGrounded;

    [HideInInspector]
    public bool canMove = true;

    void Start()
    {
        rb = gameObject.GetComponent<Rigidbody>();

        isGrounded = false;

        // Lock cursor
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
    }

    void Update()
    {
        CheckGround();
        MovePlayer();
        Gun();
        ControlDrag();
    }

    void CheckGround() {
        isGrounded = groundCheck.isGrounded;
    }

    void MovePlayer() {
        // Recalculate move direction based on axes
        Vector3 forward = transform.TransformDirection(Vector3.forward);
        Vector3 right = transform.TransformDirection(Vector3.right);
        float curSpeedX = canMove ? moveSpeed * Input.GetAxis("Vertical") : 0;
        float curSpeedY = canMove ? moveSpeed * Input.GetAxis("Horizontal") : 0;
        moveDirection = (forward * curSpeedX) + (right * curSpeedY);

        // moveDirection.y -= gravity * 1000;

        if (Input.GetButton("Jump") && canMove && isGrounded)
        {
            rb.AddForce(transform.up * jumpSpeed, ForceMode.Impulse);
        }

        // Move the player
        if(isGrounded) {
            // transform.position += moveDirection;
            rb.AddForce(moveDirection * Time.deltaTime, ForceMode.Acceleration);
        } else {
            // transform.position += moveDirection;
            rb.AddForce(moveDirection * Time.deltaTime * airMoveSpeed, ForceMode.Acceleration);
        }

        // Player and Camera rotation
        if (canMove)
        {
            rotationX += -Input.GetAxis("Mouse Y") * sensitivity;
            rotationX = Mathf.Clamp(rotationX, -lookXLimit, lookXLimit);
            playerCamera.transform.localRotation = Quaternion.Euler(rotationX, 0, 0);
            transform.rotation *= Quaternion.Euler(0, Input.GetAxis("Mouse X") * sensitivity, 0);
        }
    }

    void ControlDrag() {
        if(isGrounded) rb.drag = groundDrag;
        else rb.drag = airDrag;
    }
}
1

There are 1 answers

1
JanS On

First, try putting the all physics related things into FixedUpdate(). This is where Unity does all the physics calculations. It's most likely not the cause here, but is generally recommended.

Does the collision happen "head on" or with no full face contact? It might just be that a partial collision induces a torque to your player movement and in the code you posted I don't see any parts that control angular movement.

If this is the case, then you can try to also freeze the rotation around the y axis, like you already did with the other two.

Another option would be to control the direction in which the cube faces via script.