Commands
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:
Used for quick settings (Show/hide FPS text, Enable/Disable Player Invincible, Change player damage ...)
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
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;
...
}
- 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
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);
}
}
- 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.
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.
By default, any primitive public variable will be exposed on the tool
Support types: string , int, float, double, long
public int startHp = 1;
public float movementSpeed = 10;
public string playerName;
Support Types: bool
public bool invincibility = false;
Support types: int, float, double, long with [Range(min, max)]
attribute
[Range(1, 20)]
public int startHp = 1;
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
};
}
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;
}
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
}
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
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
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
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
}
}
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;
}
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);
}
}