Based Movement

Based Movement is a catch-all term for any type of locomotion that happens on (or at least relative to) a moving object (referred to as the base). In its most rudimentary form, the base may simply be a platform that constantly moves back and forth between two points at a fixed rate. A more advanced case of based movement could be a big ship sailing on an ocean that is transporting multiple players while also being steered by one particular player. More generally, we talk about based movement whenever the pawn not only has to consider its own movement, but that of another object as well. Refer to the demo project for practical applications of some of the concepts explained in this chapter.

Types Of Based Movement

While based movement is usually straightforward to implement for a single-player game, it can become an extremely difficult problem to solve in a networked environment. The discrepancies in the local simulation introduced by client-side prediction and network delay make it virtually impossible to create a generic solution that “just works” for any potential base. The best we can do is utilize different approaches that each have their individual benefits and drawbacks, and use the most appropriate one for a given situation. Even client-authoritative replication cannot fully solve the networking problems we face with based movement. Therefore, it is important to understand that if based movement is relevant for your game, you may have to make compromises regarding game design if you want to ensure a good client experience.

The Organic Movement Component offers different types of based movement, which can be configured via the Source parameter in the Movement|Operation|BasedMovement category. A listing with more details on the available options follows.

  • None: This mode will disable based movement, meaning the pawn will never follow any object. You obviously only want to set this mode if you don’t need based movement for your game. When there are no movable primitives in your world to begin with, the option you choose doesn’t really matter functionally and you will likely get the same behaviour across all modes. However, you should still prefer using None as source whenever applicable, it yields the best performance since all code related to based movement will be skipped entirely.

  • Velocity: This mode will follow dynamic objects based on their velocity. The velocity of the base is usually set manually by the user, but an automatically calculated value can also be retrieved from the physics engine in some cases. The quality of the based movement with this source directly depends on how accurately the velocity reflects the actual location delta applied each frame. From the perspective of writing gameplay logic, this mode is the most flexible and the easiest to work with since the whole pawn state is still predicted in world space. However, in a multiplayer scenario it is often not trivial to ensure synchronization of the base transform and velocity in a way that won’t cause client corrections – not without implementing special networking logic for the base itself that is. The GMC can help you with that as well: you can create the base as a GMC_Pawn and give it a replication component to enable full rollback support. This works, but may make the class more expensive than it needs to be, especially in terms of bandwidth usage. In certain cases it may be better to use the more lightweight GMC_RollbackActor class instead. Out of the box, GMC_RollbackPlatform is available as a specialization of this class, which¬†implements a simple platform that can be configured to move back and forth at a constant linear velocity and/or rotate at a constant angular velocity. The main advantage of using Velocity as source in connection with rollback actors is that it introduces no additional replication cost for the base whatsoever. However, the one big limitation of rollback actors is that they can only be used for deterministically moving objects. The transform of a rollback actor has to be set from the current world time, so the path of the base has to be known beforehand for the entire duration that the world exists. This excludes use cases where you want the transform of the base to be affected by gameplay events (e.g. allow the movement of the base object to be controlled by a player).

  • Relative: This mode will synchronize the state of the pawn relative to the current base. This means that the specifics of how the base is moved or even its local state don’t really matter anymore, it will work as long as the state of the pawn relative to the base object is in sync. The catch here is that a change of the actor base cannot be predicted with this method, the server alone determines the base and will correct the client onto a new base when a transition occurs, which may result in very noticeable rubber banding for the client if not handled appropriately. In a stand-alone game the local player counts as the server, so there’s no issue in that case, but for multiplayer games it is very important to ensure base objects behave in a way that makes the transition as smooth as possible for the client. In general, this means that you should only use this mode for bases that players do not get on/off very frequently and that are moving slowly (or ideally standing still) while players transition to them. You can further improve the smoothness of base transitions by ensuring that the base objects are synchronized as closely as possible across client and server. The advantage of this mode is that once the client made it onto the base, there are very little restrictions on what you can do, and there’s usually no additional setup required to make the base object work in a multiplayer game. Be aware that objects of type GMC_RollbackActor are incompatible with this based movement source.

For standalone games the default Relative based movement source is likely to cover all use cases and you don’t need to worry about it much. For multiplayer games on the other hand, I hope it has become clear that you have to put some effort into consolidating networked based movement with your game design. Here are a few practical guidelines for that:

  • Use Velocity as source in connection with rollback actors for deterministically moving bases. A common use case are platforming sections where skilful manoeuvring is expected of the player.
  • Use Velocity as source and make the base a GMC_Pawn with a replication component if it is not deterministic, but should support rollback and is simple enough to be manipulated through velocity values. A common use case would be platforms that are affected by gameplay events, e.g. an elevator that the player can control.
  • Use Relative as source for bases that are too complex to support rollback, and that can’t have their motion accurately described through velocity alone. A common use case would be a large base object (e.g. a space ship) that multiple players spend extended periods of time on, or a base that is simulating physics.

Switching Source Modes

It is important to remember that the different sources for based movement are a property of the pawn, not the base. It is not possible to use Velocity for one object and Relative for another, because the source already determines code to run before a new base is even acquired. The recommended way to handle changes of the based movement mode during runtime is to have designated areas in your game associated with a particular mode. For example, you can add an overlap volume around an object and apply the source change when the pawn enters the volume (i.e. when the pawn is near the potential base). The change itself does not need to be predicted and can be handled through RPCs; provided the overlap volume is large enough the new mode will already be applied when the pawn gets close enough to the base to mount it.

Base Equalization

When using Relative as the based movement mode, a unique problem occurs for server-authoritative movement when the base has roll and/or pitch rotation. Remember, with the Relative source the base is not rolled back, so its transform will most likely differ between server and client during move execution, synchronization is achieved by comparing the pawn state relative to the base. To illustrate the issue, imagine the base is tilted upward on the server but downward on the client from the pawn’s forward perspective (depending on how the base is moved and the amount of network latency involved this scenario is entirely possible and not hypothetical at all). Although the relative starting point may be in sync, once the pawn starts moving forward we may get deviations because on the server the code for “running up a slope” is executed (server base is tilted upward), while on the client the code for “running down a slope” is executed (client base is tilted downward). To reiterate, this issue only occurs with roll and pitch rotations of the base, rotations around the yaw axis generally do not affect the movement of the pawn.

To combat this undesirable effect, you can enable the Equalize Base Actor option. This will unrotate the base for move execution, which resolves any differences in code execution that would have been caused by rotations. While this is a good idea in theory, it can have unintended consequences. For example, if the base is rotating due to it moving across sloped terrain, it will possibly intersect the ground when unrotated, which may affect the movement of the pawn in unexpected ways. To mitigate this, it is possible to set an Equalization Location (and uncheck Equalize in Place). This will not only unrotate the base, but also move it to the equalization location. The equalization location should be a point of empty space in your level, which solves the problem of the base potentially intersecting other objects during base equalization. However, you have to realize that (in addition to the performance overhead) using these options may make your life much harder when it comes to writing gameplay logic. You have to constantly keep in mind the fact that the pawn is not actually where you think it is, and this may have far reaching consequences for your code, e.g. when trying to refer to objects that are not part of the base. It is also possible for the pawn to fall through the floor when leaving the base with this technique in some cases. Generally, using base equalization can introduce more problems than it solves, so you should consider it only as a last resort when nothing else works. If you can restrict the base object to yaw rotations only you should absolutely do so, in that case you don’t need base equalization. The method is also more suited for objects that naturally belong in more unobstructed areas distant from terrain, e.g. a ship on water or in space.