0
votes

I'll start this off by saying I am very new to Unity and C#, and I'm making my first solo project after following a tutorial series for Unity. I'm starting to make a first person shooter game, I have camera movement down, and I just wrote some code to handle player movement and acceleration. Initially when moving around a flat plane it works fine, but as soon as but as soon as my player object (PlayerColliderParent) bumps into a cube i have placed into the scene, it starts moving on its own at a constant speed and direction, depending on how it bumped into the cube. There aren't any other scripts that move PlayerColliderParent other than PlayerColliderParentScript.cs.

Here's a video of the problem occuring why is it moving???

Here is PlayerColliderParentScript.cs (attached to PlayerColliderParent)

using System.Collections.Generic;
using UnityEngine;

public class PlayerColliderParentScript : MonoBehaviour
{
    public Transform cameraRotation;
    public Vector3 directionalInput;
    public float accelerationFactor = 0.1f;
    public float maxSpeed = 6f;
    public Vector3 directionalSpeed;

    // Start is called before the first frame update
    void Start()
    {
       
    }

    // Update is called once per frame
    void Update()
    {
        //rotate horizontally with camera
        transform.localEulerAngles = new Vector3(0, cameraRotation.localEulerAngles.y, 0);

    }

    void FixedUpdate()
    {
        //accelerate while movement key is held
        //z axis
        if (Input.GetKey(KeyCode.W))
        {
            directionalInput.z = 1;
            if (directionalSpeed.z < maxSpeed)
            {
                directionalSpeed.z += accelerationFactor;
            }
        }
        else if (Input.GetKey(KeyCode.S))
        {
            directionalInput.z = -1;
            if (directionalSpeed.z < maxSpeed)
            {
                directionalSpeed.z += accelerationFactor;
            }
        }
        else if (directionalSpeed.z > 0)
        {
            directionalInput.z = 0;
            directionalSpeed.z -= accelerationFactor;
        }
        else if (directionalSpeed.z < 0)
        {
            directionalInput.z = 0;
            directionalSpeed.z += accelerationFactor;
        }
        else
        {
            directionalInput.z = 0;
        }

        //x axis
        if (Input.GetKey(KeyCode.D))
        {
            directionalInput.x = 1;
            if (directionalSpeed.x < maxSpeed)
            {
                directionalSpeed.x += accelerationFactor;
            }
        }
        else if (Input.GetKey(KeyCode.A))
        {
            directionalInput.x = -1;
            if (directionalSpeed.x < maxSpeed)
            {
                directionalSpeed.x += accelerationFactor;
            }
        }
        else if (directionalSpeed.x > 0)
        {
            directionalInput.x = 0;
            directionalSpeed.x -= accelerationFactor;
        }
        else if (directionalSpeed.x < 0)
        {
            directionalInput.x = 0;
            directionalSpeed.x += accelerationFactor;
        }
        else
        {
            directionalInput.x = 0;
        }

        //move the player according to directional speed
        Vector3 direction = directionalInput.normalized * Time.deltaTime;
        float velocityX = direction.x * directionalSpeed.x;
        float velocityY = direction.y * directionalSpeed.y;
        float velocityZ = direction.z * directionalSpeed.z;
        Vector3 velocity = new Vector3(velocityX, velocityY, velocityZ);
        transform.Translate(velocity);
    }


}


1
Does the PlayerColliderParent have a Rigidbody?derHugo
If PlayerColliderParent does have a rigidbody, what is it's gravity and friction settings?DekuDesu
@derHugo - Yes, it doesMachCoyote
@DekuDesu not sure what gravity and friction settings you're reffering to, but it has a mass of 1, drag od 0, and angular drag of 0.05MachCoyote

1 Answers

2
votes

Make sure to make the Rigidbody have isKinematic enabled. This way you can control it in FixedUpdate via the transform.Translate and it won't react to any Physics while the collision detection is still intact.


Otherwise in general whenever you have a Rigidbody you don't have want to set values via the Transform component.

I'm pretty sure what happens is that after you are already moving, the Rigidbody has a certain velocity. You are never again changing that velocity so after a collision you have both, the user Input applied via Transform and the Rigidbody's own velocity.

Instead of using transform.Translate rather directly manipulate the Rigidbody.velocity itself.

[SerializeField] Rigidbody _rigidbody;

...

    //accelerate while movement key is held
    //z axis
    if (Input.GetKey(KeyCode.W))
    {
        directionalInput.z = 1;
        directionalSpeed.z += accelerationFactor * Time.deltaTime;
    }
    else if (Input.GetKey(KeyCode.S))
    {
        directionalInput.z = -1;
        directionalSpeed.z -= accelerationFactor * Time.deltaTime;
    }
    else
    {
        directionalInput.z = 0;

        if (directionalSpeed.z > 0)
        {
            directionalSpeed.z -= accelerationFactor * Time.deltaTime;
        }
        else if (directionalSpeed.z < 0)
        {
            directionalSpeed.z += accelerationFactor * Time.deltaTime;
        }
    }

    directionalSpeed.z = Mathf.Clamp(directionalSpeed.z, -maxSpeed, maxSpeed);

    //x axis
    if (Input.GetKey(KeyCode.D))
    {
        directionalInput.x = 1;
        directionalSpeed.x += accelerationFactor * Time.deltaTime;
    }
    else if (Input.GetKey(KeyCode.A))
    {
        directionalInput.x = -1;
        directionalSpeed.x -= accelerationFactor * Time.deltaTime;
    }
    else
    {
        directionalInput.x = 0;

        if (directionalSpeed.x > 0)
        {
            directionalSpeed.x -= accelerationFactor * Time.deltaTime;
        }
        else if (directionalSpeed.x < 0)
        {
            directionalSpeed.x += accelerationFactor * Time.deltaTime;
        }
    }

    directionalSpeed.x = Mathf.Clamp(directionalSpeed.x, -maxSpeed, maxSpeed);

    _rigidbody.velocity = directionalInput;

As mentioned by @Rhach also the rotation is an issue.

You should probably rather use e.g.

_rigidbody.MoveRotation(new Vector3(0, cameraRotation.localEulerAngles.y, 0));