使播放器转动中空气时放慢速度

发布于 2025-01-23 19:14:39 字数 2405 浏览 0 评论 0原文

我想进行类似于超级马里奥兄弟的跳跃,这意味着您可以移动空气中间空气,但是如果您朝着相反的方向移动,您会放慢脚步。

例如,如果您朝正确的方向跳跃,但向左中间空中移动,则可以向左移动,但非常缓慢。我尝试通过添加一个IF子句来检查玩家是否向左移动,然后播放速度的一半,但由于某种原因不起作用。

这是我的代码:

private Rigidbody rb;
[SerializeField] private float jumpForce;
[SerializeField] private float playerSpeed;
private float distToGround = 0.0051904f;
public bool isGrounded = false;
private bool _jump;
private float _horizontal;
private bool _movingLeft;
private bool _movingRight;
private bool _turnedLeft;
private bool _turnedRight;
private BoxCollider playerFeet;

private void Awake()
{
    rb = gameObject.GetComponent<Rigidbody>();
}

private void Start()
{

}

private void Update()
{
    GetInputs();
}

private void FixedUpdate()
{
    //PlayerJump
    if (_jump && _turnedRight == true)
    {
        transform.rotation = Quaternion.Euler(0, 0, 0);
        rb.AddForce(new Vector3(0, jumpForce), ForceMode.Impulse);
        _jump = false;
    }
    else if (_jump && _turnedLeft == true)
    {
        transform.rotation = Quaternion.Euler(0, -180, 0);
        rb.AddForce(new Vector3(0, jumpForce), ForceMode.Impulse);
        _jump = false;
    }

    //RotatePlayerDependingWhereHeMoves
    if(_movingLeft == true && isGrounded)
    {
        gameObject.transform.rotation = Quaternion.Euler(0f, 180f, 0f);
        _movingLeft = false;
    }

    if (_movingRight == true && isGrounded)
    {
        gameObject.transform.rotation = Quaternion.Euler(0f, 0f, 0f);
        _movingRight = false;
    }

    //MovePlayer
    rb.velocity = new Vector3(rb.velocity.x, rb.velocity.y, _horizontal * -playerSpeed);

    //ChecksIfGrounded
    GroundCheck();
}

void GetInputs()
{
    _horizontal = Input.GetAxisRaw(Tags.HORIZONTAL_AXIS);

    if(isGrounded && Input.GetKeyDown(KeyCode.Space))
    {
        Debug.Log("Player pressed Jump");
        _jump = true;
    }

    if(_horizontal == -1)
    {
        _movingLeft = true;
    }
    else if(_horizontal == 1)
    {
        _movingRight = true;
    }

    if(transform.rotation.y == 0)
    {
        _turnedRight = true;
    }
    else if(transform.rotation.y == -180)
    {
        _turnedLeft = true;
    }
}


void GroundCheck()
{
    if(Physics.Raycast(transform.position, Vector3.down, distToGround + 0.1f))
    {
        isGrounded = true;
    }
    else
    {
        isGrounded = false;
    }
}

I wanted to do a jump similar to Super Mario Bros meaning you can move mid air but if you move in the opposite direction that you started your jump in you will slow down.

For example if you jump in the right direction but move to the left mid-air you can move to the left but very slowly. I tried doing it by adding a if clause that checks if the player is moving to the left and then half the player speed but for some reason that didn't work.

Here's my code:

private Rigidbody rb;
[SerializeField] private float jumpForce;
[SerializeField] private float playerSpeed;
private float distToGround = 0.0051904f;
public bool isGrounded = false;
private bool _jump;
private float _horizontal;
private bool _movingLeft;
private bool _movingRight;
private bool _turnedLeft;
private bool _turnedRight;
private BoxCollider playerFeet;

private void Awake()
{
    rb = gameObject.GetComponent<Rigidbody>();
}

private void Start()
{

}

private void Update()
{
    GetInputs();
}

private void FixedUpdate()
{
    //PlayerJump
    if (_jump && _turnedRight == true)
    {
        transform.rotation = Quaternion.Euler(0, 0, 0);
        rb.AddForce(new Vector3(0, jumpForce), ForceMode.Impulse);
        _jump = false;
    }
    else if (_jump && _turnedLeft == true)
    {
        transform.rotation = Quaternion.Euler(0, -180, 0);
        rb.AddForce(new Vector3(0, jumpForce), ForceMode.Impulse);
        _jump = false;
    }

    //RotatePlayerDependingWhereHeMoves
    if(_movingLeft == true && isGrounded)
    {
        gameObject.transform.rotation = Quaternion.Euler(0f, 180f, 0f);
        _movingLeft = false;
    }

    if (_movingRight == true && isGrounded)
    {
        gameObject.transform.rotation = Quaternion.Euler(0f, 0f, 0f);
        _movingRight = false;
    }

    //MovePlayer
    rb.velocity = new Vector3(rb.velocity.x, rb.velocity.y, _horizontal * -playerSpeed);

    //ChecksIfGrounded
    GroundCheck();
}

void GetInputs()
{
    _horizontal = Input.GetAxisRaw(Tags.HORIZONTAL_AXIS);

    if(isGrounded && Input.GetKeyDown(KeyCode.Space))
    {
        Debug.Log("Player pressed Jump");
        _jump = true;
    }

    if(_horizontal == -1)
    {
        _movingLeft = true;
    }
    else if(_horizontal == 1)
    {
        _movingRight = true;
    }

    if(transform.rotation.y == 0)
    {
        _turnedRight = true;
    }
    else if(transform.rotation.y == -180)
    {
        _turnedLeft = true;
    }
}


void GroundCheck()
{
    if(Physics.Raycast(transform.position, Vector3.down, distToGround + 0.1f))
    {
        isGrounded = true;
    }
    else
    {
        isGrounded = false;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

無心 2025-01-30 19:14:39
  public class PlayMovement : MonoBehaviour
  {
  //Character's blood volume
   public int Hp = 1;
  // is it on the ground
   private bool isGround = false;
   //rigid body
   private Rigidbody2D rBody;
 //animation
   private Animator ani;
 //Get the sprite image (in order to flip the image later)
   private SpriteRenderer sr;

   void Start () {
    //Get these two components here
    rBody = GetComponent<Rigidbody2D>();
    ani = GetComponent<Animator>();
    sr = GetComponent<SpriteRenderer>();
   }


   void Update() {
      if (Hp <= 0)
      {
           return;
      }
      //Because the character just runs left and right, take the horizontal axis
      float horizontal = Input.GetAxis("Horizontal");
      //if the horizontal axis is not 0
      if (horizontal != 0)
      {
        //go ahead
        transform.Translate(transform.right * Time.deltaTime * 1 * horizontal);
        //Flip the picture (simulate turning the head)
        if (horizontal > 0)
        {
            //The description is to go to the right, so it does not flip
            sr.flipX = false;
        }
        if (horizontal < 0)
        {
            sr.flipX = true;
        }
        //move animation
        ani.SetBool("Run", true);
      }
      else
      {
        ani.SetBool("Run", false);
      }
      //jump. The I key is pressed, and the character is standing on the ground.
      if (Input.GetKeyDown(KeyCode.I) && isGround == true)
      {
        //Jump force (up, acting on rigid body)
        rBody.AddForce(Vector2.up * 200);
        //Play the jump sound
        AudioManager.Instance.PlaySound("jump");
      }
   
      //Use the ray to detect whether it touches the ground (method 1)
      //Draw the ray. Starting from the center point, go down *0.1 meters.
      Debug.DrawRay(transform.position, Vector2.down * 0.1f);
       /* Create 2d rays. Features: You can return directly. 3d returns a boolean value, hit is on it, and out is used to give the hit value.
        And in the brackets, you can directly fill in the starting point, direction, distance, and detection layer of the ray (here is the 8th layer). */
    
      RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.down, 0.1f, 1<<8);
     if(hit.collider != null)
     {
       //Indicate that it hit the ground
       isGround = true;
       //Turn off the jump animation
       ani.SetBool("Jump", false);
     }
     else
     {
       // did not touch the ground (in the air)
       isGround = false;
       ani.SetBool("Jump", true);
     }
  }

  //The player's death method, because it is called in the enemy's code, is public here
   public void Die()
   {
      Hp--;
       if (Hp <= 0)
      {
        //die
        ani.SetTrigger("Die");
        // delete the collider. (Because when the player dies, it is dropped from the scene, so just delete the collider, not the rigid body).
        Destroy(GetComponent<Collider2D>());
        //stop playing background music
        AudioManager.Instance.StopMusic();
        //play death music
        AudioManager.Instance.PlaySound("death");
        // make the player still
        rBody.velocity = Vector2.zero;
        // Make the player still, i.e. set its speed to 0. In order to prevent the player from dying in different situations, the height of the upward jump is different)
        rBody.velocity = Vector2.zero;
        //jump. give an upward force
        rBody.AddForce(Vector2.up * 150f);
        // Delay. Play after 1 second
        Invoke("Die2", 1f);
      }
   }
      void Die2()
      {
       AudioManager.Instance.PlaySound("Death 2");
      }
  }

这是Mario PlayControl的脚本代码,希望它会有所帮助,因为您提供了测试代码很难的代码

  public class PlayMovement : MonoBehaviour
  {
  //Character's blood volume
   public int Hp = 1;
  // is it on the ground
   private bool isGround = false;
   //rigid body
   private Rigidbody2D rBody;
 //animation
   private Animator ani;
 //Get the sprite image (in order to flip the image later)
   private SpriteRenderer sr;

   void Start () {
    //Get these two components here
    rBody = GetComponent<Rigidbody2D>();
    ani = GetComponent<Animator>();
    sr = GetComponent<SpriteRenderer>();
   }


   void Update() {
      if (Hp <= 0)
      {
           return;
      }
      //Because the character just runs left and right, take the horizontal axis
      float horizontal = Input.GetAxis("Horizontal");
      //if the horizontal axis is not 0
      if (horizontal != 0)
      {
        //go ahead
        transform.Translate(transform.right * Time.deltaTime * 1 * horizontal);
        //Flip the picture (simulate turning the head)
        if (horizontal > 0)
        {
            //The description is to go to the right, so it does not flip
            sr.flipX = false;
        }
        if (horizontal < 0)
        {
            sr.flipX = true;
        }
        //move animation
        ani.SetBool("Run", true);
      }
      else
      {
        ani.SetBool("Run", false);
      }
      //jump. The I key is pressed, and the character is standing on the ground.
      if (Input.GetKeyDown(KeyCode.I) && isGround == true)
      {
        //Jump force (up, acting on rigid body)
        rBody.AddForce(Vector2.up * 200);
        //Play the jump sound
        AudioManager.Instance.PlaySound("jump");
      }
   
      //Use the ray to detect whether it touches the ground (method 1)
      //Draw the ray. Starting from the center point, go down *0.1 meters.
      Debug.DrawRay(transform.position, Vector2.down * 0.1f);
       /* Create 2d rays. Features: You can return directly. 3d returns a boolean value, hit is on it, and out is used to give the hit value.
        And in the brackets, you can directly fill in the starting point, direction, distance, and detection layer of the ray (here is the 8th layer). */
    
      RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.down, 0.1f, 1<<8);
     if(hit.collider != null)
     {
       //Indicate that it hit the ground
       isGround = true;
       //Turn off the jump animation
       ani.SetBool("Jump", false);
     }
     else
     {
       // did not touch the ground (in the air)
       isGround = false;
       ani.SetBool("Jump", true);
     }
  }

  //The player's death method, because it is called in the enemy's code, is public here
   public void Die()
   {
      Hp--;
       if (Hp <= 0)
      {
        //die
        ani.SetTrigger("Die");
        // delete the collider. (Because when the player dies, it is dropped from the scene, so just delete the collider, not the rigid body).
        Destroy(GetComponent<Collider2D>());
        //stop playing background music
        AudioManager.Instance.StopMusic();
        //play death music
        AudioManager.Instance.PlaySound("death");
        // make the player still
        rBody.velocity = Vector2.zero;
        // Make the player still, i.e. set its speed to 0. In order to prevent the player from dying in different situations, the height of the upward jump is different)
        rBody.velocity = Vector2.zero;
        //jump. give an upward force
        rBody.AddForce(Vector2.up * 150f);
        // Delay. Play after 1 second
        Invoke("Die2", 1f);
      }
   }
      void Die2()
      {
       AudioManager.Instance.PlaySound("Death 2");
      }
  }

Here's the script code for Mario PlayControl, hope it helps, as you provide the code to test it's hard

温柔一刀 2025-01-30 19:14:39

将输入与当前方向进行比较,刚性在空中时正在移动。然后,以所需的速度以速度消失。您可以在另一种方法中执行此操作。

private void FixedUpdate()
{
    //PlayerJump
    if (_jump && _turnedRight == true)
    {
        transform.rotation = Quaternion.Euler(0, 0, 0);
        rb.AddForce(new Vector3(0, jumpForce), ForceMode.Impulse);
        _jump = false;
    }
    else if (_jump && _turnedLeft == true)
    {
        transform.rotation = Quaternion.Euler(0, -180, 0);
        rb.AddForce(new Vector3(0, jumpForce), ForceMode.Impulse);
        _jump = false;
    }

    //RotatePlayerDependingWhereHeMoves
    if(_movingLeft == true && isGrounded)
    {
        gameObject.transform.rotation = Quaternion.Euler(0f, 180f, 0f);
        _movingLeft = false;
    }

    if (_movingRight == true && isGrounded)
    {
        gameObject.transform.rotation = Quaternion.Euler(0f, 0f, 0f);
        _movingRight = false;
    }

    //MovePlayer
    if (!isGrounded)
    {
        //since the player is not touching the ground, modify speed in here
        ModifyMidAirSpeed();
    }
    else
    {
        //move player normally...
        rb.velocity = new Vector3(rb.velocity.x, rb.velocity.y, _horizontal * -playerSpeed);
    }

    //ChecksIfGrounded
    GroundCheck();
}

float air_speed_acceleration = 1.0f; //use this to change the rate at which speed is modified mid-air
void ModifyMidAirSpeed()
{
    Vector3 new_velocity = rb.velocity;
    //check if the rb's is moving on the horizontal axis
    if (rb.velocity.x != 0)
    {
        //is the moving direction the same as the input?
        bool isRBMovingRight = rb.velocity.x > 0;
        if (isRBMovingRight && _movingRight)
        {
            //yes it is
            //accelerate mid-air?
            new_velocity.x = Mathf.Lerp(new_velocity.x, _horizontal * -playerSpeed, air_speed_acceleration * Time.fixedDeltaTime);
            rb.velocity = new_velocity;
            return;
        }
        //no it is not!
        //slow down mid-air
        new_velocity.x = Mathf.Lerp(0, new_velocity.x, air_speed_acceleration * Time.fixedDeltaTime);
        rb.velocity = new_velocity;
        return;
    }
    //the player jumped while standing still
    //move towards desired direction mid-air?
    new_velocity.x = Mathf.Lerp(0, _horizontal * -playerSpeed, air_speed_acceleration * Time.fixedDeltaTime);
    rb.velocity = new_velocity;
}

上面,我写了一个示例,该示例应该使您可以降低玩家的速度中间。您可以使用方法modifymidairsPeed当玩家不触摸地面以处理中间运动并保持代码分开且整洁时。

我还建议将输入存储为vector2。这将使您使用更少的变量(我在谈论_MovingLeft_MovingRight),并且将来应该证明有用。


潜在的问题1

我在您的代码中注意到您修改了刚体速度的Z组件。但是,您将X轴上的精灵翻转,我也将精灵移动到X轴上。这可能是一个潜在的危险疏忽,因为从经典上讲,玩家沿X轴和Z移动用于深度。


解决方案2

我花了一些时间重写代码的部分,以查看是否有其他变量引起怪异行为。我还确保仅修改Z值以避免任何可能的混淆(再次,我建议沿X轴移动...)。尝试一下。

private Rigidbody rb;
[SerializeField] private float jumpForce;
[SerializeField] private float playerSpeed;
private float distToGround = 0.0051904f;
public bool isGrounded = false;
private bool jumpedThisFrame;
private bool facingRight = true;
private Vector3 inputs; //A Vector3 allows you to handle complex input in the future such as ducking + moving in one variable...
private float air_speed_acceleration = 1.0f; //use this to change the rate at which speed is modified mid-air
private BoxCollider playerFeet;

private void Awake()
{
    rb = gameObject.GetComponent<Rigidbody>();
}

private void Start()
{

}

private void Update()
{
    GetInputs();
    //I think it would be good to handle sprite flipping in here and avoid using quaternions to flip the player around
    HandleSpriteFlipping();
}

private void FixedUpdate()
{
    //I would do the ground check before processing inputs
    GroundCheck();
    
    Vector3 new_velocity;
    //handle inputs in order
    //first determine the move state the player is is:
    //grounded or not grounded?
    if (isGrounded)
    {
        //grounded
        //did the player just jump?
        if (jumpedThisFrame)
        {
            //handle jumping
            jumpedThisFrame = false; //set it back to false here, or in the GetInputs method or somewhere else before the start of the next frame
            //todo: add koyote time ?
            //to consider: maintain previous speed?
            HandleJump();
            return; 
        }
        //did not jump
        //then the player is walking/running etc...
        
        //I would lerp the speed here, but you set it directly if you want
        new_velocity = rb.velocity;
        new_velocity.z = inputs.x * playerSpeed; //!!! - did you mean to modify the X axis value? I keep to your code and use the Z axis...
        rb.velocity = new_velocity;
        return; 
    }
    //not grounded
    //handle mid-air movement here
    ModifyMidAirSpeed();
}

private void HandleSpriteFlipping()
{
    facingRight = transform.rotation.y == 0;
    //only flip sprites if grounded
    if (!isGrounded) return;
    
    if (inputs.x > 0)
    {
        //the player is moving right
        if (facingRight) return; //already facing right
        //otherwise face right
        Quaternion r = transform.rotation;
        r.y = 0;
        transform.rotation = r;
    }
    else
    {
        //the player is moving left
        if (!facingRight) return; //already facing left //check for -180 ?
        //otherwise face left
        Quaternion r = transform.rotation;
        r.y = 180; //what about -180 ?
        transform.rotation = r;
    }
}

private void HandleJump()
{
    //handle jump here...
    rb.AddForce(new Vector3(0, jumpForce), ForceMode.Impulse);
}

void ModifyMidAirSpeed()
{
    //is there input to handle?
    if (inputs.x == 0) return; //no input
    
    //does the player have any horizontal speed?
    if (rb.velocity.z == 0)
    {
        //nope
        //move towards desired direction
        Vector3 new_vel = rb.velocity;
        new_vel.z = inputs.x * playerSpeed;
        rb.velocity = new_vel;
        return;
    }
    //yup
    //does movement match with moving (or facing) direction?
    if (inputs.x > 0 && facingRight || inputs.x < 0 && !facingRight)
    {
        //match!
        //accelerate...
        Vector3 new_vel = rb.velocity;
        new_vel.z = inputs.x * playerSpeed;
        rb.velocity = new_vel;
        return;
    }
    //no match.
    //slow down
    Vector3 new_vel = rb.velocity;
    new_vel.z = 0.5f; //some low value or lerp to 0...
    rb.velocity = new_vel;
}

void GetInputs()
{
    inputs = Vector3.zero;
    inputs.x = Input.GetAxisRaw(Tags.HORIZONTAL_AXIS);

    if(isGrounded && Input.GetKeyDown(KeyCode.Space))
    {
        Debug.Log("Player pressed Jump this frame");
        jumpedThisFrame = true; //this variable should be changed to "_jumpedThisFrame" for better clarity...
    }
    
    //you don't need the variables: _movingLeft and _movingRight
    //you only need one variable for turning, similar to jumping: "turnedThisFrame" and "facingRight"
    //there is no need for the other two...
}


void GroundCheck()
{
    isGrounded = Physics.Raycast(transform.position, Vector3.down, distToGround + 0.1f);
}

Compare the input to the current direction the rigidbody is moving when mid-air. Then, chip away at the speed at a desired rate. You can do this inside a different method.

private void FixedUpdate()
{
    //PlayerJump
    if (_jump && _turnedRight == true)
    {
        transform.rotation = Quaternion.Euler(0, 0, 0);
        rb.AddForce(new Vector3(0, jumpForce), ForceMode.Impulse);
        _jump = false;
    }
    else if (_jump && _turnedLeft == true)
    {
        transform.rotation = Quaternion.Euler(0, -180, 0);
        rb.AddForce(new Vector3(0, jumpForce), ForceMode.Impulse);
        _jump = false;
    }

    //RotatePlayerDependingWhereHeMoves
    if(_movingLeft == true && isGrounded)
    {
        gameObject.transform.rotation = Quaternion.Euler(0f, 180f, 0f);
        _movingLeft = false;
    }

    if (_movingRight == true && isGrounded)
    {
        gameObject.transform.rotation = Quaternion.Euler(0f, 0f, 0f);
        _movingRight = false;
    }

    //MovePlayer
    if (!isGrounded)
    {
        //since the player is not touching the ground, modify speed in here
        ModifyMidAirSpeed();
    }
    else
    {
        //move player normally...
        rb.velocity = new Vector3(rb.velocity.x, rb.velocity.y, _horizontal * -playerSpeed);
    }

    //ChecksIfGrounded
    GroundCheck();
}

float air_speed_acceleration = 1.0f; //use this to change the rate at which speed is modified mid-air
void ModifyMidAirSpeed()
{
    Vector3 new_velocity = rb.velocity;
    //check if the rb's is moving on the horizontal axis
    if (rb.velocity.x != 0)
    {
        //is the moving direction the same as the input?
        bool isRBMovingRight = rb.velocity.x > 0;
        if (isRBMovingRight && _movingRight)
        {
            //yes it is
            //accelerate mid-air?
            new_velocity.x = Mathf.Lerp(new_velocity.x, _horizontal * -playerSpeed, air_speed_acceleration * Time.fixedDeltaTime);
            rb.velocity = new_velocity;
            return;
        }
        //no it is not!
        //slow down mid-air
        new_velocity.x = Mathf.Lerp(0, new_velocity.x, air_speed_acceleration * Time.fixedDeltaTime);
        rb.velocity = new_velocity;
        return;
    }
    //the player jumped while standing still
    //move towards desired direction mid-air?
    new_velocity.x = Mathf.Lerp(0, _horizontal * -playerSpeed, air_speed_acceleration * Time.fixedDeltaTime);
    rb.velocity = new_velocity;
}

Above, I wrote an example which should allow you to reduce the player's velocity mid-air. You can use the method ModifyMidAirSpeed when the player is not touching the ground to handle mid-air movement and keep your code separated and tidy.

I would also recommend storing input as a Vector2. This will allow you to use fewer variables (I'm talking about _movingLeft and _movingRight) and should prove helpful in the future.


Potential problem 1

I noticed in your code you modify the Z component of the rigidbody's velocity. But, you flip the sprite on the X axis and I move the sprite on the X axis too. This could be a potential dangerous oversight, because classically the player moves along the X axis and Z is used for depth.


Solution 2

I spent some time re-writing parts of your code to see if there was some other variable causing the weird behavior. I also made sure to only modify the Z value to avoid any possible confusion (again, I recommend moving along the X axis...). Try this out.

private Rigidbody rb;
[SerializeField] private float jumpForce;
[SerializeField] private float playerSpeed;
private float distToGround = 0.0051904f;
public bool isGrounded = false;
private bool jumpedThisFrame;
private bool facingRight = true;
private Vector3 inputs; //A Vector3 allows you to handle complex input in the future such as ducking + moving in one variable...
private float air_speed_acceleration = 1.0f; //use this to change the rate at which speed is modified mid-air
private BoxCollider playerFeet;

private void Awake()
{
    rb = gameObject.GetComponent<Rigidbody>();
}

private void Start()
{

}

private void Update()
{
    GetInputs();
    //I think it would be good to handle sprite flipping in here and avoid using quaternions to flip the player around
    HandleSpriteFlipping();
}

private void FixedUpdate()
{
    //I would do the ground check before processing inputs
    GroundCheck();
    
    Vector3 new_velocity;
    //handle inputs in order
    //first determine the move state the player is is:
    //grounded or not grounded?
    if (isGrounded)
    {
        //grounded
        //did the player just jump?
        if (jumpedThisFrame)
        {
            //handle jumping
            jumpedThisFrame = false; //set it back to false here, or in the GetInputs method or somewhere else before the start of the next frame
            //todo: add koyote time ?
            //to consider: maintain previous speed?
            HandleJump();
            return; 
        }
        //did not jump
        //then the player is walking/running etc...
        
        //I would lerp the speed here, but you set it directly if you want
        new_velocity = rb.velocity;
        new_velocity.z = inputs.x * playerSpeed; //!!! - did you mean to modify the X axis value? I keep to your code and use the Z axis...
        rb.velocity = new_velocity;
        return; 
    }
    //not grounded
    //handle mid-air movement here
    ModifyMidAirSpeed();
}

private void HandleSpriteFlipping()
{
    facingRight = transform.rotation.y == 0;
    //only flip sprites if grounded
    if (!isGrounded) return;
    
    if (inputs.x > 0)
    {
        //the player is moving right
        if (facingRight) return; //already facing right
        //otherwise face right
        Quaternion r = transform.rotation;
        r.y = 0;
        transform.rotation = r;
    }
    else
    {
        //the player is moving left
        if (!facingRight) return; //already facing left //check for -180 ?
        //otherwise face left
        Quaternion r = transform.rotation;
        r.y = 180; //what about -180 ?
        transform.rotation = r;
    }
}

private void HandleJump()
{
    //handle jump here...
    rb.AddForce(new Vector3(0, jumpForce), ForceMode.Impulse);
}

void ModifyMidAirSpeed()
{
    //is there input to handle?
    if (inputs.x == 0) return; //no input
    
    //does the player have any horizontal speed?
    if (rb.velocity.z == 0)
    {
        //nope
        //move towards desired direction
        Vector3 new_vel = rb.velocity;
        new_vel.z = inputs.x * playerSpeed;
        rb.velocity = new_vel;
        return;
    }
    //yup
    //does movement match with moving (or facing) direction?
    if (inputs.x > 0 && facingRight || inputs.x < 0 && !facingRight)
    {
        //match!
        //accelerate...
        Vector3 new_vel = rb.velocity;
        new_vel.z = inputs.x * playerSpeed;
        rb.velocity = new_vel;
        return;
    }
    //no match.
    //slow down
    Vector3 new_vel = rb.velocity;
    new_vel.z = 0.5f; //some low value or lerp to 0...
    rb.velocity = new_vel;
}

void GetInputs()
{
    inputs = Vector3.zero;
    inputs.x = Input.GetAxisRaw(Tags.HORIZONTAL_AXIS);

    if(isGrounded && Input.GetKeyDown(KeyCode.Space))
    {
        Debug.Log("Player pressed Jump this frame");
        jumpedThisFrame = true; //this variable should be changed to "_jumpedThisFrame" for better clarity...
    }
    
    //you don't need the variables: _movingLeft and _movingRight
    //you only need one variable for turning, similar to jumping: "turnedThisFrame" and "facingRight"
    //there is no need for the other two...
}


void GroundCheck()
{
    isGrounded = Physics.Raycast(transform.position, Vector3.down, distToGround + 0.1f);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文