问题:
在《Unity和C#游戏编程入门》第五版的学习过程中,书上第196页的实践——按空格键使玩家跳跃,按照书上写的代码编写脚本后,在项目Play后出现有的时候按下空格键角色并不跳跃,有的时候又能跳跃
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
//速度
public float jumpVelocity = 5f;
private Rigidbody _rb;
// Start is called before the first frame update
void Start()
{
_rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
}
private void FixedUpdate()
{
if (Input.GetKeyDown(KeyCode.Space))
{
_rb.AddForce(jumpVelocity * Vector3.up, ForceMode.Impulse);
}
}
}
问题出现的原因
将代码更改成如下形式之后再Play
bool isJumpPressed; //调加一个标志位
void Update()
{
isJumpPressed = Input.GetKeyDown(KeyCode.Space);
if (isJumpPressed)
{
Debug.Log("Update Jump");
}
}
private void FixedUpdate()
{
if (isJumpPressed)
{
Debug.Log("FixedUpdate Jump");
}
}
发现Console栏出现如下输出
可以发现系统打印输出了很多次Update Jump后才打印输出了一次FixedUpdate Jump,这说明系统是在调用了多次Update方法之后才调用了一次FixedUpdate方法。Unity中Update方法是每一帧调用一次,FixUpdate是每次物理更新调用一次,所以这就解释了问题所在:为什么多次按下空格键物体才可能跳动一次。
解决方式
可以通过将FixUpdate方法中的if循环直接放在Update方法中,但是与刚体有关的代码都要放在FixUpdate方法中,因此并不推荐这种方法。
可以通过添加一个标志位来记录空格键的按下情况来解决这个问题
public class PlayerBehavior : MonoBehaviour
{
public float jumpVelocity = 5f;
bool isJumpPressed; //添加一个标志位
private Rigidbody _rb;
// Start is called before the first frame update
void Start()
{
_rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
isJumpPressed = true;
Debug.Log("Update Jump");
}
}
//与物理(刚体)相关的代码都要放到FixedUpdate方法中
void FixedUpdate()
{
if (isJumpPressed)
{
_rb.AddForce(jumpVelocity * Vector3.up, ForceMode.Impulse);
Debug.Log("FixedUpdate Jump");
isJumpPressed = false;
}
}
}
再次Play,可以看到Console栏中如下结果
Update被调用了一次FixUpdate也被调用了一次,每次按下空格物体也可以实现跳跃,问题得到解决。
参考:Unity Input.GetKeyDown(KeyCode.Space)未检测到按键 - 问答 - 腾讯云开发者社区-腾讯云 (tencent.com)