1
votes

I have a SMALL a problem. In Unity 3D 2020 Beta, I've put a player with a sphere collider on it and some cubes (walls) with box colliders. I've added a player controller script to the player object.

I've put the camera above the plane where the player and the walls are on, and I've made that the player should rotate to face the mouse position. I used rigidbody.AddForce for movement in a FixedUpdate function. The player controller script is attached below:

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

public class PlayerController : MonoBehaviour
{
     [Header("Keys")]
     public KeyCode forward;
     public KeyCode backward;
     public KeyCode left;
     public KeyCode right;
     public KeyCode fire;
     [Header("Health")]
     public int hitpoints = 3;
     [Header("Movement")]
     public float speed;
     public float turningSpeed;
     [Header("Shooting")]
     public GameObject bulletPrefab;
     public Transform bulletSpawner;
     public float bulletSpeed;
     public float reloadTime;

     private float currentReload;
     private Rigidbody rb;
     private Quaternion targetRotation;
     void Start()
     {
         rb = GetComponent<Rigidbody>();
         currentReload = reloadTime;
     }


void LateUpdate()
{
    if (hitpoints == 0)
        Die();
    // Rotation
    var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    RaycastHit hit;
    if (Physics.Raycast(ray, out hit))
    { 
        targetRotation = Quaternion.LookRotation(hit.point - transform.position);
        Debug.DrawLine(transform.position, hit.point, Color.white);
    }
    transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, turningSpeed * Time.deltaTime);
    transform.eulerAngles = new Vector3(0, transform.rotation.eulerAngles.y, 0);

    currentReload += Time.deltaTime;
    // Shooting
    if (Input.GetKeyDown(fire) && currentReload >= reloadTime)
    {
        currentReload = 0f;
        GameObject bulletGO = Instantiate(bulletPrefab, bulletSpawner.position, transform.rotation);
        bulletGO.transform.position = bulletSpawner.position;
        Bullet bulletScript = bulletGO.GetComponent<Bullet>();
        bulletScript.speed = bulletSpeed;
        Destroy(bulletGO, 5f);
    }
}
void FixedUpdate()
{
    // Movement
    if (Input.GetKey(forward))
    {
        rb.AddForce(Vector3.forward * speed, ForceMode.Force);
    }
    if (Input.GetKey(backward))
    {
        rb.AddForce(-Vector3.forward * speed, ForceMode.Force);
    }
    if (Input.GetKey(left))
    {
        rb.AddForce(Vector3.left * speed, ForceMode.Force);
    }
    if (Input.GetKey(right))
    {
        rb.AddForce(Vector3.right * speed, ForceMode.Force);
    }
    //transform.position = new Vector3(transform.position.x, 10, transform.position.z);
    // ON RIGIDBODY I HAVE CONSTRAINS:
    // POSITION: Y (thats why I commented the line above)
    // ROTATION: X, Z (topdown -> so I want only rotation on Y)
}

private void Die()
{
    Destroy(gameObject);
}

}

But the problem is when the player hits very hard a wall, the sphere collider starts shaking and the player does not look at the mouse position exactly (it is somewhere 10 degrees away most of the times - it depends on how hard do I hit the walls).

I can record if it helps. If you want any information, feel free to ask! Any help will be appreciated! :)

1
More out of curiosity, why are you using lateUpdate and not regular old update?Jay
I was reading an article (not so useful I see) and there it said that maybe it's better after the other Updates. I mean, now it sounds a bit crazy :)) I think I'll change it back to classic Update :)Marc Vana
I see, i would be interested to read that if you still have the link handy. if not then don't worry about it :)Jay

1 Answers

0
votes

The problem here seems to be you're directly altering the transform of your object despite having a Rigidbody component. Generally you should avoid altering a transform directly when you have a Rigidbody attached, especially a non-kinematic one, as by attaching one you are signalling that the object is to be controlled by the physics simulation.

Solutions I would explore:

  • If you don't need a rigidbody, don't use one
  • If you can avoid altering the transform directly, then do not do so. You can rotate objects by applying torque and the likes
  • Try setting your object to kinematic if you don't need collisions to affect the rigidbody's physics
  • Manually set the torque and velocity of your object to 0 each fixed update