How to Create a Twitch Chat Game with Unity

Learn to integrate the Twitch Chat API into your Unity game, so viewers can interact with the game during streaming. By Harrison Hutcheon.

4.7 (3) · 3 Reviews

Download materials
Save for later
Share
You are currently viewing page 5 of 6 of this article. Click here to view the first page.

Game Over and New Game Conditions

The game isn't quite ready to play yet. You still need to add some game logic, like what should happen when the battle is over?

Battle needs its own logic for when you consider a game to be over, as well as instructions for what to do when that happens.

It also needs instructions on how to start a new game, such as resetting the health of both creatures. You'll start by validating the game is actually over.

Game Over Check

Before executing a Game Over Action, you need a script that checks if the game has reached game over conditions. For GameManager to check these conditions no matter what game it's managing, you need to create an interface, so GameManager always knows what to expect.

In RW/Scripts/Common, create a new script called IGameOverCheck. Open it and replace the default code with:

public interface IGameOverCheck
{
      bool IsGameOver(GameManager gm);
}

This interface defines one method that takes a GameManager as an argument and returns a boolean.

Any script implementing this interface must have an IsGameOver that returns true if the game over conditions are met. Even though it's small, interfaces like this can be a handy way of defining a type for a class without forcing it to inherit from a parent class.

Now all GameManager has to do is look for an IGameOverCheck and call IsGameOver to know whether or not to end the game. This also means any script using IGameOverCheck can be as simple or as complex as needed.

Time to create a Game Over Check specific to Battle. Create a script in RW/Scripts/Battle called BattleGameOverCheck and open it.

BattleGameOverCheck uses the interface you created and defines the Battle scene's game over conditions.

The battle should end when one of the...Backpack...Demons...Badmons...

The battle should end when one of the Legally Distinct Pokémon-like Battle Creatures reaches 0 HP. :]

In BattleGameOverCheck, implement IGameOverCheck as below:

using UnityEngine.UI; 
public class BattleGameOverCheck : MonoBehaviour, IGameOverCheck
{
    public Slider playerHealth; 
    public Slider opponentHealth; 

    public bool IsGameOver(GameManager gm)
    {
        if (playerHealth.value <= 0 || opponentHealth.value <= 0) 
        {
            return true; 
        }
        return false; 
    }
}

This Game Over Check looks at two different Sliders, representing the player's and opponent's health. In IsGameOver, it returns true if either slider's value is less than or equal to 0. Otherwise, it returns false.

Game Over Action

Just like IGameOverCheck, you need a common definition of what the GameManager should do if a game is over.

In RW/Scripts/Common, create a script called IGameOverAction.

public interface IGameOverAction
{
    void Execute(GameManager gm);
}

IGameOverAction defines one method, Execute, that takes a GameManager.

Back in RW/Scripts/Battle, create a script called BattleGameOverAction:

public class BattleGameOverAction : MonoBehaviour, IGameOverAction
{
    public GameObject gameOverPanel; 

    public void Execute(GameManager gm)
    {
        gameOverPanel.SetActive(true); 
    }
}

BattleGameOverAction implements IGameOverAction and has a public reference to the GameOverPanel UI element. Execute in BattleGameOverAction activates the GameOverPanel.

While GameManager now knows how to end a game, you need to tell it how to start over.

New Game Action

Like the Game Over Action, you need to define what GameManager needs to prepare the scene for a new game.

In RW/Scripts/Common, create a script called INewGameAction, which is pretty much identical to IGameOverAction:

public interface INewGameAction
{
    void Execute(GameManager gm);
}

When a new Battle game starts, both health bars should reset and the game over panel should hide.

Now, in RW/Scripts/Battle, create a script called BattleNewGameAction.

BattleNewGameAction implements INewGameAction, as shown below:

using UnityEngine.UI;

public class BattleNewGameAction : MonoBehaviour, INewGameAction 
{
    public Slider playerHealth; 
    public Slider opponentHealth; 
    public GameObject gameOverPanel; 

    public void Execute(GameManager gm)
    {
        playerHealth.value = 100; 
        opponentHealth.value = 100; 
        gameOverPanel.SetActive(false); 
    }
}

It has public variables for both health sliders and the game over panel. In Execute, set the both health bar values to 100 and deactivate the game over panel.

Back in the editor, add BattleGameOverCheck, BattleGameOverAction and BattleNewGameAction to the Managers/GameManager object and set their fields to the appropriate GameObjects:

In Battle Game Over Action set Game Over Panel to UI/BattleCanvas/GameOverPanel.

Then, in Battle Game Over Check set:

  • Player Health to UI/BattleCanvas/Player/PlayerHealth.
  • Opponent Health to UI/BattleCanvas/Opponent/OpponentHealth.

In Battle New Game Action set:

  • Player Health to UI/BattleCanvas/Player/PlayerHealth.
  • Opponent Health to UI/BattleCanvas/Opponent/OpponentHealth.

Finally, in Battle New Game Action set Game Over Panel to UI/BattleCanvas/GameOverPanel.

The setup for Game Manager's Battle Game Over Action, Battle Game Over Check and Battle New Game Action components.

Revisiting the GameManager

Currently, GameManager is configured to handle incoming commands and run corresponding actions. But you need to expand it to use the last three interfaces you created.

Open RW/Scripts/Common/GameManager.cs. Add these private fields above Start:

private IGameOverCheck gameOverCheck; 
private IGameOverAction gameOverAction; 
private INewGameAction newGameAction; 

In Start, use GetComponent to assign these variables to scripts attached to this GameObject, as shown below:

gameOverCheck = GetComponent<IGameOverCheck>(); 
gameOverAction = GetComponent<IGameOverAction>(); 
newGameAction = GetComponent<INewGameAction>(); 

Then, in ResetGame, call newGameAction.Execute before setting the game state, passing this as a reference to the GameManager:

public void ResetGame()
{
    if (gameState != GameState.Playing)
    {
        newGameAction.Execute(this); // 1
        SetGameState(GameState.Playing);
    }
}

In EndGame, call gameOverAction.Execute before setting the game state. Pass the keyword this as a reference to the GameManager:

public void EndGame()
{
    if (gameState != GameState.GameOver)
    {
        gameOverAction.Execute(this);
        SetGameState(GameState.GameOver);
    }
}

Update FixedUpdate as shown below:

void FixedUpdate()
{
    if (gameState == GameState.Playing)
    {
        if (gameOverCheck == null || !gameOverCheck.IsGameOver(this))
        {
            ChatMessage recentMessage = chat != null ? chat.ReadChat() : null;
            IGameCommand command = recentMessage != null ? 
                                    CommandIsValid(recentMessage) : null;
            if (command != null)
            {
                ChatCommand newCommand = new ChatCommand(recentMessage, command);
                newCommands.Add(newCommand);
            }

            ProcessCommands();
        }
        else if (gameOverCheck.IsGameOver(this))
        {
            EndGame();
        }
    }
}

FixedUpdate now checks if gameOverCheck is null, or if gameOverCheck.IsGameOver returns false. This prevents new commands from storing and processing if the game is currently over.

Now, it also includes a check if gameOverCheck.IsGameOver returns true. If so, it calls EndGame.

Go back into Unity. To trigger BattleNewGameAction, you need to link GameManager.ResetGame to UI/BattleCanvas/GameOverPanel/NewGameButton.

Select NewGameButton and find the On Click trigger list on the Button component. Add a new trigger. Drag GameManager into the empty object slot and select GameManager.ResetGame in the dropdown list.

Setup for the NewGameButton's OnClick trigger.

That's it! Give it a try with some friends!

A GIF showing the Battle Scene in action