gpt4 book ai didi

unity3d - 与帧率无关的 FixedUpdate 与 Update

转载 作者:行者123 更新时间:2023-12-04 19:51:33 28 4
gpt4 key购买 nike

我已经阅读了this和官方文档:fixedUpdate() ,以及 deep explanation .

所以我试图分离我的代码。首先,在 Update() ,我没有给出完整的代码,变量是不言自明的:

private void Update()
{
if (Input.GetButton("Jump")) {
if (groundsTouched>0) {
_jumpRequest = true;
} else {
_keepOnJumping = true;
}
} else {
_keepOnJumping = false;
}
/* Handle release button: */
_fallRequest = true;
}

现在我正在做 FixedUpdate() 中的所有计算。像这样:
private void FixedUpdate()
{
if (_jumpRequest) {
if (!_jumpGravitySent) {
_jumpGravitySent = true;
_animator.SetBool("Jump", true);
_jumpRequest = false;
jumpTimeCounter = jumpTime;
/* Cancel all force (couldn't find a better way) */
_rigidbody.velocity = Vector3.zero;
_rigidbody.angularVelocity = Vector3.zero;
_rigidbody.AddForce(
Vector3.up * jumpVelocity, ForceMode.VelocityChange
);
}
} else if (_keepOnJumping) {
jumpTimeCounter -= Time.fixedDeltaTime;
if (jumpTimeCounter >= 0) {
_rigidbody.AddForce(
Vector3.up * jumpVelocity * jumpKeepMultiplier,
ForceMode.Acceleration
);
}
}
if (groundsTouched == 0 &&
_rigidbody.velocity.y > velocityFallMin &&
_rigidbody.velocity.y < velocityFallMax
) {
_animator.SetBool("Jump", false);
_animator.SetBool("Fall", true);
}
if (_fallRequest) {
_fallRequest = false;
_jumpGravitySent = false;
_keepOnJumping = false;
}
}

我遇到的问题真的很奇怪:当 FPS 低时,玩家跳不高。

Unity QA 看到了我的问题,他们的回答是:

You are adding Force dependent on fixedDeltaTime which is dependent on your available performance (or frame rate essentially).

If you go to Edit->Project Settings->Time and change fixed Timestep to a larger value, you will get the expected behavior. Try a few different values of Fixed Timestep and see how the behavior changes.

Another suggestion would be to rewrite the code so it's not dependent on frame rate (eg. use Velocity and not force or add a specific amount of force on jump, not dependent on Timestep).



“另一个建议是重写代码,使其不依赖于帧速率” ->你会怎么做,我认为我上面的代码正在这样做!

我错过了什么?我做错了什么/可能是什么解决方案?

最佳答案

我想知道给你这个答案的那个 Unity QA 是谁,这太令人畏惧了。

让我解释一下现实中会发生什么。

1) 让我们从 fixedDeltaTime 开始: 此值从不依赖于帧速率 .它可以在编辑器中设置(在 Edit->Project Settings->Time 中),这是在运行时保留的值,除非任何脚本通过赋值更改它。 Unity 引擎永远不会自行更改它。

2) 物理循环:在完整的引擎循环中,Unity 将执行多个物理循环(0,1 或更多),然后执行单个渲染循环。每个渲染循环执行的物理循环数基于 fixedDeltaTime以及距离上一次已经过去了多少时间(即:渲染循环的 deltaTime)。

例如,假设 fixedDeltaTime = 0.0166667并且自上次物理循环以来耗时小于那个,例如10小姐。 Unity 不会执行物理循环。现在假设在10 中甚至已经渲染了下一帧。 ms - 这意味着自上次物理循环以来,20 ms过去了。由于这高于 fixedDeltaTime , Unity 将执行一个物理循环。
有时可能会出现帧渲染非常缓慢(由于不可预见的原因),例如在 40 中。小姐。为了保持物理模拟的一致性,Unity 必须连续运行两个物理循环,这是因为 0.04/0.0166667 = 2.4 .

请记住,Unity 会跟踪上一个物理循环开始时间与下一个物理循环开始时间之间的差异:如果渲染持续 10每帧毫秒,fixedDeltaTime设置为 166667 ms (60Hz),一旦你开始运行时,Unity 将执行第一个物理循环,然后在第一个渲染帧之后跳过一个(因为只有 10 毫秒而不是 166667 ),然后执行一个物理循环在第二个渲染帧之后( 20 毫秒通过 166667 )。但是现在我们的循环被 3.3333 去同步了。 ms,所以 Unity 会对此进行跟踪。

第 3 帧之后,另一个 10 ms 已过,但自 10+3.3333 = 13.3333 起不会执行任何物理循环仍低于 fixedDeltaTime .现在,让我们假设第 4 个渲染帧“出错”,并且持续了 25 ms 而不仅仅是 10 .在下一个物理循环开始时,共有 25+13.3333 = 38.3333 个自上次物理更新以来已过去,38.3333/16.6667 = 2.3 , Unity 将执行 两个 在继续渲染第 5 帧之前,物理循环连续进行以跟上固定步长模拟。

在所有这些介绍之后,让我们回到你的问题,看看会发生什么:

在某个时刻执行 Update() , 并设置 _jumpRequest = true;_fallRequest = true; .

在这个渲染帧之后,FixedUpdate()第一次执行,执行AddForce ForceMode.VelocityChange行,并设置 _fallRequest = false; , _jumpGravitySent = false;_keepOnJumping = false; .结束后FixedUpdate() , Unity 执行物理模拟,借助物理引擎调整刚体的位置和速度。

现在问题触发了:由于渲染帧很慢,物理循环至少连续执行两次,但没有Update()在两者之间执行,所以 FixedUpdate() 中的所有内容被跳过,但物理模拟第二次运行,相对于预期的最高位置向下拖动刚体位置。

Update()再次执行,最后你的代码集 _keepOnJumping = true; , 当它返回 FixedUpdate()它将执行 AddForce ForceMode.Acceleration ,但紧接着,第二次执行另一个物理模拟(由于低帧率),再次向下拖动刚体,然后才能在屏幕上渲染。

希望这有助于理解您的问题及其发生的原因,以便您现在拥有正确的工具来正确修复它。

关于unity3d - 与帧率无关的 FixedUpdate 与 Update,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55066052/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com