Conditions¶
Conditional logic can be applied to any document. Currently, we use it to run GameEvents. Any condition starts with one of 2 logical operators And / Or. Then you can add any other types of conditions. The conditions can be as complex and nested as you want.
- Dates Range, Day Of The Week, and Time Of The Day are conditions based on a specific time.
- ABTest Condition checks if the user was assigned to a specific A/B Test and Variant.
- Active Event triggers only if the specified GameEvent is active right now.
- Segment Condition checks if the user belongs to a specific Segment.
- Revenue checks if the user has generated a specific amount of in-app/ads revenue(count) during certain days.
- Was Item Purchased checks if a StoreItem was purchased at least once.
- Was Product Purchased checks if a Product was purchased at least once.
- Primitive allows you to use any custom User Properties.
- Country checks if the user is from the specified country.
Note: Please use this Country condition under the System category instead of getting the custom Country User Property from Primitive condition.
Section for programmers¶
GameEvent documents take care of the conditional logic. However, if you want to add conditions to your documents, here are the steps you need to take:
- Let's say you have a Document, named MyDocument with a conditional parameter Condition.
- Use interface for your class
IConditionsListener
which will be responsible for the logic. Usually, it's some Manager. - Call the following method
LiveOps.General.ConditionSubscribe(MyDocument.Condition, MyDocument, this, PassType.False);
. -
The default condition value (PassType.True or PassType.False) is the last parameter in the method above. Whenever the condition state changes, one of the following methods from the interface
IConditionsListener
is called on your Manager:public void ConditionPassed(object data);
public void ConditionFailed(object data);
-
The data parameter in the methods above is the second parameter you send to the
LiveOps.General.ConditionSubscribe
- it's MyDocument in our example. - At any time you can check Condition state by calling LiveOps.General.CanPassCondition(MyDocument.Condition);
public class Manager : IConditionsListener
{
private void Start()
{
foreach (var ev in DataManager.GameEvents)
LiveOps.General.ConditionSubscribe(ev.Condition, ev, this, IsGameEventActive(ev));
}
public void ConditionPassed(object data)
{
if (data is GameEvent gameEvent)
StartEvent(gameEvent);
}
public void ConditionFailed(object data)
{
if (data is GameEvent gameEvent)
StopEvent(gameEvent);
}
....
....
....
}
Custom conditions¶
- Create a new Template inherited from CustomCondition to add your condition. For example TestCondition.
- Mark it with Partial flag to be able to add methods.
- After the code is generated, add a new class inside of the Balancy folder (due to the amsdef file) but outside of the AutoGeneratedCode folder (to avoid data loss after the following code generation). For example, you can make a new folder Assets/Balancy/Custom and put all your custom scripts there.
public partial class TestCondition : SmartObjects.Conditions.Custom
{
public override bool CanPass(IUserConditionEnvironment environment)
{
//TODO return true or false
}
protected override void SubscribeForPrivateInfo(IUserConditionEnvironment environment)
{
//TODO subscribe for all the required events and call OnUpdate() method to force conditions to recalculate
}
protected override void UnsubscribeFromPrivateInfo(IUserConditionEnvironment environment)
{
//TODO clean up all subscriptions
}
}
Conditional Template¶
When working with Conditions, especially creating your own configs, it might become complicated. For this reason we added a built-in Conditional Template. All our built-in features: GameEvent, In-Game Shop, Segmentation, Overrides and A/B tests are now built on the top of it. Balancy automatically tracks the Conditions and Priorities of all Conditional Templates and notifies user when something changes.
- A/B Tests and Overrides are using Conditional Template to identify the priority of overrides. The priority of A/B Test doesn't affect the A/B Test itself, it affects the priority of Overrides, created by the A/B test. Nothing changes for the Balancy user, but in case several Overrides or A/B Tests trying to change the parameter, Balancy will pick the override with the HIGHEST priority.
- In-Game Store are now also using the Conditional Template, allowing you to have multiple Stores. The active store will be determined by the Conditions and Priority params of each of the Stores.
You can create a new Template, inherit it from Conditional Template to use the full power of the automation. Balancy automatically tracks the availability of such documents.
-
Use the following method to subscribe to get notified if the document availability has changed
LiveOps.General.SubscribeForConditions<T>((document, passed) => { Debug.LogWarning($"{document.UnnyId} passed = {passed}"); }, true);
-
At any point of time you can request the list of all the active documents of a specific type:
LiveOps.General.GetAllActiveConditionalTemplates<BattlePass>();
-
If you have a GameConfig, which is singleton type. This is how you can access the selected document and track the changes:
var activeConfig = DataEditor.GameConfig.Get(); DataEditor.GameConfig.OnChanged += newActiveConfig => { Debug.LogWarning($"New Singleton for GameConfig {newActiveConfig.UnnyId}"); };
Helpful information
Conditional Templates, as well as Singletons, are initialized during the Init all Managers. This means that you can start using all configurations as soon as Balancy is ready.
In most cases, you will be using conditions based on parameters like AppVersion, Country, Platform, or an A/B Test—conditions that do not change during a session. Once Balancy is ready, you can safely retrieve accurate data based on these static conditions.
However, if you are using any dynamic conditions—such as those based on time or user properties (e.g., level >= 10
)—Conditional Templates, including Singletons, may change during the session. Balancy will notify you of any changes through the OnChanged
callback, though tracking these changes is optional.
A good practice is to avoid caching Singletons from Balancy. Instead, always access them directly, for example, by using DataEditor.GameConfig.Get()
. This ensures that you're always working with the most up-to-date data.
Example:¶
After creating a custom Singleton, make sure to inherit it from the ConditionalTemplate. This allows you to control active singletons using conditions, priorities, and default values. Balancy will list all the documents that pass the conditions and pick the one with the highest priority. If none of the documents pass the condition, Balancy will fall back to the default one.
For instance, if you want to A/B Test the configuration for non-payers, you can create a new A/B Test and add it as a condition. Here’s an example of setting up an A/B Test condition:
In this case, I've added a new configuration for non-payers from A/B Test group A and set a higher priority for it, ensuring that this configuration is applied when the conditions are met.