在Unity3D中使用第一人称控制器进行空中移动(C#)

时间:2019-07-19 18:35:31

标签: c# unity3d controller

我目前正在尝试在我尝试在我的项目中实现的第一人称角色控制器中启用空中移动。当前,玩家在空中时失去所有运动控制。

我试图在跳跃机制中复制正常的运动控制,但无济于事。对于这个问题的简单性,我深表歉意。在编码方面,我非常新手。

在此先感谢所有阅读本文的人:)

   [SerializeField] private string verticalInputName;
   [SerializeField] private float movementSpeed;

   private CharacterController charController;

   [SerializeField] private AnimationCurve jumpFallOff;
   [SerializeField] private float jumpMultiplier;
   [SerializeField] private KeyCode jumpKey;


   private bool isJumping;

   private void Awake()
   {
       charController = GetComponent<CharacterController>();
   }

   private void Update()
   {
       PlayerMovement();
   }

   private void PlayerMovement()
   {
       float horizInput = Input.GetAxis(horizontalInputName) * movementSpeed;
       float vertInput = Input.GetAxis(verticalInputName) * movementSpeed;

       Vector3 forwardMovement = transform.forward * vertInput;
       Vector3 rightMovement = transform.right * horizInput;

       charController.SimpleMove(forwardMovement + rightMovement);

       JumpInput();

   }

   private void JumpInput()
   {
       if (Input.GetKeyDown(jumpKey) && !isJumping)
       {
           isJumping = true;
           StartCoroutine(JumpEvent());
       }
   }

   private IEnumerator JumpEvent()
   {
       charController.slopeLimit = 90.0f;
       float timeInAir = 0.0f;


       do
       {

           float jumpForce = jumpFallOff.Evaluate(timeInAir);
           charController.Move(Vector3.up * jumpForce * jumpMultiplier * Time.deltaTime);

           timeInAir += Time.deltaTime;

           yield return null;
       } while (!charController.isGrounded && charController.collisionFlags != CollisionFlags.Above);

       float horizInput = Input.GetAxis(horizontalInputName) * movementSpeed;
       float vertInput = Input.GetAxis(verticalInputName) * movementSpeed;

       Vector3 forwardMovement = transform.forward * vertInput;
       Vector3 rightMovement = transform.right * horizInput;

       charController.SimpleMove(forwardMovement + rightMovement);
       isJumping = false;
   }
}

1 个答案:

答案 0 :(得分:0)

文档recommends仅每帧调用MoveSimpleMove 一次,但是您要在两次调用之间的每一帧之间调用它们协程和PlayerMovement

您应该将跳转逻辑移到协程之外,以便可以在每次调用之前执行跳转例程逻辑,然后然后进行一次对Move / SimpleMove的调用包括根据跳跃逻辑和玩家输入进行的计算。

这是将Move / SimpleMove的使用量减少到每帧仅一个呼叫的一种方法:

[SerializeField] private string horizontalInputName;
[SerializeField] private string verticalInputName;
[SerializeField] private float movementSpeed;

private CharacterController charController;

[SerializeField] private AnimationCurve jumpFallOff;
[SerializeField] private float jumpMultiplier;
[SerializeField] private KeyCode jumpKey;


private bool isJumping = false;
private float timeInAir = 0.0f;

private void Awake()
{
    charController = GetComponent<CharacterController>();
}

private void Update()
{
    PlayerMovement();
}

private void PlayerMovement()
{
    float forwardInput = Input.GetAxis(verticalInputName);
    float rightInput = Input.GetAxis(horizontalInputName);

    Vector3 forwardMovement = transform.forward * forwardInput;
    Vector3 rightMovement = transform.right * rightInput;
    Vector3 horizMovement = (forwardMovement+rightMovement) * movementSpeed;

    float jumpVelocity = JumpInput();

    if (isJumping)
    {
        Vector3 vertMovement = Vector3.up * jumpVelocity * jumpMultiplier;
        charController.Move((horizMovement + vertMovement) * Time.deltaTime) 
    } 
    else
    {
        charController.SimpleMove(horizMovement);
    }
}

private float JumpInput()
{
    float jumpVelocity = 0f;

    if (Input.GetKeyDown(jumpKey) && !isJumping)
    {
        isJumping = true;
        charController.slopeLimit = 90.0f;
        timeInAir = 0f;
    }

    if (isJumping){
        if (timeInAir == 0f || 
               (!charController.isGrounded 
                && charController.collisionFlags != CollisionFlags.Above))
        {
            jumpVelocity = jumpFallOff.Evaluate(timeInAir);
            timeInAir += Time.deltaTime;
        } 
        else
        {
            ifJumping = false;
        }
    }

    return jumpVelocity;
}