ModuleInstances can be attached to Modules so that unique data can be selected per StatusEffectData. Create one by simply inheriting from the ModuleInstance class or using Create > Status Effect Framework > Module Instance Script.
You NEED to use the StatusEffects.Modulesnamespace like in the example below for both Modules and ModuleInstances.
You do not need to add these to the create menu! As long as it is attached to a Module using the attribute it will be created automatically.
As an example, say you need a VFX prefab to be instantiated on each effect. Instead of having to create a unique Module for each prefab that you need, just add the variables you need in the ModuleInstance and attach it to the Module using the [AttachModuleInstance] attribute.
Now, every time you add a module to a StatusEffectData, it will instantiate those values for that effect making it so you only need to create one Module scriptable object with any constant values and then unique instance values will be displayed in each specific StatusEffectData.
Example
using UnityEngine;
// Use StatusEffects.Modules namespace for organization.
namespace StatusEffects.Modules
{
public class VFXInstance : ModuleInstance
{
public GameObject prefab;
}
}
using System.Threading;
using UnityEngine;
// Use StatusEffects.Modules namespace for organization.
namespace StatusEffects.Modules
{
// Setup scriptable object in create menu.
[CreateAssetMenu(fileName = "Vfx Module", menuName = "Status Effect Framework/Modules/Vfx", order = 1)]
// This attribute will attach the module instance so
// that the vfx can be unique to each effect.
[AttachModuleInstance(typeof(VfxInstance))]
public class VfxModule: Module
{
public override async Awaitable EnableModule(StatusManager manager, StatusEffect statusEffect, ModuleInstance moduleInstance, CancellationToken token)
{
VfxInstance vfxInstance = moduleInstance as VfxInstance;
// Make sure the particle system stop action is set to destroy so it
// automatically destroys itself when all particles die.
GameObject vfxGameObject = Instantiate(vfxInstance.Prefab, manager.transform);
// If we want this effect to be added everytime more are stacks
// added we just immediately begin destruction on the current
// particle.
if (vfxInstance.InstantiateAgainWhenAddingStacks)
statusEffect.OnStackUpdate += (previous, stack) => OnStackUpdate(vfxInstance.Prefab, manager, statusEffect, previous, stack);
else
while (!token.IsCancellationRequested)
await Awaitable.NextFrameAsync();
// Attempt to stop the particle system.
if (!vfxInstance.InstantiateAgainWhenAddingStacks)
{
// Note that you need to check if the effect is null in case
// the cancellation was invoked from the destruction of
// the MonoBehaviour.
if (!vfxGameObject)
return;
vfxGameObject.GetComponent<ParticleSystem>().Stop();
}
}
}
}
using Cysharp.Threading.Tasks;
using System.Threading;
using UnityEngine;
// Use StatusEffects.Modules namespace for organization.
namespace StatusEffects.Modules
{
// Setup scriptable object in create menu.
[CreateAssetMenu(fileName = "Vfx Module", menuName = "Status Effect Framework/Modules/Vfx", order = 1)]
// This attribute will attach the module instance so
// that the vfx can be unique to each effect.
[AttachModuleInstance(typeof(VfxInstance))]
public class VfxModule: Module
{
public override async UniTaskVoid EnableModule(StatusManager manager, StatusEffect statusEffect, ModuleInstance moduleInstance, CancellationToken token)
{
VfxInstance vfxInstance = moduleInstance as VfxInstance;
// Make sure the particle system stop action is set to destroy so it
// automatically destroys itself when all particles die.
GameObject vfxGameObject = Instantiate(vfxInstance.Prefab, manager.transform);
// If we want this effect to be added everytime more are stacks
// added we just immediately begin destruction on the current
// particle.
if (vfxInstance.InstantiateAgainWhenAddingStacks)
statusEffect.OnStackUpdate += (previous, stack) => OnStackUpdate(vfxInstance.Prefab, manager, statusEffect, previous, stack);
else
await UniTask.WaitUntilCanceled(token);
// Attempt to stop the particle system.
if (!vfxInstance.InstantiateAgainWhenAddingStacks)
{
// Note that you need to check if the effect is null in case
// the cancellation was invoked from the destruction of
// the MonoBehaviour.
if (!vfxGameObject)
return;
vfxGameObject.GetComponent<ParticleSystem>().Stop();
}
}
}
}
using System.Collections;
using UnityEngine;
// Use StatusEffects.Modules namespace for organization.
namespace StatusEffects.Modules
{
// Setup scriptable object in create menu.
[CreateAssetMenu(fileName = "Vfx Module", menuName = "Status Effect Framework/Modules/Vfx", order = 1)]
// This attribute will attach the module instance so
// that the vfx can be unique to each effect.
[AttachModuleInstance(typeof(VfxInstance))]
public class VfxModule: Module
{
public override IEnumerator EnableModule(StatusManager manager, StatusEffect statusEffect, ModuleInstance moduleInstance)
{
VfxInstance vfxInstance = moduleInstance as VfxInstance;
// Make sure the particle system stop action is set to destroy so it
// automatically destroys itself when all particles die.
// Give the vfx the name of the prefab so it can be queried later.
GameObject vfxGameObject = Instantiate(vfxInstance.Prefab, manager.transform);
vfxGameObject.name = vfxInstance.Prefab.name;
if (vfxInstance.InstantiateAgainWhenAddingStacks)
statusEffect.OnStackUpdate += (previous, stack) => OnStackUpdate(vfxInstance.Prefab, manager, statusEffect, previous, stack);
yield break;
}
public override void DisableModule(StatusManager manager, StatusEffect statusEffect, ModuleInstance moduleInstance)
{
VfxInstance vfxInstance = moduleInstance as VfxInstance;
// If we are instantiating when adding stacks it has already been destroyed.
if (vfxInstance.InstantiateAgainWhenAddingStacks)
return;
// This magic name finding system is horrible but it works.
// Unitask would do the enabling and disabling so much better
// since the reference to the GameObject can be kept as
// DisableModule is just when cancellation is called.
Transform vfxTransform = manager.transform.Find(vfxInstance.Prefab.name);
if (!vfxTransform)
return;
GameObject vfxGameObject = vfxTransform.gameObject;
// Attempt to stop the particle system.
vfxGameObject.GetComponent<ParticleSystem>().Stop();
// Unset the parent so that if multiple effects are being removed
// it doesn't grab the same VFX twice.
vfxTransform.SetParent(null);
}
}
}