我正在Unity中制作游戏,您可以在其中移动WASD并有跳跃的空间。这是我的代码:
using UnityEngine;
public class PlayerMovement : MonoBehaviour {
public Rigidbody rb;
public bool canJump;
void FixedUpdate () {
if (Input.GetKey("w"))
{
rb.AddForce(0, 0, 750 * Time.deltaTime, ForceMode.Acceleration);
}
if (Input.GetKey("a"))
{
rb.AddForce(-750 * Time.deltaTime, 0, 0, ForceMode.Acceleration);
}
if (Input.GetKey("s"))
{
rb.AddForce(0, 0, -750 * Time.deltaTime, ForceMode.Acceleration);
}
if (Input.GetKey("d"))
{
rb.AddForce(750 * Time.deltaTime, 0, 0, ForceMode.Acceleration);
}
if (canJump)
{
if (Input.GetKeyDown("space"))
{
rb.AddForce(0, 10, 0, ForceMode.VelocityChange);
Debug.Log("jump");
canJump = false;
}
}
Vector3 v = rb.velocity;
v.y = 0;
v = Vector3.ClampMagnitude(v, 6);
v.y = rb.velocity.y;
rb.velocity = v;
}
void OnCollisionEnter(Collision other)
{
if (other.gameObject.name == "Ground")
{
canJump = true;
}
}
void OnCollisionExit(Collision other)
{
if (other.gameObject.name == "Ground")
{
canJump = false;
}
}
}
但是,当我跳时,它有时会跳得很高,有时甚至一点都跳不起来。我测试了按住空格键是否有任何作用,没有。我已经尝试过使用ForceMode.Impulse和ForceMode.VelocityChange,但是跳转仍然不一致。
我还注意到,玩家在地板上的Y值约为0.23时才跳到空中。像这样,它也可以是〜0.16,并且根本不会跳得很高。
最低的跳跃使它的Y值达到〜0.7,但是最高的跳跃使它的价值达到4.83左右。
如果有人有任何想法,我将非常感激。
答案 0 :(得分:4)
我通常要做的是检查我是向上还是向下。我只接受地面检查,如果我向下走。
void OnCollisionEnter(Collision other)
{
if (other.gameObject.name == "Ground" && rb.velocity.y < 0)
{
canJump = true;
}
}
但是,您使用getKeyDOWN
并不是要占用空间等。
所以我接下来要推荐的是:在跳跃之前将Velocity.y设置为0。
if (Input.GetKeyDown("space"))
{
Vector3 vel = rb.velocity;
vel.y = 0;
rb.velocity = vel;
rb.AddForce(0, 10, 0, ForceMode.VelocityChange);
// ...
}
编辑:等等,我的第一个念头是“他使用getKey并保留了空格”,第二个念头是:“他错过了Time.deltaTime”。但是现在我看到了:
您在FixedUpdate中使用了Input.Get...
!
让我解释一下:
在调用所有Update
之前评估所有输入。
As you can see in the execution Order在更新之前就已处理Input事件。
现在,根据(取决于)帧速率,与(几乎)恒定的FixedUpdate相比,Update被频繁或很少调用。
因此,在Update
次调用之间,FixedUpdateUpdate可以多次调用。这意味着输入事件只运行了一次。
所以我不得不假设Input.GetKeyDown(Key.SPACE)
在多个FixedUpdates中都是正确的!
轻松修复:
bool jump_pressed = false;
void Update()
{
if(Input.GetKeyDown("space"))
{
jump_pressed = true;
}
if(Input.GetKeyUp("space"))
{
jump_pressed = false;
}
}
void FixedUpdate()
{
if(jump_pressed)
{
jump_pressed = false;
rb.AddForce(0, 10, 0, ForceMode.VelocityChange);
// etc...
}
}
因此,您只需处理Update中的所有Input逻辑,然后在固定Update中执行其余的逻辑。
当然,在FixedUpdate中必须将jump_pressed设置为false,因为否则它将保持为多个FixedUpdates。
edit2 :我再次查看了您的代码。无论做什么,无论是在FixedUpdate还是Update中,都不要在Time.deltaTime
中使用AddForce
。
AddForce将操纵速度。在每个PhysicsUpdate中使用速度来移动变换。但是PhysicsUpdate / FixedUpdate尝试以(几乎)固定的速率运行,而Time.deltaTime为您提供了最后一个(更新)帧的经过时间。
如果您自己移动转换(position +=
...)-使用Time.deltaTime。但是在使用AddForce时不要使用它。
答案 1 :(得分:0)
好吧,如果您需要此功能来紧急修复。抓住统一的默认FPS角色并探索其属性和组件,并尝试对您自己的对象执行相同的操作。您稍后可以详细介绍