【问题标题】:Mid-air movement with first person controller in Unity3D, c#Unity3D中使用第一人称控制器进行空中移动,c#
【发布时间】:2019-07-19 18:35:31
【问题描述】:

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

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

非常感谢所有阅读本文的人:)

   [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;
   }
}

【问题讨论】:

  • 文档recommends 每帧只调用MoveSimpleMove 一次,但是你在协程之间跳转的每一帧都调用它们和PlayerMovement。您应该将跳转逻辑移到协程之外,这样您就可以在每次调用之前执行跳转例程逻辑,然后然后Move 进行一次调用,其中包括来自跳转逻辑和玩家输入的计算。
  • 似乎有相当多的调用方法没有出现在包含的代码中,因此 IMO 无法确定发生了什么。但是,我会仔细检查您对全局变量 isJumping 的使用。确保它不会阻塞我们看不到的代码中的某些内容。
  • @computercarguy 据我所知,这段代码中使用的所有方法要么在这里定义,要么在标准统一库中。
  • 你找到这个问题的解决方案了吗?

标签: c# unity3d controller


【解决方案1】:

文档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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-12
    相关资源
    最近更新 更多