This part adds logic for the PC and keep track of things such as health, dying. I also add functionality for invisibility (that have already partly added in Guard class). I also add HUD using the new GUI system to show health and energy (that is used to maintain invisibility).
Previous parts:
Lets start with setting up HUD. We need Canvas (GameObject -> UI -> Canvas), couple Images (GameObject -> UI – Image) and Sliders (GameObject -> UI -> Slider). I add canvas under GameManager. I first created background for Invisibility bar and Slider for displaying the energy left. You can drag then object where you want them to be, After that was ready, I copied objects (and modified the parts to make it fit to another corner and have correct texts.)

(Unity UI tutorial is a good starting point to understand how the UI system works.)
As I want to health and invisibility bars to be at the bottom corners, I need to anchor them to those corners.

Slider object needs some fine-tuning also.



Copy the Energy/Invisibility bar and fine tune it to health bar.
Now we have HUD ready to be used. I need to pass pointers to the PC object to sliders so that they actually shows the values they are intended to so. So I add functionality to GameAgents.cs
GameAgents.cs
public class GameAgents : MonoBehaviour { public Slider energyBar; public Slider healthBar;
and then the end of Awake():
PlayerLogic pc = player.GetComponent(); pc.energyBar = energyBar; pc.healthBar = healthBar;
Drag-and-drop sliders from the HUD to energyBar and healthBar. And next, it is time to revise PlayerLogic and add functionality there.
using UnityEngine; using System.Collections; using UnityEngine.UI; public class PlayerLogic : MonoBehaviour, CharacterInterface { // Sliders for displaying energy and health public Slider energyBar; public Slider healthBar; // how much energy maintaining invisibility costs public float invisibilityCostInterval = 1.0f; public int invisibilityCost = 5; // Delay before start screen is loaded after dying public float startScreenDelay = 2.0f; public int startEnergy = 0; public int startHealth = 100; public const int MAX_ENERGY = 100; public const int MAX_HEALTH = 100; // definitions for saving and loading dats public const string HEALTH_KEY = "h"; public const string ENERGY_KEY = "e"; public const string CURRENT_LEVEL_KEY = "c"; public const string LAST_DOOR_KEY = "d"; private int health; private int energy; private bool invisible; // effects for later use. Grayscale effect is used when // the PC dyes and Glow and AudioLowPassFilter are use // when PC is invisible. Camera should have these components // attached. private GrayscaleEffect grayscaleEffect; private GlowEffect glowEffect; private AudioLowPassFilter audioLowpassFilter; void Awake () { invisible = false; glowEffect = GetComponentInChildren(); if (!glowEffect) { Debug.LogError("PlayerLogic.Awake(): Camera does not have GlowEffect component"); } else { glowEffect.enabled = false; } grayscaleEffect = GetComponentInChildren(); if (!grayscaleEffect) { Debug.LogError("PlayerLogic.Awake(): Camera does not have GrayscaleEffect component"); } else { grayscaleEffect.enabled = false; } audioLowpassFilter = GetComponentInChildren(); if (!audioLowpassFilter) { Debug.LogError("PlayerLogic.Awake(): Camera does not have AudioLowpassFilter component"); } else { audioLowpassFilter.enabled = false; } ReadSave(); } void Update () { // display in HUD the current values of energy and health energyBar.value = energy; healthBar.value = health; if (health <= 0) { // if dead do nothing... return; } // turning invisible with Fire1 or "o" if (Input.GetButton("Fire1") || Input.GetKey("o")) { // invisibility if (!IsInvoking()) { // Invisibility started. Enabling effects // and start tick reducing energy glowEffect.enabled = true; audioLowpassFilter.enabled = true; InvokeRepeating("MaintaingInvisibility", 0.0f, invisibilityCostInterval); } } else { // not invisible if (IsInvoking()) { // but the PC was invisible in the last frame // disabling the effects glowEffect.enabled = false; audioLowpassFilter.enabled = false; CancelInvoke(); // and setting internal state to visible invisible = false; } } } public static void DeleteSave() { // Data is store in PlayerPrefs. Deleting the data PlayerPrefs.DeleteKey(CURRENT_LEVEL_KEY); PlayerPrefs.DeleteKey(ENERGY_KEY); PlayerPrefs.DeleteKey(HEALTH_KEY); PlayerPrefs.DeleteKey(LAST_DOOR_KEY); } public void ReadSave () { // reading the saved data int e = PlayerPrefs.GetInt(ENERGY_KEY); int h = PlayerPrefs.GetInt(HEALTH_KEY); // if health is zero, the PC just died and // and we go back to max if (h > 0) { energy = e; health = h; } else { energy = startEnergy; health = startHealth; } } bool CharacterInterface.IsInvisible () { return invisible; } void CharacterInterface.ReceiveDamage (int amount) { if (amount < 0) { Debug.LogError("PlayerLogic.RecieveDamage() called with negative damage. Ignoring"); return; } health -= amount; if (health <= 0) { health = 0; grayscaleEffect.enabled = true; Invoke("StartScreen", startScreenDelay); } } void CharacterInterface.PowerUp (int _energy, int _health) { if (_energy < 0 || _health < 0) { return; } energy += _energy; if (energy > MAX_ENERGY) { energy = MAX_ENERGY; } health += _health; if (health > MAX_HEALTH) { health = MAX_HEALTH; } } bool CharacterInterface.CanUseHealth() { // return if the PC needs health from Powerup. If not // the power-up won't active if ( health < MAX_HEALTH) { return true; } else { return false; } } bool CharacterInterface.CanUseEnergy() { if ( energy < MAX_ENERGY) { return true; } else { return false; } } void CharacterInterface.Save(string levelName, string door) { Debug.Log ("PlayerLogic.Save(" + levelName + ")"); PlayerPrefs.SetInt(ENERGY_KEY, energy); PlayerPrefs.SetInt(HEALTH_KEY, health); PlayerPrefs.SetString(CURRENT_LEVEL_KEY, levelName); PlayerPrefs.SetString(LAST_DOOR_KEY, door); } public void Save () { Debug.Log ("PlayerLogic.Save() called."); ((CharacterInterface)this).Save (Application.loadedLevelName, ""); } void Start() { Transform startPosition = null; string door = PlayerPrefs.GetString(LAST_DOOR_KEY); if (door != "") { GameObject doorObj = GameObject.Find(door); if (doorObj) { startPosition = doorObj.transform.Find("spawn"); if(startPosition == null) { Debug.LogError ("PlayerLogic.Start(): " + doorObj.name + " has now spawn point"); } } } if(startPosition == null) { GameObject ps = GameObject.FindWithTag("PlayerStartPoint"); if (startPosition) { startPosition = ps.transform; } else { Debug.LogError("PlayerLogic.Start(): level has not StartPosition waypoint"); } } Debug.Log("PlayerLogic.OnStart(): spawning the PC at " + startPosition.name ); transform.rotation = startPosition.transform.rotation; transform.position = startPosition.position; CancelInvoke(); invisible = false; glowEffect.enabled = false; audioLowpassFilter.enabled = false; } private void MaintaingInvisibility () { // ticks while invisibility is maintained // reduce energy and quits if energy runs out energy = energy - invisibilityCost; invisible = true; if (energy < 0) { energy = 0; invisible = false; glowEffect.enabled = false; audioLowpassFilter.enabled = false; CancelInvoke(); } } private void StartScreen () { Application.LoadLevel(0); } }