# Raycastable Crowd

## Overview

In the Morpheus Platform, the only remote player characters that are represented by physical Actors in the world are those characters that are in [*LoD 0*](https://docs.msquared.io/creation/unreal-development/the-animated-crowd#via), which defaults to the 35 closest players. This means that in a high-scale game, most characters are rendered using the [Crowd](https://docs.msquared.io/creation/unreal-development/features-and-tutorials/the-animated-crowd), and don't have physical representations in the world that have colliders.

The Raycastable Crowd is a system to add basic colliders to some of the Crowd members in your world. The Crowd members which have colliders are constantly updated at runtime, according to configurations that you can define, so the Crowd members most relevant for your gameplay mechanics at any given moment can be the characters that have colliders.

## Quickstart <a href="#integration" id="integration"></a>

### Configuring the Raycastable Crowd Actor class

Your Raycastable Crowd Actor is the actor that will act as the collider for the selected Crowd members. Create a subclass of `M2 Avatar Raycastable Crowd Actor` to create your Raycastable Crowd Actor Class.

{% hint style="info" %}
`M2 Avatar Raycastable Crowd Actor` is set up to match the physics asset settings configured in your character's [AvatarPhysicsAssetComponent](https://docs.msquared.io/readme), which is the simplest way to set up your characters and Raycastable Crowd with appropriate skeletons.
{% endhint %}

**Avatar Physics Asset Data:** Set this to the `AvatarPhysicsAssetData` class used in your Morpheus Character's `AvatarPhysicsAssetComponent`. This makes your Raycastable Crowd Actor's skeleton match the approximate skeleton for the Morpheus Character that this Raycastable Crowd Actor is currently representing.

The Raycastable Crowd Actor will use a capsule component instead if the AvatarPhysicsAssetComponent reports that no valid physics asset was found.

**Default Skeletal Mesh:** This skeleton will be used for the Raycastable Crowd Actor if no `AvatarPhysicsAssetComponent` is on the currently represented MorpheusCharacter, or if the character is not using an MML avatar.

**Interactable Query and Object Channel:** These channels are enabled on the collider that the Raycastable Crowd Actor is currently using. Set these to be the channels used for your gameplay interactions (e.g. line traces for shooting).

**Anim Instance Class:** Set this if you want your Raycastable Crowd Actor to animate approximately in line with its current Morpheus Character. This has a performance cost.

**Debug Visibility:** Raycastable Crowd Actors by default are invisible, but set this to true to make them visible for debugging purposes.

### Configuring the Raycastable Crowd Class

Your Raycastable Crowd class configures the raycastable crowd, determining how many Raycastable Crowd Actors to use and which strategy to use to assign Raycastable Crowd Actors to Morpheus Characters at runtime. Create a subclass of `Raycastable Crowd`to create your Raycastable Crowd Class.

<figure><img src="https://1456550285-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoWTlPaoHd1McSakqMigu%2Fuploads%2Fgit-blob-d4e7e7b5f396f1c4a39eb0fe44e291295afe9a77%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

**Raycastable Crowd Actor Class:** Set this to the Raycastable Crowd Actor Class that you created in the previous section.

**Num Raycastable Crowd Actors:** The total number of Raycastable Crowd Actors for this Raycastable Crowd in use at any time. This is the maximum number of Crowd members that can be currently represented by a Raycastable Crowd Actor. If this number is too low, you'll find that players will end up trying to interact with Crowd members that don't have Raycastable Crowd Actors, and so the interaction won't register. 20 is a sensible default.

**Priority Calculation:** This determines on a frame-by-frame basis which Morpheus Characters get assigned a Raycastable Crowd Actor. The Morpheus Characters with the highest priority in any frame get assigned the Raycastable Crowd Actors. The setting in the above screenshot is good starting point - it prioritises Morpheus Actors that are within 10 degrees field of view of the local camera, calculated with a view frustum, so approximately any crowd member that your cursor is over in a shooter game will be assigned a Raycastable Crowd Actor. Full details of the different strategies are described below.

**Update View Info Interval:** How often to update the data used for the priority calculation.

### Enabling the Raycastable Crowd

#### Via the Morpheus Actor

{% hint style="warning" %}
NOTE: This section is available from release v40 onwards.
{% endhint %}

* In the details panel, you can enable the Raycastable Crowd by ticking the box in the `Morpheus Render Target Settings`
* By default, this will use the `DefaultRaycastableCrowdClass` defined in `Project Settings -> Morpheus Platform -> Animated Crowd Settings`
* You can override the default by specifying a class in `Advanced -> RaycastableCrowdClass`

<figure><img src="https://1456550285-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoWTlPaoHd1McSakqMigu%2Fuploads%2Fgit-blob-93970fba617924049e213de4672aba8fa1f10d23%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

* You can update the raycastable crowd class at runtime using `SetRaycastableCrowdClass` or `ResetRaycastableCrowdClass`

#### Via the pawn set

Navigate to the [animated crowd render target section](https://docs.msquared.io/creation/unreal-development/the-animated-crowd#via-the-pawn-set-asset) of your Pawn Set asset.

<figure><img src="https://1456550285-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoWTlPaoHd1McSakqMigu%2Fuploads%2Fgit-blob-dbb686dd4fa49e46614bc0c0fdf11a5c11bce708%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

Set the Raycastable Crowd Class to the class you just created.

{% hint style="info" %}
You can create multiple Animated Crowds, and each crowd a separate Raycastable Crowd Class (with a separate pool of Raycastable Crowd Actors) can be used.
{% endhint %}

Your Raycastable Crowd should now be fully configured!

### Testing the Raycastable Crowd

To see the Raycastable Crowd in action, you can:

* Temporarily enable `Debug Visibility` in your Raycastable Crowd Actor class;
* Temporarily set `Num Raycastable Crowd Actors` in your Raycastable Crowd class to 1;
* Start a PIE deployment with 3 clients;
* Use the [console command](https://docs.msquared.io/creation/unreal-development/features-and-tutorials/the-animated-crowd/legacy-animated-crowd/animated-crowd-console-commands) `JunoGameData.SetValue game PlayerClient.Rendering.NumInLoD0 0` to force all players other than your local player into the Crowd

You should be able to see the visible Raycastable Crowd Actor on the character that your cursor is currently closest to.

<figure><img src="https://1456550285-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoWTlPaoHd1McSakqMigu%2Fuploads%2Fgit-blob-f37f681eeac144e3b934f915384cf8de875e4105%2Fimage.png?alt=media" alt=""><figcaption><p>The white skeleton is the mesh that the Raycastable Crowd Actor is using.</p></figcaption></figure>

### Interacting with the Raycastable Crowd Actors

Just as with regular Render Targets, the `Get Morpheus Actor` function will return the MorpheusActor that is currently associated with the Raycastable Crowd Actor.

This means that for any physical interaction such as a line query that returns an Actor, the `Get Morpheus Actor` function will return the associated MorpheusActor, regardless of whether the Actor is the MorpheusActor's Render Target or a Raycastable Crowd Actor.

<figure><img src="https://1456550285-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoWTlPaoHd1McSakqMigu%2Fuploads%2Fgit-blob-aab50a570c47c3772bdc1670e75c2158d53386d5%2Fimage.png?alt=media" alt=""><figcaption><p>This graph will print the name of the MorpheusActor that the line trace hit actor is associated with, whether that actor is a Render Target or a Raycastable Crowd Actor.</p></figcaption></figure>

## Additional configuration <a href="#integration" id="integration"></a>

### Priority Calculation Strategies <a href="#integration" id="integration"></a>

You can configure the priority calculation using multiple strategies to configure which Morpheus Characters should currently have Raycastable Crowd Actors. Multiple strategies can be used in combination.

* `Strategies Enabled` : Selector for which prioritization strategies to be used.
* There are currently 3 prioritization strategies that can selectively enabled:
  1. 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.
  2. 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.
  3. Area of Influence:
     * Prioritizes crowd members that are within user-defined Areas of Influence.
     * Use the functions`AddAreaofInfluence` 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.
     * Further details on this strategy below.

### Area of Influence Strategy

The Area of Influence strategy allows you to prioritise characters near certain coordinates. This can be used to give Raycastable Crowd Actors to characters who are near projectiles or other items that need to interact with crowd members.

When using this strategy, the areas of influence need to be added and removed at runtime using `AddAreaofInfluence` and `ClearAreasOfInfluence` in Raycastable Crowd class. To do this, you'll need a reference to your Raycastable Crowd, which you can get with `Get All Actors Of Class`. Note that there can be multiple Raycastable Crowd objects, and they only spawn when any players have entered the crowd, so you can't just cache them at the start of the game.

<figure><img src="https://1456550285-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoWTlPaoHd1McSakqMigu%2Fuploads%2Fgit-blob-a3d5413f7bfa49f3a9355975342fc66101a83cbb%2Fimage.png?alt=media" alt=""><figcaption><p>This is called whenever <code>Cached Raycastable Crowds</code> is empty to lazily initialize the cache.</p></figcaption></figure>

<figure><img src="https://1456550285-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoWTlPaoHd1McSakqMigu%2Fuploads%2Fgit-blob-41730b3b19f0e8ac74f47f51ab79f9a7ef630828%2Fimage.png?alt=media" alt=""><figcaption><p>This is called each tick to give Raycastable Crowd Actors to all characters near any projectile.</p></figcaption></figure>

### Customising the Viewpoint

The viewpoint from which the priority calculations are based is set with `Update View Info` . By default, this returns the `FMinimalViewInfo` of the player's camera. This can be overridden in the Raycastable Crowd class to provide a custom viewpoint for the priority calculations.

<figure><img src="https://1456550285-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoWTlPaoHd1McSakqMigu%2Fuploads%2Fgit-blob-88842d24890a7eb50adfb9ffc0593e4603717033%2Fimage.png?alt=media" alt=""><figcaption><p>Update View Info is called whenever the priority calculations are made.</p></figcaption></figure>

## Customising a Raycastable Crowd Actor at runtime

You may want to change the Raycastable Crowd Actor's mesh from the defaults at runtime. For example, if a gameplay effect has added a forcefield surrounding the character, you might need the Raycastable Crowd Actor to reflect this, so that collisions in the crowd are still accurate.

### Raycastable Crowd Actor Setup

When the Raycastable Crowd Actor is initialised, a number of SkeletalMeshComponents are created according to all the meshes that the Raycastable Crowd Actor could represent, based on the AvatarPhysicsAsset data. A capsule component is also created. You can access these by getting the children of the scene component.

Only one of these components has their collision responses enabled at any time, which is the component that matches the avatar the currently assigned Morpheus Character is using.

### Hooks for customising mesh assignment

When a new Morpheus Actor is assigned to a Raycastable Crowd Actor, or the Raycastable Crowd Actor needs to update its current mesh for another reason (e.g. its Morpheus Character changes what avatar it is using), `RaycastableMeshUpdate` is called.

The default implementation of `RaycastableMeshUpdate` calls `SetMeshCollisionsFromUserAvatar`. Override `RaycastableMeshUpdate` to customise what happens in this step.

<figure><img src="https://1456550285-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoWTlPaoHd1McSakqMigu%2Fuploads%2Fgit-blob-337aa0d8db792ffb28d62284aaa329eeeae691db%2Fimage.png?alt=media" alt=""><figcaption><p>In this example, I want my Raycastable Crowd Actor to ignore its usual behaviour and just use a Sphere as its collider whenever my character's <code>IsInBubble</code> variable is true. I have added my own Sphere component to the actor, and in the false branch, I disable the Sphere and call the regular Raycastable Crowd Actor before.</p></figcaption></figure>

{% hint style="info" %}
Don't forget the case where your Raycastable Crowd Actor needs to update its mesh even when its Morpheus Character hasn't changed! You'll need to call `Raycastable Mesh Update` yourself. This is easier with the Raycastable Crowd Component (below).
{% endhint %}

### Raycastable Crowd Component

The `Raycastable Crowd Component` is a component on every Morpheus Pawn class that exposes the above hooks from your Morpheus Pawn class, instead of needing references to the Raycastable Crowd Actors.

Call `ForceRaycastableCrowdActorUpdate` to cause `RaycastableMeshUpdate` to fire, if you need your Raycastable Crowd Actor to update while it is assigned to a Morpheus Character.

<figure><img src="https://1456550285-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoWTlPaoHd1McSakqMigu%2Fuploads%2Fgit-blob-25a008b48ab7d0bc33d9aab28e35fbf14a25c101%2Fimage.png?alt=media" alt=""><figcaption><p>This Blueprint is in my Morpheus Character. I need my Raycastable Crowd Actor to update its mesh if my player enables or disables their bubble. This causes the above <code>Raycastable Mesh Update</code> to fire when my IsInBubble variable changes on the character.</p></figcaption></figure>

You can also write your entire Raycastable Crowd Actor's custom logic in your Morpheus Character by binding to `OnRaycastableCrowdActorAssigned` and `OnUpdateRaycastableCrowdActor`.

<figure><img src="https://1456550285-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoWTlPaoHd1McSakqMigu%2Fuploads%2Fgit-blob-5780898f6b04a4330be2f41da19004a6bdd7621f%2Fimage.png?alt=media" alt=""><figcaption><p>I can implement the above custom <code>RaycastableMeshUpdate</code> in my Morpheus Character instead, using <code>RaycastableCrowdComponent.OnUpdateRaycastableCrowdActor</code> .</p></figcaption></figure>

T
