我正在尝试将我朋友的 Scratch 游戏移植到 Unity 来娱乐,但减速代码导致玩家根据帧速率加速和减慢。最大 X 速度应为 6.75,即 30 fps(scratch 的通常帧速率),但当 FPS 更改时,其速度会变化到约 7.5。 代码(未完成):
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public Vector2 Velocity, WallJumpForce;
public float Acceleration, Decceleration;
public float Gravity, JumpForce;
public int TargetFPS;
void Update()
{
Velocity.y -= Gravity;
if(Input.GetKey("right") || Input.GetKey("d"))
Velocity.x += Acceleration * SDT();
if(Input.GetKey("left") || Input.GetKey("a"))
Velocity.x -= Acceleration * SDT();
Velocity.x -= Velocity.x*(1-Decceleration) * SDT();
Move(Velocity.x, 0);
Debug.Log(1 / Time.deltaTime + ", " + SDT());
Application.targetFrameRate = TargetFPS;
}
void Move(float x, float y) //Converts Scratch Units to Unity Units
{
transform.position += new Vector3(x, y, 0) * 1.2f * Time.deltaTime;
}
float SDT() //Basically allows Scratch variables designed for 30fps work in unity
{
return 30 * Time.deltaTime;
}
}
我发现改变
Velocity.x *= Decceleration * SDT();
到
Velocity.x -= Velocity.x*(1-Decceleration) * SDT();
有帮助,但不能解决问题。
作为参考,这是我正在移植的游戏。
https://scratch.mit.edu/projects/590825095
帮自己一个忙,每次写物理方程时验证一下你的单位。在这种情况下,验证您的单位将解决问题。
速度的单位为距离/时间,重力的单位为距离/(时间^2)。
因此,让我们检查一下这一行的单位:
Velocity.y -= Gravity;
你是说距离/时间-=距离/(时间^2)。
那些单位不起作用!
显然,您必须将
Gravity
乘以一定的时间才能获得速度的变化。为此,我们有 Δt,即自上一帧以来经过的时间量:
Velocity.y -= Gravity * Time.deltaTime;
现在的单位是距离/时间 -= 距离/(时间^2)*时间。这更有意义。 对所有物理方程执行此操作,您的问题就会得到解决。
晚了几年,但以防万一有人偶然发现这一点。您应该使用FixedUpdate() 进行移动。我相信在某些情况下,固定更新每帧运行多次,并且出于这个确切原因而设计为以固定间隔运行。