KEMBAR78
Game Architecture with Scriptable Objects | PPTX
Ryan Hipple
Principal Engineer
Schell Games
Schell Games
VR / AR
Theme Parks
Transformational Games
Game Architecture with
Scriptable Objects
Engineering
Pillars
Modular
Editable
Debuggable
Modular
Systems not directly dependent on each other
Scenes are clean slates
Prefabs work on their own
Components!
Editable
Focus on data
Change the game without code
Emergent Design
Change at runtime
Debuggable
Test in isolation (modularity)
Debug views and features
Never fix a bug you do not understand
Engineering
Pillars
Modular
Editable
Debuggable
Scriptable Object Basics
Primer
Serializable Unity Class
Similar to MonoBehaviour, no Transform
Saved as .asset file
Simple Use Cases
Game config files
Inventory
Enemy stats
AudioCollection
Architecture
Singleton Benefits
Access anything from anywhere
Persistent State
Easy to understand
Consistent pattern
Easy to “plan”
*Lies
*
Singleton Problems
Rigid Connections / Not Modular
No Polymorphism
Not Testable
Dependency Nightmare
Single Instance!
Solutions
Reduce need for global managers
Inversion of Control
Example: Dependency Injection
Objects are given dependencies
Single responsibility principle
Modular Data
Enemy Prefab Example
EnemyManager.Instance.MoveSpeed?
Hard reference
Dependency on manager being loaded
EnemyConfig ScriptableObject reference?
Lumps all part of the enemy stats together
Limits extension / modularity
Better?
ScriptableObject Variables
[CreateAssetMenu]
public class FloatVariable : ScriptableObject
{
public float Value;
}
ScriptableObject Variables
Hitpoints
Damage Amounts
Timing Data
public class DumbEnemy : MonoBehaviour
{
public FloatVariable MaxHP;
public FloatVariable MoveSpeed;
}
Float Reference
[Serializable]
public class FloatReference
{
public bool UseConstant = true;
public float ConstantValue;
public FloatVariable Variable;
public float Value
{
get { return UseConstant ? ConstantValue :
Variable.Value; }
}
}
Float Variable
public class DumbEnemy : MonoBehaviour
{
public FloatVariable MaxHP;
public FloatVariable MoveSpeed;
}
public class DumbEnemy : MonoBehaviour
{
public FloatReference MaxHP;
public FloatReference MoveSpeed;
}
Float Variable Secrets
[CreateAssetMenu]
public class FloatVariable : ScriptableObject
{
public float Value;
}
PlayerHPPlayer
EnemyAI
HealthUI
Audio
System
Demo!
Event Architecture
Event Architecture
Modularize systems
Reuse in other projects
Isolates Prefabs
Optimize, only execute when needed
Highly debuggable
UnityEvent
*Serialized Function Call
*
UnityEvent Advantages
Editor hook-ups
Less code, fewer assumptions
Pass Arguments
Extend UnityEvent<T>
Static / dynamic arguments
UnityEvent Problems
Rigid bindings
Button hard references what responds to it
Limited serialization
Garbage allocation
Making Our Own Events
Data driven
Designer authorable
Debuggable
Making Our Own Events
[CreateAssetMenu]
public class GameEvent : ScriptableObject
{
private List<GameEventListener> listeners =
new List<GameEventListener>();
public void Raise()
{
for(int i = listeners.Count -1; i >= 0; i--)
listeners[i].OnEventRaised();
}
public void RegisterListener(GameEventListener listener) ...
public void UnregisterListener(GameEventListener listener) ...
}
Making Our Own Events
public class GameEventListener : MonoBehaviour
{
public GameEvent Event;
public UnityEvent Response;
private void OnEnable()
{ Event.RegisterListener(this); }
private void OnDisable()
{ Event.UnregisterListener(this); }
public void OnEventRaised()
{ Response.Invoke(); }
}
Demo!
Scriptable Objects vs ...
Singleton Manager Goals
Track all enemies in a scene
Understand player
Issue commands
Singleton Manager Problems
Race conditions
Rigid singleton
Only one
Runtime Sets
Keep track of a list of objects in the scene
Avoid race conditions
More flexible than Unity tags, singleton
Runtime Sets
public abstract class RuntimeSet<T> : ScriptableObject
{
public List<T> Items = new List<T>();
public void Add(T t)
{
if (!Items.Contains(t)) Items.Add(t);
}
public void Remove(T t)
{
if (Items.Contains(t)) Items.Remove(t);
}
}
Runtime Sets
Buildings placed in an RTS
Renderers for special effects
Items on a map
Demo!
Enums
Must change in code
Difficult to remove / reorder
Can’t hold additional data
Demo!
Asset Based Systems
Generic Systems
System is ScriptableObject Asset in project
Reference directly with inspector
No code lookup
No scene-only references
Like AudioMixer / AudioMixerGroup
Inventory
ScriptableObject Master List
ScriptableObject per item
Use different inventories in different scenes
InventoryPlayer
Inventory Example
Equip
Screen
NPC
Save
System
Demo!
Engineering
Pillars
Modular
Editable
Debuggable
Thank you!
Ryan Hipple
@roboryantron

Game Architecture with Scriptable Objects