Documentation
Features
🎬 Conditional Actions

🎬 Conditional Actions


Conditional actions consists of 2 separate systems which can be used together: Conditions and Actions. They are small independent scripts that can be used in many different scenarios allowing really simple to extremely complex scenarios. Using these small script allows maximum reusability and decoupling.

public interface ICondition
{
	bool IsValid();
}
 
public interface IAction
{
	void Execute();
}

In this example the Conditional Action check if it is a NewPlayer and if the game is in a specific FlowNode, then send the NewGame analytics event:


ConditionalActions example

At its core, the Conditional Actions are extremely simple, but allow for great versatility with extensions.

Create many reusable conditions and actions for use in upcoming features and future games.

ConditionalActions can be used in different ways and locations:

  • Flow nodes and transitions
  • GameObject Components
  • Code
  • Debug menu
  • Different system such as Sequences, Milestones, AB Testing etc.

Conditions

Usage

In essence, conditions just check if something is true or false. Due to its data structure you can stack conditions to make complex scenarios which are editable in the inspector by developers and designers alike.

ConditionLibrary

Conditions can be create as library assets. There is nothing else to configure aside from adding the condition stack:


Conditions library asset

Condition from flow

Conditions can be used as transitions to create decoupled and complex checks to make the player navigate exactly as intended. This example only uses the transition if there are rewards to claim, the player is on a mobile device and it is the weekend:


Conditions flow

ConditionalActions can be used on nodes as well, the toggle allows for executing an action if the conditions are met, and other actions when the conditions are not set.


Conditions node

!!! tip "Actions on update" If you want to execute the actions repeatedly every update, instead of adding it to the OnEnter in the Action State (Detailed), just add it to the OnUpdate instead.
Enabling toggle in the OnUpdate will make the ConditionalAction act as a light switch: when the conditions are true, the Actions are executed once, then when the conditions turn to false, the InvalidActions are executed.

Conditional Actions from components

Conditional actions can really shine when used as component. In this example it keeps checking if the top bar is visible, and when it is, it plays a sound effect and enables a button.


Conditional action component

The ActionUnityEvent can only be used through components but is very powerful to change the look and functionality of a screen.

  • Check Manually When unchecked, the script will update through OnUpdate() but if you want to be in full control, enable this box and call CheckConditions() to do it manually.
  • Toggle Enables the "light switch" mode which will call Actions when the conditions are true and InvalidActions when false.
  • Check Validation Once will just check the conditions a single time, continuous keeps checking every frame.
  • Run Actions Execute the Actions one time when the conditions became valid. Continuous will keep executing the Actions every frame as long as the conditions are valid.

Condition from code

Conditions are easily created by implementing the ICondition interface. The script will now appear in any condition dropdown.

public class ConditionBoolean : ICondition
{
	public bool Enabled;
 
	public bool IsValid()
	{
		return Enabled;
	}
}

Adding an ICondition or a collection of IConditions will enable the drawers in the inspector:

public List<ICondition> Conditions = new List<ICondition>();

You can also use the ConditionLibrary assets if needed, it works the same as any LibraryAsset, just add the [Condition] attribute to a Guid:

[Condition]
public List<Guid> Conditions = new List<Guid>();

Condition inspector

Conditions are drawn in the inspector while running the game showing a green valid or red invalid state. These can be on Components or on Condition LibraryAssets, they both work.


Conditions inspector

!!! danger "Inspector can affect outcome" When creating conditions, take in consideration that the condition can viewed in the inspector and debug menu which shows the valid state. This will activate your code and can result in it producing invalid results compared to a clean run of the game.
An example of this is a timer: When viewing the timer in the inspector, it should not start running. To fix this: Add the start timer logic inside the IInitializable to make it work in both scenarios.

Condition debug menu

All conditions assets from the ConditionLibrary can be inspected on device at any time by navigating to GameState > Conditions. This can even be useful for QA to debug and see the inner workings of the application, such as checking if the player has completed a checkpoint.


Conditions debug menu

IInitializable Condition

Add any dependencies and in-game starting values to the IInitializable. Only in-game systems should call the IInitializable, and the inspector does not. So when you view a timer in the inspector, it is not started yet because it is not initialized. When an in-game system uses the condition, it will call the initialize method and the timer works as intended.

This is how you would call the initialize:

List<ICondition> conditions;
 
// Calling Initialize() returns true if it has been initialized.
if (conditions.Initialize() &&
	conditions.IsValid())
{
	// Implement actions here which should happen when all
	// conditions are initialized and valid.
}
 
// You can also just check if the conditions are initialized without
// starting the initialization process.
if (conditions.IsInitialized())
{
 
}

When finished with conditions, call Reset on them.

IDisposable Condition

Just like with Services, implement the IDisposable by condition to clean up any cached assets in the Dispose() method. Different systems clear the disposables at different times. It also saves on memory and performance when caching the condition states.

Expansions

There are a few build-in expansions on the ICondition, but most of your conditions will not use these.

  • ICallbackCondition
    Implement ICallbackCondition for optimization purposes. Used by the Sequence system to wait for a callback instead of polling the conditions every frame.

    public interface ICallbackCondition : ICondition
    {
    	event Action OnValid;
    	void Register();
    }
  • IProgressCondition Used by the MilestoneService to to show the progress of a milestone. For example leveling up goes from 1000 xp to 1200 xp, with a current xp of 1145 can show 145 / 200 xp in the progression.

    public interface IProgressCondition : ICondition
    {
    	int Value { get; }
    	int StartValue { get; }
    	int Target { get; }
    }
  • IInfoCondition The MilestoneService uses this as well to return the visual text info on the milestone progression.

    public interface IInfoCondition
    {
    	string Info { get; }
    }
  • IMultiCondition IMultiCondition contains an inner list of conditions, used by condition operators (ConditionOperatorAll, ConditionOperatorOr etc.) This is mostly used to find specific conditions for inspector drawing purposes.

    public interface IMultiCondition : ICondition, IInitializable, IDisposable
    {
    	List<ICondition> Conditions { get; }
    }

Build-in Conditions

GameSuite has many build-in conditions which you can explore for yourself. Lets go over a few interesting conditions which will help level up your game development:

Operators

Operators are conditions that can be stacked to create complex behaviors:


Conditions operators example

They cover a wide range of possible options and it is easy to create new operators by inheriting from ConditionOperatorBase and implement the IsValid method.


Conditions operators

Actions

Usage


Action debug menu

Any Actions from the ActionLibrary can be executed from the debug menu.

Creating Actions

Actions are scripts that execute a single action, just like this hello world example:

public class ActionDebugLog : IAction
{
	public string Message;
 
	public void Execute()
	{
		Debug.Log(Message);
	}
}

IDisposable Action

Just like Conditions, Actions can also implement IDisposable. In most scenarios the Dispose will be called right after execution, but in case of the Sequence system the action will only get disposed after a step has finished.

Build-in Actions

Many build-in actions allow for most scenarios in game design, but creating new variations is extremely easy. These are just some examples of what is possible:


Action examples