Populations - anticto/Mutable-Documentation GitHub Wiki

⚠️EXPERIMENTAL⚠️

Mutable Populations is an additional plug-in to automatically generate customized crowds or populations from an existing Mutable Object.

Within Populations Editor you can control randomness to create endless variations and content in realtime or in the production pipeline. Also use the editor to define generation rules for different populations to create cohesive groups that communicate a common origin, culture or guild. After release, new assets can be easily tagged to automatically enrich the variability of existing populations.

This plugin is offered as an example on how to generate population with Mutable. This is something very specific for each project, and this can be used as a template to create your own system.

Customizable Objects, Classes and Populations

image

Mutable Populations generate random Customizable Object Instances based on their internal configuration, which consists of Population Classes and relative chances to appear.

Each Population Class is based on a single Customizable Object , and it defines its typical traits. It does so by choosing which Parameter values should be able to be produced on random Customizable Object Instances and how often.


Population Class

This is a new type of asset added to Unreal Engine. It defines which Customizable Object is this class based on and what are its Characteristics.

Each Characteristic is a range of what are acceptable options for one Parameter and its relative chances of appearing on random Customizable Object Instances of this Population Class generated by a Population. Depending on the type of Parameter, it allows setting how common it is to find certain options, choosing a single value as valid, or even using a curve to define the chances of appearance of continuous numeric values. The class also allows denylisting and allowlisting integer and boolean Parameters via Tags , both globally and on individual Parameters.

You can create Customizable Population Classes from the Content Browser Add New menu:

image

Population

This is a new type of asset added to Unreal Engine. It produces random Customizable Object Instances according to how it's set up: which Population Classes and how often are they used.

This allows a single Population to create Customizable Object Instances from multiple different Customizable Objects and/or from the same Customizable Objects but from different Population Classes.

You can create Customizable Populations from the Content Browser Add New menu:

image

Its Customizable Object Instance generation algorithm is updated each time the Population or the Population Class are saved, using the Parameters from the Customizable Objects of each Population Class at that time. It's also updated when the project is packaged, so it's ensured to be up to date.


Population Class Editor

image

The left panel edits the Population Class. It's used to:

(1) Choose which Customizable Object it is based on. (2) Define characteristics of that class. (3) Set the global class tag allowlist and denylist.

There is at most one characteristic per parameter that the base Customizable Object has.

Each Characteristic is defined using Constraints: they define what values will be found in random Customizable Object Instance of the Population Class, for each Parameter, and their chances.

Different types of Constraints can be used to define a Characteristic depending on the Parameter type.

Multiple Constraints can be used on a singe Characteristic, each with a chance to be applied relative to the others defined by its weight.

Any Parameter that is not specified with a valid Characteristic will end up randomized by the Population Class, with each of its options having equal chance of being on a Customizable Object Instance generated from this particular Population Class.

The central panel defines the Customizable Object's Population Tags. These Tags can be used and modified from any Population Class that shares this Customizable Object. Tags are used to control what ends up in the random Customizable Object Instances via the global allowlist and denylist or setting Characteristics that use constraints of type "Tag". The panel allows you to:

(4) Add and remove Tags, to be able to use them. The text box can be used to add new Tags. Below it, there is the list that shows the existing Tags, where they can be deleted. (5) Choose which parameter are we going to be setting Tags for. (6) Define what Tags are appliable to each of the options of the enum.

The upper right panel (12) there's a curve editor. It shows to the last curve constraint from which the button "Open in Editor" was pressed, and allows for some basic tuning of the curve.

The lower right panel (7) shows a preview of what would be generated with the current settings. They are generated each time the "Test Population Class" button (8) is pressed. The amount of Customizable Object Instances generated can be defined using the down arrow next to the button, the default is ten.

Here you can also select instances to inspect them; in this image the left-most instance is chosen. With the Inspect Instance (10) button you are able to check and modify the chosen Customizable Object Instance in the editor. With the Inspect Skeletal Mesh (11) button you can check the resulting skeletal mesh.

Finally, the "Generate Instances" button (9) can be used to generate random Customizable Object Instance assets. These are normal Customizable Object Instances, to use as game assets from the editor, and they will have nothing else randomly generated after being created.

To generate random Customizable Object Instances at runtime, you can use the functions "Generate Population" and "Regenerate Population" found in the "Population" asset.


Population Tags

Tags are created on the tag manager text box. Tags are designed to be assigned to each of the options of an enum Parameter individually. Then, they are used to indicate that certain Parameter options should be found or not on Population Classes. That is done by allowlisting and denylisting those Tags. This is defined later in this section, with a truth table at the end. So, you can understand them as a way to filter what parameters get used or not by the Population Class.

image

To use a Tag, it first has to be created (4), then assigned to some Parameter options (6) (5), and finally used on allowlists and/or denylists either globally (3) and/or on a Constraint that affects a single Parameter (2).

Tags are stored in the Customizable Object, so different Population Classes of the same Customizable Objects have access to the same Tags, on the same Parameters and Parameter options.

Assigning Tags to each of the options of an enum is the main purpose of Population Tags, and together with denylists and allowlists allow to manage a growing amount of options without manually modifying each Population Class constraint that depends on it each time an option is added or removed.

Each Population Class has a general allowlist and denylist, to define in broad strokes what will and will not be found on Customizable Object Instances generated from that Population Class.

Integer and boolean Parameters can also have Tag Constraints set on them. Those Constraints override the global allowlists and denylists, but only for the specific Caracteristic that defines the Tag Constraint. This allows us to specify exceptions to the general allowlists and denylists to fine tune specific Parameters of Population Classes.

Tag lists follow this logic until some condition applies:

  1. If none of the Tags on any option of an enum are in any tag list for this Parameter: All of it's options have the same chance to appear.

  2. If one of the Tags of at least one option of an enum is in a Constraint list for this Parameter: Only enum options that don't have any Tag on the Constraint denylists appear. If any enum option Tag is in the allowlist, only options that have some Tag in the allowlist and none in the denylists appear. The table at the end describes the result:

  3. The same as point 2. but on global lists. If one of the Tags of at least one option of an enum is in a global list for this Parameter: Only enum options that don't have any Tag on the global denylist appear. If any enum option Tag is in the allowlist, only options that have some Tag in the allowlist and none in the denylist appear. The table at the end describes the result:

Truth table for allowlists and denylists:

The enum option has a Tag in allowlist The enum option has a Tag in denylist Another option of the same enum has a Tag in the allowlist Can this enum option appear on random Customizable Object Instances?
no no no YES
yes no no YES
no yes no NO
no no yes NO
yes yes no NO
yes no yes YES
no yes yes NO
yes yes yes NO