Raycastable Crowd System
This page covers the Raycastable Crowd system that can be used to handle collisions on Animated Crowd members (e.g. shooting). We will go through how to set it up and its limitations
Last updated
This page covers the Raycastable Crowd system that can be used to handle collisions on Animated Crowd members (e.g. shooting). We will go through how to set it up and its limitations
Last updated
Any characters outside of the nearest ~30 actors to the local character is not in lod0, which means they are a crowd member. The meshes of crowd members do not exist on the CPU for performance reasons, so by default you can't raytrace to them.
RaycastableCrowdActors are a simple way to add basic collisions to the crowd members that in the centre of the local player's screen.
The user specifies an actor class (the Raycastable Crowd Actor
class) that is used as a non-replicated actor to handle the collisions for a crowd member. Instances of these actors are spawned at the start of the game, and teleported each frame to the transforms of the N most relevant crowd members.
These raycastable actors should be invisible, but can be visible for debugging purposes. When a player attempts to raytrace to a crowd member that's in the centre of their screen, they will get a hit result on the Raycastable Crowd Actor that is in the crowd member's position. The ARaycastableCrowdActor
object has GetMorpheusActor
which allows the user to get the MA that the raycastable actor is currently representing.
Example usage can be found in the CombatGym
map.
Create a BP class that inherits from Raycastable Crowd
. This singleton class handles the spawning of the Raycastable actors and allows you to set some configurations.
Raycastable Crowd Actor Class
: The actor class that will be spawned to use for collision on the most relevant crowd members.
Num Raycastable Crowd Actors
: The number of crowd members that will have collision actors. This is also the pool size of the Raycastable Actors.
Priority Calculation
: Section for configuring the prioritization of the crowd members
Strategies Enabled
: Selector for which prioritization strategies to be used.
There are currently 3 prioritization strategies that can selectively enabled:
View Frustum:
Prioritizes crowd members within the View Frustum specified using the Field of View Degrees
and Near Clip Plane.
The priority returned will be square the distance between the crowd member and the View location.
Uses the FMinimalViewInfo
data returned via UpdateViewInfo
function.
Field of View:
Prioritizes crowd members that are within the specified Field of View Degrees
angle.
The priority returned will be the 1/cosine
of the angle of the crowd member and optionally scale that by distance if ScaleByDistance
is enabled.
Doesn't consider the crowd member size like the View Frustum Strategy.
Uses the FMinimalViewInfo
data returned via UpdateViewInfo
function.
Area of Influence:
Prioritizes crowd members that are within user-defined Areas of Influence.
Use the functionsAddAreaofInfluence
and ClearAreasOfInfluence
to control the behaviour of this strategy during runtime.
Scales the priority by the squared distance from the center of the Area of Influence.
Update View Info Interval
: The interval through which the function Update View Info
will be called.
By default, Update View Info
returns the FMinimalViewInfo
of the player's camera.
This can be overridden in the RaycastableActor
class allowing for more configurability.
In your DA_Pawns
asset you need to reference your RaycastableCrowd asset in your Animated Crowd as the following:
Now, we need to create our Raycastable crowd actor that will get assigned to the crowd members if their priority is high enough.
Create an actor that inherits from ARaycastableCrowdActor
, and add some type of component that can handle collision. For example, a capsule component, or a skeletal mesh. Here, I've used the basic human skeletal mesh.
Make sure you set this actor up for raytracing with the Shootable
channel.
I've left this actor Visible for now, but you can untick Visible in the details panel when you're satisfied that the Raycastable actors are behaving correctly.
Finally, we need to set our RaycastableCrowd
asset to use this actor class by setting the Raycastable Crowd Actor Class
property.
To test this locally, go into PIE in your map, and enter the console command ImprobableLiveConfig.SetOverride game PlayerClient.Rendering.NumInLoD0 0
to force all players to become crowd members. If your Raycastable actor is Visible, you will be able to see the raycastable mesh overlayed on your crowd actors.
It's important to make sure the Raycastable actor mesh is not offset from the crowd transform. You may need to adjust the offset in your raycastable actor mesh to make sure it's property aligned with the crowd actor.
The above flow is suitable for the basic case where all crowd members in the game are always the same shape, so you can use the same unchanged Raycastable actor for everyone. In many cases, you'll want different shapes or sizes for different actors, and for these to change in the game. For example, if different players have differently sized avatars, or if a player has a forcefield that disappears part way through the game.
To implement this, bind to the event UpdateRaycastableActor
in the RaycastableCrowdComponent
that's on the Morpheus character. This event is executed whenever your character is assigned a new raycastable actor.
To change the state of the raycastable actor when it may already be assigned to your actor, call ForceRaycastableCrowdActorUpdate
. You should use this when you want the state of your raycastable actor to change (e.g. if a forcefield around the character disappears). This will cause UpdateRaycastableActor
to be executed on your character, only if your character currently has a raycastable actor.
Here's an example demonstrating the forcefield example. I've created my BP class of RaycastableCrowdActor.
To set up the raycastable state for my actor correctly, I need to use the UpdateRaycastableActor
event to configure the raycastable actor for my player.
Then, in order for the raycastable actor to correctly update when the forcefield on the player should disappear, I call ForceRaycastableCrowdActorUpdate
.
There's also an event OnRaycastableActorAssigned
which is called when the character is assigned a raycastable actor, but not when ForceRaycastableCrowdActorUpdate
is called.
A big limitation is that the raycastable actor does not animate alongside the crowd member. This means, in the skeletal mesh example, that the raycastable actor's legs and arms don't match the crowd member's legs and arms if the actor is in a running animation, for example. This limits the nature of the gameplay you can perform this. Fixing this is planned for the future but is estimated at 3-4 weeks of work.