GameData Version1
GameData - Version 1
Important Concepts: 1. Singleton Pattern - One and only one component instance exists - Globally accessible variable - Component Persistence between Scene-change 2. DontDestroyOnLoad( ) - Persistence 3. Static Variables - Globally accessible variable 4. Component Communication via Methods
In the game we'll create a custom component to store game-data that is persisted throughout the gameplay session so that we can keep track of score, lives, health, etc. This is the first version for class: GameData, we'll add more complexity to this class definition throughout the course.
Singleton Pattern:
GameData will use the Singleton Programming Pattern, this means that we'll add code to insure that there is always one and only one of this gameObject in existence throughout the lifetime a gamePlay session.
Awake( ) - GameData will be initialized in the Awake( ) event-handler method, so that it's created before other gameObjects that may need to access the object during their initialization in the Start( ) event-handler.
GameObject Persistence: DontDestroyOnLoad( )
In order to insure that the GameData Component exists throughout the entire gameplay session, it's necessary to insure that the gameObject is not destroyed when changing scenes. So, the code below shows the use of the method: DontDestroyOnLoad( someGameObject ).
Test to determine existence of any other GameObject Instances:
When initializing GameData in Awake( ) we need logic to test to determine if a GameData object already exits in a scene: The code below checks to see if the instanceRef variable already points to an active GameData object, if not, then this variable should point to: this
(the object currently executing the code ). Otherwise a GameData object already exists and the one executing the code should destroy itself!
if( instanceRef == null) //this code hasn't been executed before
{
instanceRef = this; //point to object instance currently executing this code
DontDestroyOnLoad(this.gameObject); //don't destroy the gameObject this is attached to
}
GameData instanceRef;
is a the variable used to implement the Singleton Programming pattern for GameData.cs. A static variable belongs to the class, rather than to an object instance of a class, there can only be one instance of a static variable during a program's execution.
Typical class-defined variables, each time an object is created from the class definition, each object gets it's own unique instance of each variable.
Example: a class static variable can be used to keep track of the number of object instances currently instantiated in an executing program. public static numZombies;
This variable could be incremented each time a zombie object is created and decremented each time a zombie object is destroyed during a program's execution, so that a count of the number of zombies could be displayed during the program.
The data-type of the static variable instanceRef is GameData. So it's a variable that can 'point' to an instance of an object of the GameData class. While this seems a bit odd, think of it as you wearing a name-tag...it provides other gameObjects with easy access to the one GameData object in the game.
public static GameData instanceRef; //null //variable that can point to a GameData object
This script will be attached to the GameManager in the first game Scene and will be persisted throughout the game since it uses the singleton design pattern.
Add GameData script to an Empty GameObject: named: GameManager in your starting scene, so it will be executed as a singleton and shows up as 'DontDestroyOnLoad' in the Hierarchy when the game is played.
DontDestroyOnLoad - in Play-mode
Event-Driven Component Communication via public Methods
Inter-Component Communication: When the Player gameObject has a collision with a gameObject that has an attached PickUp component, and a Collider2D Component with Trigger set to true: this can be considered the initializing event in a chain of events that need to be communicated with other components on other GameObjects, so that corresponding components are notified that the GameState has changed, so they can be updated to reflect that change. For example, the Score and Health displays should be updated. Requirement: PlayerController component must notify GameData component that Score or Health values have changed: Solution: When PlayerController logic has determined that a GameState changing event has occurred, it will execute a public GameData Method, so that GameData values for Score or Health are updated. We'll also discuss how other GameObjects can be notified to update, when a GameState changing-event occurs. See example below: How to use GameData Singleton To use the singleton reference in another class use the following syntax, for example, when calling the Add method from the PlayerController script:
Example of using GameData singleton in PlayerController.cs
// Inside PlayerController.cs
// Inside event-handler: OnTriggerEnter2D( )
// After PlayerController logic has deteremined
//that the GameData.score must be updated
GameData.instanceRef.Add( item.value );
GameData Class Definition - Version1
modified 4/10/2020
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Singleton Object to store all GameData
/// Is not destroyed when changing scenes
/// </summary>
public class GameData : MonoBehaviour
{
public static GameData instanceRef; //null //variable that can point to a GameData object
private int score;
private int health;
//TODO - Add properties: Score, Health
// Awake is called before Start() is called on any GameObject
// Other objects have dependencies on this object so it must be created first
void Awake()
{
if( instanceRef == null) //this code hasn't been executed before
{
instanceRef = this; //point to object instance currently executing this code
DontDestroyOnLoad(this.gameObject); //don't destroy the gameObject this is attached to
}
else //this object is not the first, it's an imposter that must be destroyed
{
DestroyImmediate(this.gameObject);
Debug.Log("Destroy GameData Imposter");
}
//initialize after destroying imposters
score = 0;
health = 100;
} //end Awake
//will be executed in PlayerController when colliding with a collectible
public void Add( int value)
{
score += value;
Debug.Log("Score updated: " + score); //display score in console
}
public void TakeDamage( int value)
{
health -= value;
Debug.Log("health updated: " + health); //display health in console
if( health <= 0)
{
Debug.Log("Health less than 0"); //display health in console
}
}
//called when restarting the miniGame
public void ResetGameData()
{
score = 0;
health = 100;
}
}//end class GameData
Resets Score and Health to correct initial values. Public, so it can be executed from MiniGameManager Script.
Last updated
Was this helpful?