In this part of the air hockey tutorial series, we will add a win and loose situation (game over screen) when we hit a certain amount of goals. This means that we will be working a lot with the Unity UI, so stop wasting time and let’s go straight to the video! 😉
This post contains all the code that’s been written in this YouTube video.
UiManager.cs
using UnityEngine;
public class UiManager : MonoBehaviour {
[Header("Canvas")]
public GameObject CanvasGame;
public GameObject CanvasRestart;
[Header("CanvasRestart")]
public GameObject WinTxt;
public GameObject LooseTxt;
[Header("Other")]
public AudioManager audioManager;
public ScoreScript scoreScript;
public PuckScript puckScript;
public PlayerMovement playerMovement;
public AiScript aiScript;
public void ShowRestartCanvas(bool didAiWin)
{
Time.timeScale = 0;
CanvasGame.SetActive(false);
CanvasRestart.SetActive(true);
if (didAiWin)
{
audioManager.PlayLostGame();
WinTxt.SetActive(false);
LooseTxt.SetActive(true);
}
else
{
audioManager.PlayWonGame();
WinTxt.SetActive(true);
LooseTxt.SetActive(false);
}
}
public void RestartGame()
{
Time.timeScale = 1;
CanvasGame.SetActive(true);
CanvasRestart.SetActive(false);
scoreScript.ResetScores();
puckScript.CenterPuck();
playerMovement.ResetPosition();
aiScript.ResetPosition();
}
}
AudioManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AudioManager : MonoBehaviour {
public AudioClip PuckCollision;
public AudioClip Goal;
public AudioClip LostGame;
public AudioClip WonGame;
private AudioSource audioSource;
private void Start()
{
audioSource = GetComponent<AudioSource>();
}
public void PlayPuckCollision()
{
audioSource.PlayOneShot(PuckCollision);
}
public void PlayGoal()
{
audioSource.PlayOneShot(Goal);
}
public void PlayLostGame()
{
audioSource.PlayOneShot(LostGame);
}
public void PlayWonGame()
{
audioSource.PlayOneShot(WonGame);
}
}
ScoreScript.cs
using UnityEngine;
using UnityEngine.UI;
public class ScoreScript : MonoBehaviour {
public enum Score
{
AiScore, PlayerScore
}
public Text AiScoreTxt, PlayerScoreTxt;
public UiManager uiManager;
public int MaxScore;
#region Scores
private int aiScore, playerScore;
private int AiScore
{
get { return aiScore; }
set
{
aiScore = value;
if (value == MaxScore)
uiManager.ShowRestartCanvas(true);
}
}
private int PlayerScore
{
get { return playerScore; }
set
{
playerScore = value;
if (value == MaxScore)
uiManager.ShowRestartCanvas(false);
}
}
#endregion
public void Increment(Score whichScore)
{
if (whichScore == Score.AiScore)
AiScoreTxt.text = (++AiScore).ToString();
else
PlayerScoreTxt.text = (++PlayerScore).ToString();
}
public void ResetScores()
{
AiScore = PlayerScore = 0;
AiScoreTxt.text = PlayerScoreTxt.text = "0";
}
}
PuckScript.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PuckScript : MonoBehaviour {
public ScoreScript ScoreScriptInstance;
public static bool WasGoal { get; private set; }
public float MaxSpeed;
public AudioManager audioManager;
private Rigidbody2D rb;
// Use this for initialization
void Start () {
rb = GetComponent<Rigidbody2D>();
WasGoal = false;
}
private void OnTriggerEnter2D(Collider2D other)
{
if (!WasGoal)
{
if (other.tag == "AiGoal")
{
ScoreScriptInstance.Increment(ScoreScript.Score.PlayerScore);
WasGoal = true;
audioManager.PlayGoal();
StartCoroutine(ResetPuck(false));
}
else if (other.tag == "PlayerGoal")
{
ScoreScriptInstance.Increment(ScoreScript.Score.AiScore);
WasGoal = true;
audioManager.PlayGoal();
StartCoroutine(ResetPuck(true));
}
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
audioManager.PlayPuckCollision();
}
private IEnumerator ResetPuck(bool didAiScore)
{
yield return new WaitForSecondsRealtime(1);
WasGoal = false;
rb.velocity = rb.position = new Vector2(0, 0);
if (didAiScore)
rb.position = new Vector2(0, -1);
else
rb.position = new Vector2(0, 1);
}
public void CenterPuck()
{
rb.position = new Vector2(0, 0);
}
private void FixedUpdate()
{
rb.velocity = Vector2.ClampMagnitude(rb.velocity, MaxSpeed);
}
}
PlayerMovement.cs
using UnityEngine;
public class PlayerMovement : MonoBehaviour {
bool wasJustClicked = true;
bool canMove;
Rigidbody2D rb;
Vector2 startingPosition;
public Transform BoundaryHolder;
Boundary playerBoundary;
Collider2D playerCollider;
// Use this for initialization
void Start () {
rb = GetComponent<Rigidbody2D>();
startingPosition = rb.position;
playerCollider = GetComponent<Collider2D>();
playerBoundary = new Boundary(BoundaryHolder.GetChild(0).position.y,
BoundaryHolder.GetChild(1).position.y,
BoundaryHolder.GetChild(2).position.x,
BoundaryHolder.GetChild(3).position.x);
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButton(0))
{
Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
if (wasJustClicked)
{
wasJustClicked = false;
if(playerCollider.OverlapPoint(mousePos))
{
canMove = true;
}
else
{
canMove = false;
}
}
if (canMove)
{
Vector2 clampedMousePos = new Vector2(Mathf.Clamp(mousePos.x, playerBoundary.Left,
playerBoundary.Right),
Mathf.Clamp(mousePos.y, playerBoundary.Down,
playerBoundary.Up));
rb.MovePosition(clampedMousePos);
}
}
else
{
wasJustClicked = true;
}
}
public void ResetPosition()
{
rb.position = startingPosition;
}
}
AiScript.cs
using UnityEngine;
public class AiScript : MonoBehaviour {
public float MaxMovementSpeed;
private Rigidbody2D rb;
private Vector2 startingPosition;
public Rigidbody2D Puck;
public Transform PlayerBoundaryHolder;
private Boundary playerBoundary;
public Transform PuckBoundaryHolder;
private Boundary puckBoundary;
private Vector2 targetPosition;
private bool isFirstTimeInOpponentsHalf = true;
private float offsetXFromTarget;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
startingPosition = rb.position;
playerBoundary = new Boundary(PlayerBoundaryHolder.GetChild(0).position.y,
PlayerBoundaryHolder.GetChild(1).position.y,
PlayerBoundaryHolder.GetChild(2).position.x,
PlayerBoundaryHolder.GetChild(3).position.x);
puckBoundary = new Boundary(PuckBoundaryHolder.GetChild(0).position.y,
PuckBoundaryHolder.GetChild(1).position.y,
PuckBoundaryHolder.GetChild(2).position.x,
PuckBoundaryHolder.GetChild(3).position.x);
}
private void FixedUpdate()
{
if (!PuckScript.WasGoal)
{
float movementSpeed;
if (Puck.position.y < puckBoundary.Down)
{
if (isFirstTimeInOpponentsHalf)
{
isFirstTimeInOpponentsHalf = false;
offsetXFromTarget = Random.Range(-1f, 1f);
}
movementSpeed = MaxMovementSpeed * Random.Range(0.1f, 0.3f);
targetPosition = new Vector2(Mathf.Clamp(Puck.position.x + offsetXFromTarget, playerBoundary.Left,
playerBoundary.Right),
startingPosition.y);
}
else
{
isFirstTimeInOpponentsHalf = true;
movementSpeed = Random.Range(MaxMovementSpeed * 0.4f, MaxMovementSpeed);
targetPosition = new Vector2(Mathf.Clamp(Puck.position.x, playerBoundary.Left,
playerBoundary.Right),
Mathf.Clamp(Puck.position.y, playerBoundary.Down,
playerBoundary.Up));
}
rb.MovePosition(Vector2.MoveTowards(rb.position, targetPosition,
movementSpeed * Time.fixedDeltaTime));
}
}
public void ResetPosition()
{
rb.position = startingPosition;
}
}

Thank you for your sharing. I am worried that I lack creative ideas. It is your article that makes me full of hope. Thank you. But, I have a question, can you help me?
I don’t think the title of your article matches the content lol. Just kidding, mainly because I had some doubts after reading the article. https://www.binance.com/fr-AF/register?ref=JHQQKNKN
Thank you for your sharing. I am worried that I lack creative ideas. It is your article that makes me full of hope. Thank you. But, I have a question, can you help me?
Your article helped me a lot, is there any more related content? Thanks! https://www.binance.com/bg/join?ref=V2H9AFPY
Your article helped me a lot, is there any more related content? Thanks!
Can you be more specific about the content of your article? After reading it, I still have some doubts. Hope you can help me.