CustomAssets
Askowl Custom Assets
CustomAssetTranscript.cs
1 //- Copyright 2018 (C) paul@marrington.net http://www.askowl.net/unity-packages
2 //- Custom assets are an extension to the unity ScriptableObject classes to provide containers for logic and data isolated from the interactive I/O elements of a game.
3 //- So, what are the benefits [[https://docs.google.com/presentation/d/1DaXU2w91cnFZjshvLlB_lQKfEJ1I_ewFkK_Gqs09XdE/edit#slide=id.p]] [[click slide]]
4 //- I will be showing the refactoring of a game object into custom asset managers later in this presentation [[click slide]]
5 //- By keeping all data used by multiple components in individual custom assets, changes and interactions are limited to loaded managers [[click slide]]
6 //- This makes component and multiple component testing extremely simple [[click slide]]
7 //- Changes in data custom assets raise events. These can be used to communicate between manager as well as driving visual changes [[click slide]]
8 //- By setting a custom asset as persistent it can be used to keep data between runs - such as the player level or location on a map [[click slide]]
9 //- Custom assets can be made to change GameObject Components directly using Custom Asset Drivers. When the component does not expose the needed public variable, use one of he provided connectors [[click slide]]
10 //- There are drivers for triggers and all basic data forms - from integer to string. There is a named version for Animator components [[switch to Rider Example/Example.cs]]
11 
12 //- Now we will refactor a real game manager from a 2D game. The original code is to the left while we will build up the custom asset managers on the right
13 
14 #if !ExcludeAskowlTests
15 using System;
16 using CustomAsset;
17 using CustomAsset.Mutable;
18 using UnityEngine;
20 
21 // ReSharper disable MissingXmlDoc
22 
23 namespace Askowl.Transcripts {
24  //- Because a custom asset exists on disk as part of the project, we need to create a concrete form. We could have more than one for a multi-player game
25  [CreateAssetMenu(menuName = "Managers/Player Death"), Serializable]
26  public class PlayerDeathManager : Manager {
27  //- We load up all the data custom assets in the inspector. All of these are mutable assets that change during the course of the game.
28  [SerializeField] private Float health = default;
29  [SerializeField] private Integer coins = default;
30  [SerializeField] private Integer lives = default;
31  [SerializeField] private Integer scene = default;
32  //- This is the only data custom asset that could be CustomAsset.Constant.Integer, but we may want to change it based on user level. It could also be persistent.
33  [SerializeField] private Integer maximumLives = default;
34  //- These two are sent with a GameObjectConnector MonoBehaviour. Add it to the relevant game object by selecting it and using the menu option Component/CustomAssets/GameObject Connnector
35  [SerializeField] private GameObject player = default;
36  [SerializeField] private GameObject checkpoint = default;
37 
38  //- Initialise is called for a custom asset on the first FixedUpdate after the asset is enabled (OnEnable)
39  protected override void Initialise() => health.Emitter.Listen(OnHealthChange, once: false);
40 
41  //- Called every time health changes. Not that frequently in the scheme of things.
42  private void OnHealthChange(Emitter emitter) {
43  if (health <= 0) KillPlayer();
44  }
45 
46  //- In this game the player goes back to the last checkpoint if they have lives left.
47  private void KillPlayer() {
48  if (lives <= 1) {
49  RestartGame();
50  } else {
51  SendPlayerToCheckpoint();
52  }
53  }
54 
55  private void RestartGame() {
56  lives.Value = maximumLives;
57  coins.Value = 0;
58  //- THe SceneManager shown below interfaces the scene to Unity management
59  scene.Value = 0;
60  }
61 
62  //- The custom assets are filled with the GameObject containing the custom asset connector
63  private void SendPlayerToCheckpoint() => player.Value.transform.position = checkpoint.Value.transform.position;
64  }
65 
66  //- The scene manager would normally be in separate file
67  [CreateAssetMenu(menuName = "Managers/Scene"), Serializable] public class SceneManager : Manager {
68  [SerializeField] private Integer scene = default;
69 
70  //- Action triggered when scene changes
71  protected override void Initialise() => scene.Emitter.Listen(OnSceneChange, once: false);
72 
73  //- That connects to Unity to change the display. This could be a string if you were to change scenes by name - my preferred option.
74  private void OnSceneChange(Emitter emitter) =>
75  UnityEngine.SceneManagement.SceneManager.LoadScene(sceneBuildIndex: scene);
76 
77  //- MoveToNextLevel() can be replaced by level.Value += 1
78  //- AddCoin is replaced by coin.Value += 1
79  //- OnLivesChanged and OnCoinsChanges are replaced by lives.Subscribe() and coins.Subscribe()
80  //- Now we can delete the original GameManager.cs
81  //- and write a few tests :)
82  }
83 }
84 #endif
virtual T Value
For safe(ish) access to the contents field
//#TBD#//
Definition: Manager.cs:8
override UnityEngine.GameObject Value
For safe(ish) access to the contents field
Definition: GameObject.cs:12
Float CustomAsset contains a float value which can be connected directly to OnValueChange callbacks i...
Definition: GameObject.cs:10
Float CustomAsset contains a float value which can be connected directly to OnValueChange callbacks i...
Definition: Mutable/Float.cs:9