Unity2D横板游戏角色跳跃优化代码

一切都要从Update()和FixedUpdate()这两个折磨怪讲起:

  • Update()在游戏运行时,每一帧都会调用一次该方法。但在不同的机器上,游戏运行效率,帧率是不同的;就算在一台机器上跑,帧率也是有浮动的。这就导致对Update()的调用并不是严格周期性的,如果将游戏中对刚体的运算放在Update()里——比如角色的移动、跳跃,可能会导致角色的移动速度、跳跃高度有变化,这不是我们想要的。
  • FixedUpdate()则是以固定周期调用(每0.02S调用一次),即使帧率不同,它的调用频率也是不变的,因此我们一般将刚体的运算放在FixedUpdate()中。

但这也会导致新的问题:
如果我们将角色的跳跃功能放在FixedUpdate()中,包括玩家输入检测和实现代码一并放在FixedUpdate()里,可能会遇到“按下跳跃键但是角色没反应”的情况。
这应该是FixedUpdate()方法的弊端,导致我们有时按下跳跃键后,输入并没有被FixedUpdate()接收。
因此我们可以将输入检测放在Update()里,将跳跃代码放在FixedUpdate()里。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FinalMovement : MonoBehaviour
{
    private Rigidbody2D rb;
    private Animator anim;
    private Collider2D Ccoll;

    public LayerMask ground;
    public Transform groundCheck;

    private float speed, jumpForce;
    private bool isJump, isGround;
    private int jumpCount;
    private bool jumpPressed;//当跳跃键按下的时候

    private void Awake()
    {
        rb = GetComponent<Rigidbody2D>();
        anim = GetComponent<Animator>();
        Ccoll = GetComponent<CircleCollider2D>();
        speed = 7f;
        jumpForce = 7f;
        jumpCount = 2;
    }

    void Update()
    {
        if(Input.GetButtonDown("Jump") && jumpCount>0)
        {
            jumpPressed = true;
        }
    }

    private void FixedUpdate()
    {
        Movement();

        //检测是否在地面
        isGround=Ccoll.IsTouchingLayers(ground);
        Jump();

        switchAnim();
    }

    private void Movement()
    {
        float horizontalMove = Input.GetAxisRaw("Horizontal");

        rb.velocity = new Vector2(horizontalMove * speed, rb.velocity.y);//设置速度
        if(horizontalMove!=0)
        {
            transform.localScale = new Vector3(horizontalMove, 1, 1);//更改朝向
        }
    }

    private void Jump()
    {
        if(isGround)
        {
            jumpCount = 2;
            isJump = false;
        }
        if (jumpPressed && isGround)
        {
            isJump = true;
            rb.velocity = new Vector2(rb.velocity.x, jumpForce);
            jumpCount--;
            jumpPressed = false;//别忘了设置
        }
        else if (jumpPressed && !isGround && jumpCount > 0)//在空中按下跳跃键
        {
            rb.velocity = new Vector2(rb.velocity.y, jumpForce);
            jumpCount--;
            jumpPressed = false;
        }
    }

    private void switchAnim()
    {
        anim.SetFloat("Running", Mathf.Abs(rb.velocity.x));
        if(Ccoll.IsTouchingLayers(ground))
        {
            anim.SetBool("Falling", false);
        }
        else if(rb.velocity.y>0)//跳跃
        {
            anim.SetBool("Jumping", true);
            anim.SetBool("Falling", false);
        }
        else if(rb.velocity.y<0)//下落
        {
            anim.SetBool("Jumping", false);
            anim.SetBool("Falling", true);
        }
    }
}

上一篇
下一篇