Skip to content

Commands

pixeption edited this page Oct 22, 2021 · 13 revisions

When in development, you may want to do lots of thing on your device without rebuilding or reinstalling like clear all saved data, add items, make player invincible ... You can create your own commands for that

There are 2 types of command:

Setting Command

Used for quick settings (Show/hide FPS text, Enable/Disable Player Invincible, Change player damage ...)

Executable Command

Used for more complex actions which can be executed with inputs (Reset level, Add items, Prints out inventory ...)

Both Setting and Executable Command are shared the same class, thus most of their behaviours are the same, the only difference is Execute function do nothing on Setting Command

Define a setting command

To create a setting command, you need to create a class that inherits from Command and add [SettingCommand(name = "name")] above it.

using MobileConsole;

[SettingCommand(name = "Console")]
public class ConsoleSettings : Command
{
    [Variable(OnValueChanged = "UpdateShowFPS")]
    public bool _showFPS;

    [Variable(OnValueChanged = "UpdateShowTimestamp")]
    public bool _showTimestamp;

    [Variable(OnValueChanged = "UpdateShowChannel")]
    public bool _showChannel;
    ...
}

Command name

  • The name of Setting command can have multiple levels separated by "/" character. For example: System/Console
  • If the name is not specified, class name will be used as setting name

Define an executable command

This is pretty much the same as creating setting command, the different is you need to add [ExecutableCommand(name = "name)] attribute instead of SettingCommand and override Execute function

[ExecutableCommand(name = "Game/Restart Game")]
public class RestartGameCommand : Command
{
	public override void Execute()
	{
		SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
	}
}

Simple and Complex executable command

  • A simple command is a command that has no public primitive variable
  • A complex command is a command that has one or more public primitive variable

As simple commands have no input, it will be executed when you tap on the command in Command View. On the other hand, a Command Detail View will be opened when taping on a complex command.

Add Custom buttons

Normally there is only one button at the bottom right corner to execute the command, however you might want to add another button to Command View. You can do that with [Button] attribute

[Button(category = "Action", icon = "share")]
void Share()
{

}
  • category: is the group that this button belongs
  • icon: the name of icon that will be used for this button. The list of available icons can be found in Assets/Mobile Consoles/Assets/AssetConfig.asset/Sprites

Please note that the function name is also the button name.

Variables in depth

By default, any primitive public variable will be exposed on the tool

Supported controls

Input

Support types: string , int, float, double, long

public int startHp = 1;
public float movementSpeed = 10;
public string playerName;

Checkbox

Support Types: bool

public bool invincibility = false;

Slider

Support types: int, float, double, long with [Range(min, max)] attribute

[Range(1, 20)]
public int startHp = 1;

Dropdown

Support types: Enum (default). string, int, float, double, long with [Dropdown(optionsFunctionName)] attribute

public enum SearchType 
{ 
    Name, 
    Tag, 
    Component 
}

public SearchType searchType;

For other types than enum, you need to define a function that return an array of options and pass the function name to Dropdown attribute

[Dropdown("TimeScaleOptions")]
public float _timeScale = 1.0f;

float[] TimeScaleOptions()
{
    return new float[] 
    {
        0.25f,
        0.5f,
        1.0f,
        1.5f,
        2.0f,
        2.5f,
        3.0f,
        4.0f,
        6.0f
    };
}

Init default variable value

Normally, you can define default value of variable by define and assign it

public float _backgroundTransparency = 1.0f;

However, if the value can not be pre-defined and can be obtained only at runtime, you can init its default value in InitDefaultVariableValue function, this function will be called right after the command is created and before the command loads saved variable value (if it was saved before).

Note that if a variable has been saved before, its value will be overriden by saved value.

public override void InitDefaultVariableValue()
{
	_showFPS = LogConsoleSettings.Instance.showFPS;
	_showTimestamp = LogConsoleSettings.Instance.showTimestamp;
	_showChannel = LogConsoleSettings.Instance.showLogChannel;
	_windowWidth = LogConsoleSettings.Instance.windowWidth;
	_windowHeight = LogConsoleSettings.Instance.windowHeight;
	_windowPosX = LogConsoleSettings.Instance.windowPosX;
	_windowPosY = LogConsoleSettings.Instance.windowPosY;
	_backgroundTransparency = LogConsoleSettings.Instance.backgroundTransparency;
}

OnVariableValueLoaded

This function will be called right after the command loads saved variable value (if it was saved before). You can do the initialization for your system here to ensure it has all new data (loaded from PlayerPref)

public override void OnVariableValueLoaded()
{
	// Init your system here or override the data
}

Variable value

For convenience:

  • Variable value will be saved automatically to PlayerPrefs when it's changed
  • Variable value will be loaded automatically after the command is created

Handle when a variable value has changed

There are 2 ways to handle this, each one has its own cons and pros based on the situation. You can choose which one you want or both of them

Using VariableAttribute

To handle on value changed, you need to add VariableAttribute to the variable and indicate the function name that will be called when the value is changed.

[Range(0.1f, 1.0f)]
[Variable(OnValueChanged = "UpdateBackgroundTransparency")]
public float _backgroundTransparency = 1.0f;

void UpdateBackgroundTransparency()
{
	LogConsoleSettings.Instance.backgroundTransparency = _backgroundTransparency;
	EventBrigde.NotifyBackgroundTransparencyChanged();
}

Note: As mentioned above, the variable will be loaded automatically after the command is created, thus the OnValueChanged function will be called too so the game will update the state of current settings

As VariableAttribute is introduced to reduce the pain of duplicated code in the version 1.0, OnVariableValueLoaded and OnValueChanged(string varName) have been deprecated. These functions still work but you should use VariableAttribute instead

Using OnValueChanged(string varName)

Override the function to handle when a variable value has changed, all changes will be called here

public override void OnValueChanged(string varName)
{
	if (varName == "_backgroundTransparency")
	{
		// Update backgroudn transparency
	}
}

Get Command Instance

There might be case that you want to set a command values from you game. Example there is a PlayerSettingCommand, but the Player instance only exist when enter in-game scene, then you can get the command and set its values directly.

Please note that you have to update the command logic by yourself, the Console doesn't aware of these changes

void OnMainGameSceneLoaded()
{
	Player player = GameManager.GetPlayer();
	PlayerSettingCommand command = LogConsole.GetCommand<PlayerSettingCommand>();
	command.hp = player.hp;
	command.attackDmg = player.attackDmg;
}

Commands with Zenject

As Zenject is becoming more and more popular with Unity developers, you might want to use Zenject with commands. Here is how:

using MobileConsole;

void OnInitialized()
{
    // Check if commands have been created
    if (LogConsole.IsCommandsCreated())
    {
        OnCommandCreated(LogConsole.GetCommands());
    }
    else
    {
        LogConsole.OnCommandsCreated += OnCommandCreated;
    }
}

void OnCommandCreated(List<Command> commands)
{
    foreach (var command in commands)
    {
        Container.Inject(command);
    }
}