【问题标题】:Unity Ball Shaking as it movesUnity 球在移动时摇晃
【发布时间】:2016-05-24 00:56:40
【问题描述】:

我有一个球类游戏对象,我正在使用明确的物理方程进行弹跳。我尝试使用统一的物理引擎,但不够准确。我这样设置球的位置:

float dTime = Time.time - timeSinceBounce;
 ballPosition.x -= meterOffset / sensitivity;
 ballPosition.y = ballInitialPosition.y + GameConstants.Instance.GetBallYVel ()
 * dTime - (float)0.5 * GameConstants.Instance.GetGravity () * dTime * dTime; //Yi+Vy*t-0.5(G)(time^2)
 ballPosition.z = (-dTime * GameConstants.Instance.GetBallZVel ()
 + ballInitialPosition.z) * startConstant; //Zi + t*Vz
 ball.transform.position = ballPosition;

此代码在 Update() 方法中运行。当检测到碰撞时,重置时间和初始位置,这有效。目前,球可以正常反弹,但在快速移动时会摇晃。 FPS 为 80。我不认为我的方程式是错误的,因为它反弹得当,只是晃动。去除奶昔的最佳方法是什么?谢谢!

编辑 1:我决定编写自己的物理引擎,因为 Unity 的物理引擎有很多其他组件,例如摩擦和滚动,这些组件会使球的反弹发生变化。相机的 x 和 y 也是固定的,唯一改变的是相机的 z 位置。 在固定更新中效果更好

【问题讨论】:

  • 你可以写0.5f,你不应该(float)0.5。至于您的问题:您的意思是 Unity Physics 不够“准确”?你做了什么?另外,如果你做物理,你应该使用 FixedUpdate() 而不是 Update()。另一个注意事项:你有 Time.deltaTime 和 Time.fixedDeltaTime,你不必自己计算。 “摇晃”一般是由于强制某种动画而发生的,这与您所做的运动背道而驰。例如。您一直强制球面向“x”方向,但您在更新时旋转它以使其看起来像移动(或类似)
  • 我认为 meterOffsetsensitivity 在 FixedUpdate 中进行了更新,因此它们在几帧中保持相同的值(默认情况下,物理每秒更新 50 次,而您有 80 fps)
  • 我不确定你能比内置物理做得更好。 “不够准确”是什么意思?如果我查看您的代码,它似乎很基本,我不明白为什么内置引擎会出错。
  • 请参阅编辑。 @Mark FixedUpdate 似乎也让它变得更好,如果你愿意,请随时回答这个问题。

标签: c# unity3d game-physics


【解决方案1】:

根据提问者的要求,我特此添加所有我能做到的细节,即使没有看到实际、完整和完整的代码以及看到这种“摇晃”效果,很难给出准确和正确的答案。不过,我会尽力而为。

所以让我们这样做吧。
1. “摇晃”的原因:很可能您设置了某种动画,以及强制定位/旋转等,这两个代码相互影响。仔细检查您的 AnimatorControllerAnimator 以及您的 Mecanim 是否已设置/配置这些(也可以阅读:“运动”)。
您还可以在您打开 Animator Window 时保持打开状态正在从 Unity UI 进行测试,看看谁是为你做“摇晃”效果的棘手人,并更接近它发生的原因。
如果这些没有帮助,请从头开始:最小化你的代码写移动球,删除所有效果等,然后将它们一一添加。迟早会出现“不稳定”(如果它坚持使用尽可能干净的代码,请参见上文,Animator/Locomotion 问题)

2. 再想一想,不要重写 Unity Physics...您提到例如
"...物理引擎有很多其他组件,例如摩擦和滚动球的弹跳会有所不同...”。
现在,您可以关闭此功能。如果你愿意,完全可以。最简单的方法是在Physics Material 上将所有内容设置为零(即摩擦力和弹性),但是如果您希望 Unity 忽略所有和所有“实际物理”并让您对游戏对象做您想做的事情,请在 isKinematic 属性中打勾的Rigidbody。其中有趣的部分是,您仍然会在您想要的地方发生碰撞,AddForce 等,但重力、摩擦或“任何物理”都不会影响您。
如果您对 Unity 不满意(而且您是似乎不是),我强烈建议先了解一下它,因为它是一个非常好的和非常强大的引擎 - 所以不要放弃它的功能,因为它们不能像你最初预期的那样工作。例如,Sebastian Lague 几周前刚刚开始了一个很棒的初学者系列。这家伙是位老师,他的视频既短小又有趣,而且信息量很大,所以我只能推荐他的频道。

3. 对于您的代码,我将进行以下更改:

public static class GameConstants { //no monobehaviour == can be a "proper, global" singleton!
   public static float GetGravity {
      get { return [whatever you want]; }
      //why not Physics.gravity, using locally when and where it's needed?
   }
   //etc, add your methods, properties and such
   //use this approach if and only IF you access these values application wide!
   //otherwise, instead of a """singleton""" logic you just implemented,
   //consider adding an empty GameObject to the Scene, name it "GM" and
   //attach a "GameManager" script to it, having all the methods and
   //properties you'll need Scene-wide! You can also consider
   //using PlayerPrefs (see help link below) instead of a global static
   //class, so you save memory (but will need to "reach out" for the data)
}
private void FixedUpdate() { //FIXED update as you'll work with physics! //float dTime = Time.time - timeSinceBounce; //not needed //positioning like this is not recommended, use AddForce or set direction and velocity instead ballPosition.x -= meterOffset / sensitivity; ballPosition.y = ballInitialPosition.y + GameConstants.Instance.GetBallYVel () * Time.fixedDeltaTime - 0.5f * GameConstants.Instance.GetGravity () * Time.fixedDeltaTime * Time.fixedDeltaTime; //Yi+Vy*t-0.5(G)(time^2) ballPosition.z = (-dTime * GameConstants.Instance.GetBallZVel () + ballInitialPosition.z) * startConstant; //Zi + t*Vz ball.transform.position = ballPosition; }
但是说实话,

我只想扔掉那些代码,实现 Bouncing Ball Unity 教程提供的示例,修改它(参见第 2 点),然后从那里开始。

未链接但我在代码中提到的项目: PlayerPrefsPhysics.gravityRigidbody.velocity
注意“速度”忽略了物理学的某些部分(加速、被“拖动”等),即物体突然开始随着您设置的速度(这就是为什么 Unity5 建议使用 AddForce 而不是 -linked above-)

您也可以通过Time Management 更改FixedUpdate() 频率,但我不确定这是否需要(即仅用于弹跳球)

我希望这会有所帮助,并且那个球会弹跳、跳跃、跳舞以及你想要它做的一切;)
干杯!

【讨论】:

  • 感谢您的回答!我很想使用 Unity 的物理引擎,但是当我尝试使用它并遵循弹跳球教程时,即使在 1 和 0 摩擦的弹力下,球也不总是弹回相同的高度。有没有办法使用 uniti'es 物理引擎我可以总是让球达到相同的高度?
  • @AlexPelletier 您还应该将拖动和反弹的效果“归零”,以使 Unity 可以说“停止模拟逼真的行为”,并“像机器一样”,即系统化。如果仍然不满意,您还可以在碰撞时设置触发器以在球撞到地面时重置速度(或 AddForce)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-19
  • 1970-01-01
  • 1970-01-01
  • 2022-12-18
  • 1970-01-01
  • 1970-01-01
  • 2012-09-24
相关资源
最近更新 更多