一切都要从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); } } }