To define new or modify existing Scriptable Objects, modify Interfaces and/or Enums located in the folder Assets/Parameters/Interfaces/. Code for parameter Scriptable Objects and relevant files are automatically created upon compilation of new changes to files in this folder.
These files live under the Interfaces folder and can be organized in subfolders.
Before reading about the workflows below, read about the anatomy of interfaces & enum at InterfacesAndEnums.md.
Assets/
├─ Parameters/
│ ├─ Interfaces/
│ │ ├─ Enums
│ │ │ ├─ CurrencyType.cs (enum)
│ │ ├─ Structs
│ │ │ ├─ RewardStruct.cs (struct interface)
│ │ ├─ AssemblyInfo.cs
│ │ ├─ ParameterInterface.asmdef
│ │ ├─ ICurrencyInfo.cs (info interface)
│ │ ├─ IBuildingInfo.cs (info interface)
│ ├─ GeneratedCode/ (contains generated files that implement the defined interfaces)To add an interface, simply crete a new interface file under the Assets/Parameters/Interfaces/ folder or subfolder. Upon Unity compilation, code will automatically be generated author the interface as Scriptable Objects.
Example
- Create
IDragonInfo.csinAssets/Parameters/Interfaces. - Upon compilation, new files will be modified & added in
Assets/Parameters/GeneratedCode/. - Commit these changes.
To delete an interface, follow the following steps:
- Delete the interface file.
- If there are any references to that interface in game code, those will need to be resolved.
- Delete the associated valiation file under
Assets/Parameters/Validation/ - Compilation
- There will also be compilation errors in auto generated files in
Assets/Parameters/GeneratedCode/. - Upon this compilation error, the package will automatically disable any classes that implement these interfaces and allow compilation again.
- Upon compilation, the correct code will be auto-regenerated in the
Assets/Parameters/GeneratedCodefolder.
- There will also be compilation errors in auto generated files in
- Commit these changes.
Example
- If
ICurrencyInfo.csis no longer needed. - Delete it from
Assets/Parameters/Interfaces/ICurrencyInfo.cs. - Resolve game code that have compilation errors from this removal.
- This will result in errors in the auto generated code:
The type or namespace name 'ICurrencyInfo' could not be found
- The package will automatically disable code paths causing errors in auto generated code and allow compilation.
- New code in
Assets/Parameters/GeneratedCodewill be regenerated to reflect the correct changes. - Delete old
CurrencyInfoScriptable Objects.
Renaming an interface creates a new Scriptable Object of a different name therefore any previous data created with the original Scriptable Object class (with a unique guid) may be lost if the instructions below are not followed.
Example
- Lets say we'd like to rename
IAnimalInfotoICritterInfo. - Find the Scriptable Object class for the object to rename
AnimalInfoScriptableObject. It should be under theAssets/Parameters/GeneratedCode/Editor/ScriptableObjectsfolder. - Use your IDE and use the refactor functionality & rename the class to the desired name
CritterInfoScriptableObject. Your IDE should make all of the code changes across the board to change this. - Wait for Unity to recompile and click on a few of your Scriptable Objects to ensure they're displayed correctly in the inspector.
- Open the
IAnimalInfointerface file and do the same IDE refactor & rename toICritterInfo. - After a Unity recompliation, it will trigger another code generation to rename all generated files & variables correctly.
- Wait for Unity to recompile and click on a few of your Scriptable Objects to ensure they're displayed correctly in the inspector.
- Delete the newly created
CritterInfoValidatorin theAssets/Parameters/ValidationFolder. - Use your IDE to refactor & rename the
AnimalInfoValidatorclass toCritterInfoValidator
To add a new property to an existing interface:
- Add the new property to the interface.
- Compilation
- This change will result in compilation errors in the
Assets/Parameters/GeneratedCodefiles that implement the changed interface. - Upon this compilation error, the parameter system will automatically disable any classes that implement these interfaces and allow compilation again.
- Upon compilation the correct code will be auto-regenerated in the
Assets/Parameters/GeneratedCodefolder.
- This change will result in compilation errors in the
- Commit these changes.
- The property can now be utilized.
Example
- Add a new property
int RewardCount { get; }toIEventInfo. - This will result in two errors in the auto generated code:
EventInfoScriptableObject' does not implement interface member 'IEventInfo.RewardCountEventInfoFlatBuffer' does not implement interface member 'IEventInfo.RewardCount
- The parameter system will automatically disable these code paths and allow compilation.
- Upon compilation,
Assets/Parameters/GeneratedCodewill be re-generated with the correct implementation code.
- Delete the property from the interface.
- Any game specific compilation errors due to deleting of property needs to be resolved.
- Upon compilation, code in
Assets/Parameters/GeneratedCodewill be regenerated to reflect the updates. - Commit these changes.
⚠️ Note: This flow will be improved & simplified in a future release.
To rename a property, we must ensure that the serialized Scriptable Object saves the data under the correct new name. There is tooling provided to support this.
Example
- Lets say we'd like to rename this property
int InitialAmount { get; }toint StartingAmount { get; }inICurrencyInfo. - This works for both Scriptable Objects & Structs:
- For Scriptable Object
- Find the Scriptable Object file for the interface
Assets/Parameters/GeneratedCode/Editor/ScriptableObjects/CurrencyInfoScriptableObject.cs.
- Find the Scriptable Object file for the interface
- For Struct
- Find the Struct file for the interface
Assets/Parameters/GeneratedCode/Editor/Structs/CurrencyStruct.cs.cs.
- Find the Struct file for the interface
- For Scriptable Object
- Find the field that's mapped to that interface
int _initialAmount. - Utilize your IDE's "refactor" feature to rename the field. Add
FormerlySerializedAsto the field if your IDE doesn't automatically add that for you. It should look like this:[FormerlySerializedAs("_initialAmount")] public int _startingAmount;. - Go to the Parameters config window under
Pocket Gems->Config Panel. Press theRe-save All Scriptable Objects. This will re-save all Scriptable Objects under the new field. - Go to the
ICurrencyInfo.csand utilize your IDE's "refactor" feature to rename the property fromInitialAmounttoStartingAmount. This should rename all references to this interface across the code base. - Upon compilation, the correct code in
Assets/Parameters/GeneratedCodewill be generated. The[FormerlySerializedAs]that was added will be removed and no longer needed since fields have been re-serialized to the correct new name. - Commit
.assetand code changes.
⚠️ Note: This flow will be improved & simplified in a future release.
If two developers are making modifications to the parameters interfaces, this can result in conflict the auto-generated code.
- Resolve any game code merge conflicts.
- Resolve the conflict in any files under
Assets/Parameters/Interfaces/to intended outcome. - Code files in
Assets/Parameters/GeneratedCodewill be regenerated again once the game code is compiled. Therefore comment out any code within files in that folder to get the game to compile without concern for correctness. - Upon the game compiling, the correct code in
Assets/Parameters/GeneratedCodewill be auto generated.
On MacOS, the first time code generation occurs, a permissions error will occur.
You must go to your mac OS's System Preferences --> Security & Privacy --> Allow "flatc". After this, try generating with the menu item Pocket Gems --> Parameters --> Regenerate All Data & CSVs.
Interface extensions can be authored in the application in order to add helper methods to interface objects.
Example
public static class IEventCurrencyInfoExt
{
// Example Extension
public static int CalculateBonus(this IEventCurrencyInfo info)
{
return (int)(info.StartingAmount * info.EventBonusChance);
}
}
The auto generated scripts for Scriptable Objects located under Assets/Parameters/GeneratedCode/Editor/ScriptableObjects are internal & Editor only so that developers do not accidentally directly reference the class at runtime (the ParameterReference<> must be used instead).
In cases where game specific tooling is required to access, modify, or create Scriptable Objects directly, these internal classes can be accessed by exposing the assembly internals to a game specific editor assembly. Add [assembly: InternalsVisibleTo("ASSEMBLY.NAME.HERE")] attribute to Assets/Parameters/GeneratedCode/Editor/AssemblyInfo.cs. These changes will not be overridden and persist across code generation.
Example
// Assembly Info to expose internals of generated parameter code to game specific editor tools
// DO NOT EXPOSE INTERNALS TO RUNTIME CODE!
using System.Runtime.CompilerServices;
// Made up example:
// glam specific Editor tool that auto generates Scriptable Object content based on designer inputs
[assembly: InternalsVisibleTo("Glam.ContentCreation.Editor")]
// hash:[d6fe471fb74d0f566ac79bcb9c682415]