简体   繁体   中英

Unity c# 3D movement forwards and backwards breaks when adding side movement?

Beginner question so please don't hate. I've made this 3d character controller script (I know it's terrible but I'm trying to begin with something I 100% understand before moving to more complex things). In this script, I made bools of wPressed, aPressed, sPressed, and dPressed in the update function. I then made the FixedUpdate function and added this section of code:

    if (wPressed == true)
    {
        player.velocity = transform.forward * movementSpeed;
    }

    if (sPressed == true)
    {
        player.velocity = -transform.forward * movementSpeed;
    }

    if (wPressed == false && sPressed == false)
    {
        player.velocity = transform.forward * 0;
    }

    if (wPressed == true && sPressed == true)
    {
        player.velocity = transform.forward * 0;
    }

Its probably bad... But it worked fine for now... However when I tried adding the a and d movement,

if (aPressed == true)
{
    player.velocity = -transform.right * movementSpeed;
}

if (dPressed == true)
{
    player.velocity = transform.right * movementSpeed;
}

if (aPressed == false && dPressed == false)
{
    player.velocity = transform.right * 0;
}

if (aPressed == true && dPressed == true)
{
    player.velocity = transform.right * 0;
}

It also worked, but it now broke the w and s movement script. Why is that?

Here is the entire code

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

public class PlayerMovement : MonoBehaviour
{
    bool dPressed;
    bool aPressed;
    bool wPressed;
    bool sPressed;
    Rigidbody player;
    private int movementSpeed;

    // Start is called before the first frame update
    void Start()
    {
        player = GetComponent<Rigidbody>();
        movementSpeed = 5;
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKey(KeyCode.W))
        {
            wPressed = true;
        }

        if (Input.GetKeyUp(KeyCode.W))
        {
            wPressed = false;
        }

        if (Input.GetKey(KeyCode.S)) 
        {
            sPressed = true;        
        }

        if (Input.GetKeyUp(KeyCode.S))
        {
            sPressed = false;
        }

        if (Input.GetKey(KeyCode.A)) 
        {
            aPressed = true;
        }

        if (Input.GetKeyUp(KeyCode.A))
        {
            aPressed = false;
        }

        if (Input.GetKey(KeyCode.D)) 
        {
            dPressed = true;
        }

        if (Input.GetKeyUp(KeyCode.D))
        {
            dPressed = false;        
        }
    }

    private void FixedUpdate()
    {
        if (wPressed == true)
        {
            player.velocity = transform.forward * movementSpeed;
        }

        if (sPressed == true)
        {
            player.velocity = -transform.forward * movementSpeed;
        }

        if (wPressed == false && sPressed == false)
        {
            player.velocity = transform.forward * 0;
        }

        if (wPressed == true && sPressed == true)
        {
            player.velocity = transform.forward * 0;
        }

        if (aPressed == true)
        {
            player.velocity = -transform.right * movementSpeed;
        }

        if (dPressed == true)
        {
            player.velocity = transform.right * movementSpeed;
        }

        if (aPressed == false && dPressed == false)
        {
            player.velocity = transform.right * 0;
        }

        if (aPressed == true && dPressed == true)
        {
            player.velocity = transform.right * 0;
        }


    }

}

Your issue is that whenever you have new input, you are fully overwriting your current velocity. For example, at every conditional statement, you have a

player.velocity = transform.direction * movementSpeed

Instead, you would want to isolate the velocity that each direction would change. I recommend looking into GetAxis , which is a similar approach but reduces the number of input checks.

float mH = Input.GetAxis ("Horizontal");
float mV = Input.GetAxis ("Vertical");
player.velocity = new Vector3 (mH * movementSpeed, rb.velocity.y, mV * movementSpeed);

You are always overwriting the entire velocity eg

player.velocity = transform.right * 0;

so even if w (or anything else) is pressed you set the entire velocity = 0,0,0. Forgetting all previously handled keys.


Rather do eg

private void Update()
{
    var movement = Vector2.zero;

    if (Input.GetKey(KeyCode.W))
    {
        movement.y += 1;
    }
    if(Input.GetKey(KeyCode.S))
    {
        movement.y -= 1;
    }

    if(Input.GetKey(KeyCode.A))
    {
        movement.x -= 1;
    }
    if(Input.GetKey(KeyCode.D))
    {
        movement.x += 1;
    }

    movement = Vector2.ClampMagnitude(movement, 1f);

    player.velocity = transform.forward * movement.y + transform.right * movement.x;
}

Note that by default Unity also provides this via GetAxis

var movement = new Vector2 (Input.GetAxis ("Horizontal"),  Input.GetAxis ("Vertical"));

movement = Vector2.ClampMagnitude(movement, 1f);

player.velocity = transform.forward * movement.y + transform.right * movement.x;

First of all, this section

if (aPressed == false && dPressed == false)
{
    player.velocity = transform.right * 0;
}

will execute always when (A == false && D == false) even if W/S are pressed too. Easy solution is just move this double-check section to the top.

More complex solution is create Vector3 for velocity and then make single player.velocity = newVec based on the input.

Vector3 dir = Vector3.zero;
var forward = transform.forward;
var right = transform.right;

if(aPressed)
  dir -= right;
if(dPressed)
  dir += right;
if(sPressed)
  dir -= forward;
if(wPressed)
  dir += forward;

//Same as Vector3.ClampMagnitude(vec, 1f) but a bit faster
dir = dir.normalized;
player.velocity = dir;

There is also Input.GetAxis solution, but be careful with it, because it can cause minor performance loss when called frequently (for instance 100-1000 times a frame)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM