Repository navigation
Swarm Manager v1.3.4 – Mob Behavior & Vegetation Builder #6
Replies: 5 comments
|
⚙️ How to Use itGetting startedInstallationImport Swarm Manager from Asset Store or any other source. CustomizationAfter importing, find the Swarm Manager section under Tools in the top menu, inside you'll find multiple options to use:
Starting the system// Initialize and optionally set the player as main target
AssetSwarmManager.Manager.SwarmStart( playerTransform );
// Returns true when system finished loading
AssetSwarmManager.Manager.SwarmIsReady( );Spawning// Spawn a unit at position using a specific link ID
AssetSwarmManager.Mobs.Spawn_ByName( ID, position );
// Spawn a random unit from the link list
AssetSwarmManager.Mobs.Spawn_Any( position );
// Both return a reference script to the unit 'MobBrain' Despawning// Despawn a unit
AssetSwarmManager.Mobs.Despawn_ByMob( MobBrain );
// Or check if there's one inside a Game Object to despawn
AssetSwarmManager.Mobs.Despawn_ByGameObject( gameObject );Settings// Set a main target, if units don't have a target then this one will be used
AssetSwarmManager.Manager.Mob_MainTarget( targetTransform );
// Add a limit to the number of spawn units (set a value lower than 0 to not put a limit)
AssetSwarmManager.Manager.Mob_SpawnLimit( amount );Manager Tools// Set a flag to despawn all active units
AssetSwarmManager.Mobs.Global_KillAll( );
// If true, halt the manager stopping any Update
AssetSwarmManager.Mobs.Global_PlayPauseAll( trueOrFalse );
// Return a list with all active units
AssetSwarmManager.Mobs.Global_GrabAllActives( );
// Deal damage to all active units
AssetSwarmManager.Mobs.Global_DamageAll( damageValue );Update// Change the state of the manager loop
// true: manager will skip the update - false: update will be run as normal
AssetSwarmManager.Manager.Update_SetManual( trueOrFalse );
// If Manual Update is enabled (true)
// Run the update loop completely
AssetSwarmManager.Manager.Update_All( deltatime );
// Run the first part of the update loop until scheduling the job
AssetSwarmManager.Manager.Update_ToJobSchedule( deltatime );
// Run the second part of the update loop, complete the job and set data
AssetSwarmManager.Manager.Update_ToJobComplete( );
// Run the third part of the update loop to check if there's any mobs on the spawn/despawn queue
AssetSwarmManager.Manager.Update_ToCheckQueue( );Using Mob eventsTo use custom made events you need to use the interface IMobEvents, to do it you want to attach a monobehavior that use the interface or add it manually // example
public class MyEventsClass : MonoBehaviour, IMobEvents {
public void EventJustSpawned( ) {
// Do something when the mob spawn
}
public void EventChangedToIdle( ) {
// Do something when the idle animation start for the first time
}
public void EventIdleFinished( ) {
// Do something every time the idle animation finish
}
public void EventChangedToMove( ) {
// Do something when the move animation start for the first time
}
public void EventMoveFinished( ) {
// Do something every time the move animation finish
}
public void EventChangedToAttack( ) {
// Do something when the attack animation start for the first time
}
public void EventAttackFinished( ) {
// Do something every time the attack animation finish
}
public void EventDamageDealing( ) {
// Do something when the attack animation is at the selected frame
}
public void EventDamageTaking( ) {
// Do something when the mob takes damage
}
public void EventChangedToDeath( ) {
// Do something when the death animation start for the first time
}
public void EventDeathFinished( ) {
// Do something every time the death animation finish
}
} |
Prop Baker - How to useTo start, create a library file on your folder:
Prefabs are created with a script 'MobProp' that contains 3 structs
PropSettingsGlobal valuesValues need to be updated at runtime to see changes
PropSettingsInstance valuesValues need to be updated at runtime to see changes
Global settingsGlobal values can be set either on the shader to be used in a global way or in the material to be used on the objects using that material // Global on shader
Shader.SetGlobalFloat("_GlobalWindStrength", 3);
Shader.EnableKeyword("FULL_LIT");
// Global on material
Material matReference;
matReference.SetGlobalFloat("_GlobalWindStrength", 3);
matReference.EnableKeyword("FULL_LIT");Per instance settingsPer instance values needs to be set on a shared material on the renderer and specific values need to be set on a MaterialPropertyBlock to not break GPU instancing, the script has function to pass values safely by calling 'InstanceStart()' to start the object and 'InstanceUpdate()' to update values // Initialize the instance
private void Start() {
InstanceStart();
}
// Update the instance
InstanceUpdate(); |
Instancing ModeTo render objects on the scene this asset use Unity's API Batch Render Group(BRG) which allow to skip most performance cost that Game Objects has, allowing to render huge amounts of objects with high performance. This asset uses 2 custom VAT shaders, prefabs made with this asset's baker and BRG to render on scene animated instance with very low CPU cost while most of the process and weight goes to the GPU. Or as alternative this asset has another 2 custom shaders to be used without VAT which use mesh instead of prefabs. Culling is also another part of the rendering process which BRG also helps, enabling the developer to customize culling on the batch, this asset use 3 distances to either change LOD mesh or skip rendering the object, and a frustum radius to know on what side of the camera's planes the object is. 1. Registering/UnregisteringTo start using it, the user need a baked prefab or a mesh and the max amount of objects to render on gameplay, and just to be clear, the total amount because the batch won't be resized (but it can be eliminated and re-registered) after registration. // This will create the uploader on the system, save the PropUploaderID returned because it will be used as ID
PropUploaderID myUploaderID = AssetSwarmManager.Instance.Generate();
// This will allocate the memory necessary on the GPU to render the amount given
AssetSwarmManager.Instance.Register(myUploaderID, MobProp bakedProp, bool lod0IsLit, bool lod1IsLit, bool lod2IsLit, int maxAmount);
// Or with Mesh
AssetSwarmManager.Instance.Register(myUploaderID, Mesh lod0, bool lod0IsLit, Mesh lod1, bool lod1IsLit, Mesh lod2, bool lod2IsLit, int maxAmount);
// The value on lodNIsLit will tell what shader to use, Lit or Unlit, for the N LOD, each LOD uses different materials just for the sake of customizationAnd this will clean up if the game has no needs of using it // This destroy the object managing the prefab and calling the onDestroy function which will clean up all necessary data and freeing all allocated memory on the GPU
AssetSwarmManager.Instance.Unregister(myUploaderID);
// As safe as it can be, try not to do this too many times on a single frame, just keep it in moderation2. UploadingAfter generating, registering and allocating memory on the GPU there's a need to tell the manager where to render all instances or as many as the user wants(but not exceeding the limit amount), to do that the user will need minimum the position of all objects then send them to the manager. // Other values are optional but position is taken as priority to indicate the amount of objects to show, excess amount will be skipped
AssetSwarmManager.Instance.Upload(myUploaderID, List<float3> allPositions);
// Or you can use the full option, any empty optional values will be filled with default values that can be set beforehand
AssetSwarmManager.Instance.Upload(myUploaderID, List<float3> allPositions, List<float3> allRotations, List<float3> allScales, List<Color> allColors, List<Color> allRimColors, List<float4> allDetails);
// float4 Details: x=animation speed(0 to 2), y=animation phase(0 to 1), z and w are free for the momentThis will tell the manager to render the prop selected on all the position sent with the settings added as optional. 3. Setting culling optionsThe culling job will choose what to show using the camera as center and the culling values set by the user. // Set culling options for all instances for the uploader ID sent
AssetSwarmManager.Instance.Update_CullingOptions(myUploaderID, float frustumRadius, float lod0Distance, float lod1Distance, float cullDistance, int frameSkip);
// frustumRadius(default=30): from each 6 planes on the camera(imagine a pyramid with the top cut), objects inside the planes are taken as visible
// lodDistances: distances from the camera to each enabled object is calculated then compared with the distance set, objects on a distance higher than LOD1 distance and lower than the culling value will use LOD2. All objects past the culling distance will not be rendered
//frameSkip(default=4): calculations are saved then depending on the frame skip value, these calculations will be reused to save CPU.Light pass can call the culling too in case shadows are enabled, only 1 shadow result is saved so it's recommended to use 1 cascade AssetSwarmManager.Instance.Culling_Shadow(myUploaderID, float frustumShadowRadius, float shadowDistance);
// frustumShadowRadius(default=30): same as camera, an area from the light source that follows the camera, objects inside the frustum will be taken as objects that render shadows
// shadowDistance(default=50): radius around the camera, objects inside it will render shadows, mostly for tall objects like trees that should show shadows on view even after they are out of screenCommands are whats sent to the BRG system to know what and how to render, a few values can be set which can be relevant on some occasions AssetSwarmManager.Instance.Culling_Commands(myUploaderID, int lodLevel, bool shadowCasting, float shadowReceive, bool shadowStaticCaster);
// lodLevel: which LOD(0, 1 or 2) to affect, use a different value to set it to all LODs
// shadowCasting: does the object cast shadow
// shadowReceive: shadow attenuation value, higher values can have interesting visuals
// shadowStaticCaster: if the object is completely static, no movement or mesh deformation4. Setting Default valuesSet default values to be used on upload. // Set default Transform values
AssetSwarmManager.Instance.Defaults_Transform(myUploaderID, float3 rotation, float3 scale);
// Set default color, and if enabled get a randomized color for each instance
AssetSwarmManager.Instance.Defaults_Color(myUploaderID, Color color, bool randomize);
// Set default rim color, or if enabled get a randomized color for each instance
AssetSwarmManager.Instance.Defaults_Rim(myUploaderID, Color color, bool randomize);
// Set default phase making all instance start on the same animation frame or randomize the phase making all instances have different timing
AssetSwarmManager.Instance.Defaults_Phase(myUploaderID, float value, bool randomize);
// Set default animation speed
AssetSwarmManager.Instance.Defaults_AnimationSpeed(myUploaderID, float value);5. VisualsAll shaders have a few customizable options to use: AssetSwarmManager.Instance.Material_AlphaClipping(myUploaderID, float value, int lod, int submesh);
AssetSwarmManager.Instance.Material_Saturation(myUploaderID, float value, int lod, int submesh);
AssetSwarmManager.Instance.Material_Contrast(myUploaderID, float value, int lod, int submesh);
AssetSwarmManager.Instance.Material_Brightness(myUploaderID, float value, int lod, int submesh);
AssetSwarmManager.Instance.Material_Rim(myUploaderID, float value, int lod, int submesh);
AssetSwarmManager.Instance.Material_Wind(myUploaderID, float value, int lod, int submesh);
AssetSwarmManager.Instance.Material_Dither(myUploaderID, float value, int lod, int submesh);
AssetSwarmManager.Instance.Material_Albedo(myUploaderID, Texture2D albedo, int lod, int submesh);
AssetSwarmManager.Instance.Material_Normal(myUploaderID, float value, Texture2D normal, int lod, int submesh);
AssetSwarmManager.Instance.Material_Mask(myUploaderID, float value, Texture2D mask, int lod, int submesh);
AssetSwarmManager.Instance.Material_Subsurface(myUploaderID, float value, Color subsurface, int lod, int submesh);
AssetSwarmManager.Instance.Material_Shadow(myUploaderID, Color shadow, int lod, int submesh);
// lod: the LOD to affect, use a value different from 0 to 2 to set them on all LODs
// submesh: the submesh to affect, for VAT prefabs this value should always be 06. UpdatingUpdating instance can be done after uploading with not many problems depending on the way to do it, what BRG likes is updating in bulk not one by one so consider your approach.
// Change the visibility state of the object with the same index
AssetSwarmManager.Instance.Update_State(myUploaderID, int index, bool state);
// Set the state for all instances
AssetSwarmManager.Instance.Update_StateAll(myUploaderID, bool state);
// Set the state for as many instances as the amount on the array
AssetSwarmManager.Instance.Update_StateSource(myUploaderID, bool[] source);
// Set the state for as many instances as the amount on the array. Value equal to 0 will disable instances
AssetSwarmManager.Instance.Update_StateSource(myUploaderID, int[] source);
// Change the position, rotation and scale of the instance with the same index as the one set
AssetSwarmManager.Instance.Update_Transform(myUploaderID, int index, float3 position, float3 rotation, float3 scale);
// Change the position, rotation and scale of as many instance as the amount of positions set. Rotations and scales are optional but they will use default values if not passed
AssetSwarmManager.BRGUpload.Update_TransformAll(myUploaderID, List<float3> allPositions, List<float3> allRotations, List<float3> allScales);
AssetSwarmManager.BRGUpload.Update_TransformAll(myUploaderID, float3[] allPositions, float3[] allRotations, float3[] allScales);
// Change the transform data of as many instance as the amount of the smallest array passed
AssetSwarmManager.Instance.Update_TransformRaw(myUploaderID, NativeArray<float3> positions, NativeArray<PackedMatrix> objectToWorld, NativeArray<PackedMatrix> worldToObject);
// Using transform
var matrixOtoW = transform.localToWorldMatrix;
var inverseWtoO = matrixOtoW.inverse;
// Or using transform data
var matrixOtoW = Matrix4x4.TRS(position, rotation, scale);
var inverseWtoO = matrixOtoW.inverse;Afterward you can get the packed matrix using the struct on this asset as format PackedMatrix packedOtoW = new PackedMatrix(matrixOtoW);
PackedMatrix packedWtoO = new PackedMatrix(inverseWtoO);7. GettersYou can obtain a list of all the props positions uploaded by using: List<float3> myList = AssetSwarmManager.Instance.GrabPositions_List(myUploaderID);
float3[] myList = AssetSwarmManager.Instance.GrabPositions_Array(myUploaderID);
NativeArray<float3> myList = AssetSwarmManager.Instance.GrabPositions_NativeArray(myUploaderID);Using the NativeArray function will not give a pointer to the same array as the one on the uploader, just a copy that needs disposing when not used |
Technical Information (This is just technical info, you don't need to remember this)👩🏻🍳 Baking processThe usual path the asset will follow to prepare the animation is:
Afterwards the conversion to VAT starts:
On Spawning a mob or changing animation
|
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Swarm Manager is a tool that helps adding animated props or mobs to your game with low CPU cost.
It uses performance-oriented animation techniques combined with an inspector-friendly workflow to make large crowds simple to set up and control.
What the asset provides
For the mobs side
For the prop renderer
Stress Test Video
Unity discussion thread
Unity Asset Store
Free Lite version to test
Instance Mode Test on Unity Play
All reactions