Physics and Movement

Overview

After loading geometry into a Slot, we can create a physical entity (represented by the IPhysicalEntity interface) and add the physical geometry from the slots. This results in a physical representation of the entity that can interact with the world.

To physicalize an entity, we can call IEntity::Physicalize (example contained within). This will create a physical entity for the entity of the specified type, and optionally create physical parts for individual or all entity slots. Note that physicalization of slots assumes the existence of a physics proxy, set up by the author in the DCC tool.

To query the physical entity of an entity, use IEntity::GetPhysicalEntity.

Once an entity is physicalized, we can optionally add physical parts for individual entity slots by calling IEntity::PhysicalizeSlot.

Physical Types

CRYENGINE provides many different IPhysicalEntity implementations, represented by the pe_type enum:

Enum EntryDescription
PE_NONERepresents an entity with no physics type – physicalizing with this type will remove the existing physical entity attached to the entity.
PE_STATICStatic object that other geometry can collide with, and will respond to queries – but cannot move on its own.
PE_RIGIDDynamic object in the world that has a mass and can move around freely.
PE_WHEELEDVEHICLESpecialization based on the rigid entity that allows for wheeled vehicle movements. Requires setting pe_params_car at physicalization time.
PE_LIVINGCompletely specialized class meant for walking FPS style actors – operates by casting a ray downwards every time step.
PE_PARTICLEUsed for simulating basic particles, such as gun tracers.
PE_ARTICULATEDSpecialized implementation for ragdoll simulation.
PE_ROPEImplementation that supports physicalized ropes with complex tension simulation.
PE_SOFTReal-time cloth simulation type – please note that this type can easily become very costly on the CPU.
PE_AREASpecialized setup that allows tracking entities inside a physical shape to create gravity and wind modifiers.

IPhysicalEntity functionality

Once an entity has been physicalized, we can use the IPhysicalEntity interface directly to manipulate its physical behavior. The interface exposes, among others, four functions that are crucial to interacting with the physics at run-time:

IPhysicalEntity::SetParams

Used to set parameters implementing the pe_params structure, will be queued and executed next time step unless executed on the physics thread with bThreadSafe set to true.

IPhysicalEntity::GetParams

Used to get parameters implementing the pe_params structure. This will always execute immediately using locks, potentially interrupting the main and physics threads until done.

IPhysicalEntity::GetStatus

Used to get status of the entity, implementing the pe_status structure. As with IPhysicalEntity::GetParams, this will always execute immediately using locks.

IPhysicalEntity::Action

Executes an action, implementing the pe_action structure. As with IPhysicalEntity::SetParams this is queued by default.

The physics simulation is run on a different thread, this means that any attempt at setting data will be delayed until the next thread sync unless 'bThreadSafe' is set to true. This can be used if handling immediate events (such as ENTITY_EVENT_COLLISION_IMMEDIATE) that come directly from the physics thread, to avoid the request being queued.

Get functionality will always execute immediately without queuing.

Listening to Collision Events

Components can listen to collision events logged by physics by processing Cry::Entity::EEvent::PhysicsCollision (ENTITY_EVENT_COLLISION). This event is fired the next frame after the collision was processed on the physics thread, and provides data through the EventPhysCollision structure - detailing the collision that occurred.

Raycasts

It is often useful to trace a ray through the physical world, for example to let the user mouse-over or click on in-world objects. This is possible through the IPhysicalWorld::RayWorldIntersection function.

Impulses

Impulses can be triggered on individual physical entities using the pe_action_impulse structure.

Explosions

By using the IPhysicalWorld::SimulateExplosion function we can enhance gameplay logic by supporting grenades and more things – effectively adding impulses to nearby entities based on a force and an origin point:

After done, any dynamic entities in the vicinity of the explosion point and radius will be impacted by the impulse.

Walking Characters

As mentioned in the parent page, the PE_LIVING physical entity type is specialized for walking type actors, specifically developed for games such as Far Cry and Crysis. Physicalizing a living entity is more intricate than static and rigid entities, as it requires setup with the pe_player_dimensions and pe_player_dynamics structures.

Once done, the entity will be physicalized and start casting a ray down every step to check if the player is on ground or not.

Sending Movement Requests

The living entity will only move when a movement request is sent to it via the pe_action_move structure. For example, to make the player move forward:

pe_action_move moveAction;
// Apply movement request directly to velocity
moveAction.iJump = 2;
moveAction.dir = Vec3(0, 1, 0);
physicalEntity.Action(&moveAction);

After that, the player will move forward – as if velocity was always 1m/s in the forward axis. This can for example be used to make the player jump and strafe.

Getting the Entity Status

We can query the living entity's status using the pe_status_living structure, in addition to pe_status_dynamics. For example:

pe_status_living livingStatus;
if (pPhysicalEntity->GetStatus(&livingStatus) != 0)
{
  const bool isOnGround = !livingStatus.bFlying;
  // Store the ground normal in case it is needed
  // Note that users have to check if we're on ground before using, is considered invalid in air.
  const Vec3& groundNormal = livingStatus.groundSlope;
}

// Get the player's velocity from physics
pe_status_dynamics playerDynamics;
if (pPhysicalEntity->GetStatus(&playerDynamics) != 0)
{
  const Vec3& velocity = playerDynamics.v;
}

Note that walking character handling is automated by the Character Controller Component in the default components plug-in, see Cry::DefaultComponents::CCharacterControllerComponent.

Conclusion

This concludes the article on Physics and Movement, you may be interested in: