Skip to content
This repository has been archived by the owner on Aug 10, 2021. It is now read-only.

Game events and shared data realized using scriptable objects

License

Notifications You must be signed in to change notification settings

chark/unity-scriptable-objects

Repository files navigation

Unity Scriptable Objects

Unity 2019.4+ Actions Status

⚠️ We are deprecating/splitting up this repository. No new features will be added except for bug fixes. Further development will continue on:

This package provides utilities for implementing game architecture which is oriented around ScriptableObject assets and game events. Most of these ideas are based on Unite2017.

Features

  • Game events - allows transferring of data between scripts using ScriptableObject event assets.
  • Game event listeners - listener components which allow subscribing to various events.
  • Mutable objects - eases up sharing of mutable data via ScriptableObject assets.

Installation

This package can be installed by using the Unity Package Manager. To install this package, add the following to manifest.json:

{
  "dependencies": {
    "com.chark.unity-scriptable-objects": "https://github.com/chark/unity-scriptable-objects.git#upm"
  }
}

Samples

Example usage of game events and mutable objects can be found in Assets/Samples directory. These samples can also be imported via Unity Package Manager.

Documentation

Game events

Example usage of Game Event assets Example of a setup Game Event Listener component

Game events are scriptable objects (Right Click -> Create -> Game Events -> ...) which can be subscribed to via listener components (Add Component -> Game Events -> ...). Events allow to decouple scripts and instead rely on intermediate ScriptableObject assets for communication.

Available game events:

  • GameEvent - simple event which doesn't accept any arguments.
  • BoolGameEvent - event with a bool argument.
  • IntGameEvent - event with an int argument.
  • FloatGameEvent - event with a float argument.
  • StringGameEvent - event with a string argument.
  • Vector2GameEvent - event with a Vector2 argument.
  • Vector3GameEvent - event with a Vector3 argument.
  • TransformGameEvent - event with a Transform argument.
  • GameObjectGameEvent - event with a GameObject argument.

Mutable objects

Example usage of Mutable Objects

Mutable objects are used for storing and editing data on ScriptableObject assets at runtime. This data can be referenced, observed and used as a bridge by various scripts. Mutable objects are useful in situations where ScriptableObject data needs to be reset when the active scene changes.

Available mutable objects:

  • MutableBool - encapsulates a bool value.
  • MutableInt - encapsulates an int value.
  • MutableFloat - encapsulates a float value.
  • MutableString - encapsulates a string value.
  • MutableVector2 - encapsulates a Vector2 value.
  • MutableVector3 - encapsulates a Vector3 value.

Each mutable object has a ResetType property. This allows specifying when data in the mutable object should be reset. The following modes are available:

  • None - do not reset (default).
  • ActiveSceneChange - when the active (focused) scene changes.
  • SceneUnloaded - when the current scene gets unloaded.
  • SceneLoaded - when the scene is loaded.

Custom game events

In some situations, built-in game events might not suffice. For example if a custom type needs to be passed as an argument to the event. In this case, a custom game event can be created which would carry all the necessary data.

To create a custom game event, first create a regular UnityEvent:

[Serializable]
public class CustomEvent : UnityEvent<Custom>
{
}

After that is ready, create a game event by extending GameEvents.Generic.ArgumentGameEvent:

[CreateAssetMenu(fileName = "CustomEvent", menuName = "Game Events/Custom Event")]
public class CustomGameEvent : ArgumentGameEvent<Custom>
{
}

Finally, create a game event listener by extending GameEvents.Generic.ArgumentGameEventListener:

[AddComponentMenu("Game Events/Custom Game Event Listener")]
public class CustomGameEventListener : ArgumentGameEventListener<CustomGameEvent, CustomEvent, Custom>
{
}

, add a custom editor so that the event could be raised, and the listeners which reference the event get displayed in the inspector.

[CustomEditor(typeof(CustomGameEvent))]
public class GameObjectGameEventEditor : ArgumentGameEventEditor<CustomGameEvent, Custom>
{
    protected override Custom DrawArgumentField(Custom value)
    {
        var fieldValue = EditorGUILayout
            .ObjectField(value, typeof(Custom), true);

        return fieldValue as Custom;
    }
}

Custom mutable objects

In some cases, littering the script code with loads of MutableObject references can be inconvenient. To avoid this, a single object can be used which encompasses multiple fields.

To create a custom mutable object, extend MutableObjects.Generic.MutableObject and override ResetValues() method, e.g:

[CreateAssetMenu(fileName = "MutableCustom", menuName = "Mutable Objects/Mutable Custom")]
public class MutableCustom : MutableObject
{
    [SerializeField]
    private int health = default;

    [SerializeField]
    private int armor = default;

    [SerializeField]
    private int xp = default;

    public int Health { get; set; }

    public int Armor { get; set; }

    public int Xp { get; set; }

    // This will set property values when mutable object is enabled or if the values change in the
    // inspector.
    public override void ResetValues()
    {
        Health = health;
        Armor = armor;
        Xp = xp;
    }
}