简体   繁体   English

Unity c# 3D 在添加侧向移动时前后移动中断?

[英]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).我已经制作了这个 3d 字符 controller 脚本(我知道这很糟糕,但我试图从我 100% 理解的东西开始,然后再转向更复杂的东西)。 In this script, I made bools of wPressed, aPressed, sPressed, and dPressed in the update function.在这个脚本中,我在更新 function 中创建了 wPressed、aPressed、sPressed 和 dPressed 的布尔值。 I then made the FixedUpdate function and added this section of code:然后我做了 FixedUpdate function 并添加了这部分代码:

    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,它可能很糟糕......但它现在工作正常......但是当我尝试添加 a 和 d 运动时,

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.它也有效,但它现在破坏了 w 和 s 移动脚本。 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.我建议研究GetAxis ,这是一种类似的方法,但减少了输入检查的次数。

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.因此,即使按下w (或其他任何东西),您也可以设置整个速度 = 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请注意,默认情况下 Unity 也通过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.将始终在 (A == false && D == false) 时执行,即使 W/S 也被按下。 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,然后根据输入制作 single player.velocity = newVec。

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)也有 Input.GetAxis 解决方案,但要小心,因为它在频繁调用时会导致轻微的性能损失(例如一帧 100-1000 次)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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