5
\$\begingroup\$

I have seen various descriptions of how to handle movement in a component-based entity framework. The most common I've stumbled across is the idea of using components called Controller, Physics, Transform, Velocity, and Collider.

The idea here is that the Controller influences the Velocity component when movement keystrokes are detected. The Velocity component in turn influences Physics. Once the simulation has been stepped, the Collider is either affected if a collision occured or is not if no collision happened. In the end, the Transform is updated with the new position from the physics simulation step and thusly the Renderable needs to be adjusted so it is drawn in the proper location.

I have often read that one needs to consider both physics-driven and non-physics-driven entities. As outlined in the above paragraph, manipulating physics-driven entities seems like a piece of cake. The difference with non-physics-driven entities is that the Velocity component values need to simply be applied to the the Transform based on delta-time. This would allow moving the entity without being concerned with physics nor collision detection.

For physics-driven entities, one simply iterates entities with both Velocity and Physics components. But for non-physics-driven entities, simply iterating over entities with a Velocity component isn't sufficient as it would include the above subset as well.

So there must be some factor that clearly separates these two cases. So with these two cases in mind, how would movement actions that influence the values of Velocity be carried out in such a system to manipulate both types of entities whether physics plays a roll in their movement or not??

And lastly, considering that there may be times where the transform for an entity needs to be manipulated directly, such as player clicking on a portal to be teleported to another x/y/z position, how would one properly propagate this change to adjust both the physics step simultation and the renderable's draw location?

EDIT: @bobenko Your explanations provide insight to the most common case where objects are simulated via physics but I'm somewhat lost on the Kinematic aspect regarding updating an entities position via a velocity value? Are you simply implying that some code of my own will apply movement to the entity via velocity, thus being Kinematic? I still am interested in your explanation on how to avoid cyclic notifications effectively when aspects of these components involved change.

For all who answered, I'm still not clear how would you handle teleporting an entity from one position to another? Would this involve turning off physics, teleporting the player, then turning physics on after teleport finished? Turning physics on/off can be as simply as setting the entity as Kinematic YES/NO, right?

\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

With your Physics you subscribe to changes of your Transform component. So when transform position changed directly you Physical part also moves. And after physics simulation you can directly change Transform->position from Physics, because entities which have Physics will always have Transform.

What about direct moving of objects without physical simulation, you can use Kinematic bodies most of engines provides their support. Or you can directly write your position+=velocity in any your script. Or create some BasicPhysics component and then just adjust properties.

\$\endgroup\$
2
  • \$\begingroup\$ How are you preventing cyclic updates from happening, particularly where Transform's change updates the physical representation which yields an update which gets replicated back to Transform from Physics. This would appear to restart the process over again if one isn't careful. \$\endgroup\$
    – gamer13
    Commented Jan 17, 2013 at 13:39
  • \$\begingroup\$ they are not connected cyclic, Physics updates constantly Transform, but Transform notifies Physics only when it's needed(in script - programmers code), simply you can use Transform setter that doesn't notify subscribers. \$\endgroup\$
    – Yevhen
    Commented Jan 17, 2013 at 14:58
1
\$\begingroup\$

The basic setup for interaction with physical simulation has already been covered by user bobenko. I've implemented it more or less like this myself and it works fine.

However, a problem that occurs when multiple Components each add their own movement to the same object during the frame is that velocity is no longer a value you can simply store somewhere and set from the outside, as suggested by your Velocity Component. My solution was, in short:

  • The Transform Component stores a velocity value, but doesn't apply it. This is just a "for your information" stat.
  • If some Component wants to move the object (not teleport it), it wouldn't just set the position (obj.Pos += vel) but call one of several specific Move methods exposed by Transform. They remember the applied velocity in a local variable and accumulate it throughout the frame.
  • Actually, the Transform Component stores two velocity values: One that is accumulated and one that is exposed for read access - the actual velocity value that has been determined last frame. When the Transform Component updates, the accumulator is written to the readout value and then set to zero.

That way, Transform isn't only a central place to store the current position and rotation values, but also a place where all the modifications done to them in one frame are gathered for public usage. I read those values out for velocity-specific effects such as the doppler effect for the sound system.

\$\endgroup\$
2
  • \$\begingroup\$ In your design, I'm guessing that the way you prevent the cyclic notification of component changes is by applying some force or movement vector/velocity to an entity. This is handled by the physics step and reset to zero each frame. All the physics step does is post collision check & motion change, updates the transforms raw position. The renderables in this case can listen for transform raw position changes and update accordingly. That all makes sense until you consider teleports. Then how would one differ between a physics update to transform and an outside user teleporting? \$\endgroup\$
    – gamer13
    Commented Jan 17, 2013 at 13:46
  • \$\begingroup\$ @gamer13 As I said, teleporting happens by just setting the Transforms position property to some value, which will not update the accumulated velocity value as described above. Any non-teleport movement such as the physics update or other (probably user-defined) movement happens by calling transform.MoveTo / transform.MoveBy methods which will add up to the measured total velocity value. I don't really get that cyclic notification problem you're talking about, though. Probably because I use a software design that differs in some details. It shouldn't be too hard to avoid that kind of stuff. \$\endgroup\$
    – Adam
    Commented Jan 17, 2013 at 16:07

You must log in to answer this question.

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