c# - Unity3D - 防止3D角色在空中改变方向

标签 c# unity-game-engine 3d

我是一名学习视频游戏编程的二年级学生,我已经在这个问题上挣扎了一段时间,我想知道你们是否可以就如何解决这个问题提供最好的建议。

我有一个 3D 角色,可以行走、奔跑、跳跃、二段跳和旋转以面对光标。然而,我注意到一种错误,我的角色能够控制其在半空中的移动。

例如,如果你按住左Shift + W然后跳跃,你就可以停止向前移动,然后开始在半空中向左扫射.

这是我的代码:

void Update ()
{
    // Turns off all animations while in the air
    if (isInAir)
    {
        animator.SetBool("Running", false);
        animator.SetBool("Walking", false);
    }

    if (Input.GetKey(KeyCode.W))
    {
        // If the character is not in the air then turn on the walk animation
        if (!isInAir)
        {
            animator.SetBool("Walking", true);
        }
        transform.Translate(Vector3.forward * movementSpeed * Time.deltaTime);
    }
    else if (Input.GetKey(KeyCode.S))
    {
        // If the character is not in the air then turn on the walk animation
        if (!isInAir)
        {
            animator.SetBool("Walking", true);
        }
        transform.Translate(Vector3.back * movementSpeed * Time.deltaTime);
    }

    if (Input.GetKey(KeyCode.A))
    {
        // If the character is not in the air then turn on the walk animation
        if (!isInAir)
        {
            animator.SetBool("Walking", true);
        }
        transform.Translate(Vector3.left * movementSpeed * Time.deltaTime);
    }
    else if (Input.GetKey(KeyCode.D))
    {
        // If the character is not in the air then turn on the walk animation
        if (!isInAir)
        {
            animator.SetBool("Walking", true);
        }
        transform.Translate(Vector3.right * movementSpeed * Time.deltaTime);
    }

    if (Input.GetKey(KeyCode.LeftShift))
    {
        // If the character is not in the air then turn on the run animation 
        //  and change the character's movementSpeed
        if (!isInAir)
        {
            movementSpeed = runSpeed;
            animator.SetBool("Running", true);
        }
    }
    else
    {
        // If the character is not in the air then reset their movement speed
        //  and turn off the run animation.
        if (!isInAir)
        {
            movementSpeed = walkSpeed;
            animator.SetBool("Running", false);
        }
    }

    // When a key is released, turn off the movement animations
    // This does not cause an issue since each movement if statement turns the animation back on
    if (Input.GetKeyUp(KeyCode.W) || Input.GetKeyUp(KeyCode.S) || Input.GetKeyUp(KeyCode.A) || Input.GetKeyUp(KeyCode.D))
    {
        animator.SetBool("Walking", false);
        animator.SetBool("Running", false);
    }
    #endregion

    // Jumping
    if (Input.GetButtonDown("Jump") && jumpCounter != 2)
    {
        jumpCounter++;
        isInAir = true;
        myRigidbody.AddForce(new Vector3(0, jumpForce));
        if (jumpCounter == 1)
        {
            firstJumpStamp = Time.time;
        }
    }

    if(Physics.Raycast(groundCheckRay, groundCheckRayDistance) && Time.time > firstJumpStamp + 0.5f)
    {
        jumpCounter = 0;
        isInAir = false;
    }
}

我删除了所有与角色移动无关的代码。

有人可以给我一个关于我可以用来完成这项工作的方法的建议吗?

我不是要求提供代码来解决此问题,只是一个建议...

我觉得我需要自己学习这个,我只需要有人给我指明正确的方向。

如果您不理解部分代码,请随时询问我,我很乐意向您展示我正在尝试用它做什么。 :) 例如,也许您知道编写某些行的更好方法。

(我确实尽量避免使用 Input.GetAxis,因为我发现当我无法 100% 控制它时,很难进行移动)

最佳答案

我可以建议您重新评估您的要求并将其与您所写的内容进行比较。您所描述的内容与您在代码中所做的内容之间存在细微差别。首先,您希望该角色能够向左或向右移动,而不是同时移动这两个移动,前进和后退也是如此。

为了解决此问题,您可以使用 Input.GetAxis 而不是您现在使用的 Input.GetKey


我可以建议的第二件事是使用本地 Vector3 来计算力,然后将其应用于您的角色。然后,您可以根据 Vector3 值设置动画变量。


您的主要问题在于所使用的运动技术。由于您决定使用 Transform.Translate 而不是使用 Rigidbody 来移动角色,因此您必须计算帧上的位置增量。
假设您的角色将从位置 [ x:1.00f, y: 0.00f, z: 1.00f ] 开始,并朝 [ x: 0.30f, y: 0.00f, z: 0.70f ] 在帧 1 上,它决定跳跃。那么你要做的就是抢到之前的位置 (帧更改之前的那个)将是 [ x:1.00f, y: 0.00f, z: 1.00f ] 并从当前位置中减去它,即 [ x:1.30f ,y:0.00f,z:1.70f]。这将返回一个等于先前位置增量的向量 ([ x: 0.30f, y: 0.00f, z: 0.70f ] )。现在只需将此位置添加到当前位置,它应该保持相同的航向(方向)。
这不包括摩擦力,因此您的角色在半空中时将始终以相同的速度朝相同的方向移动。

即使您没有要求提供代码,但在其中描述它比用简单的英语描述要容易得多(至少对我来说是这样:))所以,这里有一个示例代码:

// value indicating what was the position before change
Vector3 previousPosition;

void Update ()
{
    // get user input as a vector
    Vector3 horizontal = Vector3.right * Input.GetAxis("horizontal");
    Vector3 vertical = Vector3.forward * Input.GetAxis("vertical");

    bool isRunning = Input.GetKey(KeyCode.LeftShift);
    float speedModifier = isRunning ? runSpeed : walkSpeed;

    // add these inputs together
    Vector3 currentVelocity = (horizontal + vertical);

    // check if player is in mid air
    if (IsInAir)
    {
        // if it is, get the previous and current positions
        // add calculate the distance between frames
        // and normalize it to get the movement direction
        Vector3 currentPosition = transfor.position;
        Vector3 direction = (currentPosition - previousPosition).Normalize();
        // apply movement direction to the "currentVelocity"
        currentVelocity = direction * speedModifier * Time.deltaTime;
    }
    else
    {
        // user is not in mid air so you can just calculate
        // the position change
        currentVelocity = currentVelocity.Normalize() * speedModifier * Time.deltaTime;

        if ( currentVelocity != Vector3.zero )
        {
            animator.SetBool("walking", !isRunning);
            animator.SetBool("running", isRunning);
        }
    }

    // current position ( before changes )
    // should be copied to a previous position
    // to calculate it in the next frame update
    previousPosition = currentPosition;

    // do the translation
    transform.Translate(currentVelocity);
}

附加信息: 我仍然强烈建议您从 Transform.Translate 切换到 Rigidbody,并在角色处于半空中时“重新使用”它的速度。这不需要您计算每帧的位置增量,从而使其更易于使用。

关于c# - Unity3D - 防止3D角色在空中改变方向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46171538/

相关文章:

c# - 从 CRM 沙盒插件调用 WCF(使用生成的客户端)抛出 System.Security.SecurityException

c# - 可以获取 C# Delegate 的 MSIL 吗?

c# - 如何在Unity测试脚本中触发OnMouseOver/OnMouseExit?

css - CSS3 中的反向 3d 旋转 - 透视原点,变换原点?

javascript - 如何在 three.js 中将 MTL 纹理添加到 OBJ

c# - 使用 MongoDB 和 C# 将元素附加到现有项目的数组

C# IEnumerable<Object> 到字符串

php - Unity + PHP + SSL + Https + 黑客

unity-game-engine - 检测 "player"是在屏幕中间的左边还是右边

c++ - 如何在 C++ 中使用 OpenGL 绘制 3D 超椭圆