0
\$\begingroup\$

I'm trying to recreate the ball maze puzzle game from Breath of the Wild with Unity. This is what I currently managed to make:

this

As you can see, it's not nearly as smooth and I feel like I lack the understanding to manipulate things the way I want.

At first, I used Transform.Translate() to move it around but it wasn't working well. I googled and read that Translate() is like a "teleport" and you should be using Rigidbody physics. This is cool, but I want to understand why it's like a teleport and how do functions like AddTorque work? What is it adding exactly, how is adding it, when to use what and why etc...

\$\endgroup\$
5
  • 3
    \$\begingroup\$ Stack Exchange wants to be a knowledge base, not a crowd-sourced search engine. Which is why we prefer questions which ask questions directly and not ask us to procure an offsite resource. Can you rephrase your post to ask one, specific question about the Unity physics system? If one question is not enough to find out everything you need to know, feel free to post more than one question. Please do not just post a "please tell me everything about [subject]" question, because that's help vampirism. \$\endgroup\$
    – Philipp
    Commented Mar 14, 2022 at 14:24
  • 1
    \$\begingroup\$ @Philipp FWIW, I think this could be viewed as a low-ball question and could be helpful for folks here to help answers questions that go along the lines "My object jitters and behaves weirdly, here's my code [code that includes modifying the .translate and using body.addForce]". \$\endgroup\$
    – Vaillancourt
    Commented Mar 14, 2022 at 14:43
  • \$\begingroup\$ @Philipp I understand but that's not really what I'm asking. I'm asking where do I learn about this stuff myself. Most of the stuff online is about how to implement and use tools not about how they work and when to use them. \$\endgroup\$ Commented Mar 14, 2022 at 15:30
  • 3
    \$\begingroup\$ The only answer we should give to the question "where do I learn this stuff" is "here, on this website, by asking the right questions". \$\endgroup\$
    – Philipp
    Commented Mar 14, 2022 at 15:32
  • 1
    \$\begingroup\$ You may be interested in Improving Rigidbody collision between real-time movable object and other Rigidbodies, which also asks about creating a ball-maze type mechanic. Or Car driving through walls with Transform.Translate, where I wrote an answer explaining in more detail why the physics engine has more difficulty resolving transform changes cleanly. \$\endgroup\$
    – DMGregory
    Commented Mar 14, 2022 at 17:01

2 Answers 2

2
\$\begingroup\$
  • RigidBody is just Newtonian physics. It means that you add a force to an object and it moves according to physics (you can say that the object is being moved by forces rather than it is moving on its own).

  • Transform translate/rotate/position is changing the object transform instantaneously, so velocity is not regarded in any way (if you don't implement it explicitly).

  • Movement can be done also with Character Controller component. It does not use physics in a way RigidBody does, but still makes use of velocity and collision (which transform modifying does not).

Important thing to know is you should use ONLY one of the options. You can use RigidBody on an object and spawn it once using transform.position, but if you intend on moving it around continuously with transform or character controller, the RigidBody component will mess up the movement badly not expecting you to move the object this way.

In a nutshell, generally speaking:

  • RigidBody is for sliding cubes, rolling balls, throwing objects in an arch, character movement like in fall guys (can simulate feeling like your character has slow reflexes or is drunk)
  • Character controller is for precise movement of the main character for platformers, racing games etc.
  • Transform modifications are for spawns, lock-on rotations towards an target, or can simulate some on-purpose jittery movement.

For the cube in your game, I would suggest using RigidBody.

\$\endgroup\$
0
2
\$\begingroup\$

Transform.Translate() seems to behave like teleportation because it simply moves a Transform without any knowledge of underlying physics. It could be enough for moving a simple object, but it is likely to interfere with a more complex simulation. The "not as nearly smooth" feeling you are experiencing is due to inconsistencies between the object's rendering and physics states.

How is physics done?

Game engines simulate rigid-body physics via numerical integration. The starting idea is to consider an initial position and velocity \$(x_0, v_0)\$, then take a small step forward and compute the position and velocity \$(x_t, v_t)\$ at a future time. Finally, repeat this process using the result from previous calculations as the new initial data. Although we consider time continuous, computer numbers are finite, and integration must use discrete time steps.

Many physics engines take several properties into account: mass, friction, density, etc. All these are plugged into the equations and contribute to a better simulation. Eventually, they can be wrapped together (in a data structure) and considered a physics state. The engine will use a given physics state \$S_t\$ to compute the next physics state \$S_{t+1}\$:

// Example physics state
struct State {
    Vector3 position;
    Vector3 velocity;
    // ...
}

// Example integrator
State Integrate(State fromState, float dt) {
    State toState = State();
    toState.velocity = fromState.velocity + ( forces / mass ) * dt;
    toState.position = fromState.position + toState.velocity * dt;
    // ...
    return toState;
}

When is physics updated?

The above function is a naive example of what modern engines implement in their physics update routines. You achieve movement by applying forces and torque to rigid bodies, and the engine updates the physics.

However, we don't usually think in terms of Newtonian forces. A more natural way to think about movement is by considering velocity. Therefore, we may use Rigidbody.AddForce() with the ForceMode.VelocityChange parameter and obtain a character-like controller. Or, we could get rid of the RigidBody component and write our custom movement code.

Whatever choice, the order of execution is paramount here. A game loop updates physics, reads user input, renders graphics, and more. Code execution during these phases must be as much consistent as possible. Engines enforce this consistency by exposing game loop events. These events are each intended for specific use cases.

When do inconsistencies rise?

In Unity's event execution order, you can see that the internal physics update has a specific order in the flowchart: it comes after FixedUpdate() and before Update(). FixedUpdate() is intended for applying forces to rigid bodies; forces will transform into motion subsequently. Alternatively, you can code your custom physics inside FixedUpdate() to make it go along with the engine's time step. Either way, the Rigidbody component will update the Transform position before rendering.

If you translate a rigid body during Update(), you overwrite the latest integrated position with a new one. At least, this is only true for its Transform component. As said above, a rigid body keeps track of its internal physics state, and so does in Unity. Transform.Translate() changes the object's Transform position without affecting other components, such as a Rigidbody component.

There we have an inconsistency between Transform and Rigidbody states. Physics updates Rigidbody; Rigidbody updates Transform; we update Transform. Finally, the GameObject renders at Transform position. Then, the loop continues, but we aren't updating Transform anymore. However, we witness strange behaviour. The object abruptly changes position or starts moving at high speed with no apparent reason. This happens because physics resume from Rigidbody.position to simulate the next state, completely ignoring Transform.position.


It's okay to control a kinematic character via custom code and switch to ragdoll physics when they die. We can also combine kinematic and physics objects in the same environment (e.g. player moving around crates). When it comes to physics, we must choose only one update method per object. Or at least only one approach at any given time.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .