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

时间:2017-09-12 08:31:30

标签: c# unity3d 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%控制它时,我发现更难移动)

2 个答案:

答案 0 :(得分:4)

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

要获得此帮助,您可以使用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 ]。这将返回一个等于前一个位置delta([ 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,然后重新使用"角色在半空中时的速度。这不需要您计算每帧的位置增量,使其更容易使用。

答案 1 :(得分:1)

我认为您需要的是将transform移到if。因为现在你正在以任何方式移动物体,只是不更新​​布尔 例如:

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); //<-- New line
        }
        //transform.Translate(Vector3.forward * movementSpeed * Time.deltaTime); //<-- Removed line
    }

您需要为所有动作if s

执行此操作