I’m a novice making a 2D game. I’m trying to create a text notification simulation like the GIF from Football Manager here: https://i1.wp.com/superchartisland.com/wp-content/uploads/2020/01/cm2goal.gif?resize=620%2C465&ssl=1
What are some good approaches to scripting and presenting this in UI in C#/Unity?
Notifications like “Corner says the ref” will be hardcoded into the C# script. While I’m only writing 6 or so unique notifications for the prototype, eventually 100+ notifications, e.g. “Goal for ” etc will need to exist.
So far I’ve created an array to store string data types housing each of these unique notifications. The challenges I’ve hit so far are:
-
I can’t save my UI Text box as a Prefab and have it display text on game screen.
Thinking was to create a Text Prefab to store proper formatting, font, etc for the with no text, then populate text upon instantiation of the Prefab Text box clone (like a SpawnManager). Issue is the text does not display on Game screen when I make the Text a Prefab (I don’t know why?) This might be the solution… c# - Instantiated 2D text doesn't show up in Unity - Stack Overflow
-
The Text box GameObjects need to be destroyed after a few seconds once the player has read the text notification (to prevent overlapping text)
-
I want some text notifications to be unique and not repeated, e.g. “The game is over”, so this makes using RandomRange or random number generators a challenge.
Any thoughts or best practices are much appreciated! Below is the code so far.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SpawnManager : MonoBehaviour
{
// This is the spawn manager that creats text notifications for the performance simulation.
public GameObject[] textNotifications;
private float spawnLocationX = 6;
private float spawnLocationY = 51;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
// Generate fixed spawn position
Vector3 spawnPos = transform.position;
spawnPos = new Vector3(spawnLocationX, spawnLocationY, 0);
// Randomly generate text notification index
int notificationIndex = Random.Range(0, textNotifications.Length);
Instantiate(textNotifications[notificationIndex], spawnPos, textNotifications[notificationIndex].position???);
Debug.Log(textNotifications);
}
}
}
Tons of ways to do this, each with benefits and drawbacks that only you can evaluate in the context of your game.
The most straightforward way is to create a UI element that has content size fitter and text element (or elements) and a controller you call to make it appear, and some mechanism for making it go away, such as a timer, or a button, or some explicit call from the code.
I like to break my UI into separate scenes that I load with , so I would just have such a box in my UI scene, and a controller script to a) turn it off by default, b) make it come up and populate with data when the main program needs it, c) listen and hide it when your condition is met.
Thanks Kurt, I am trying to visualize this. Is the attached architecture a valid approach?
I am trying to implement this while also keeping the initial prototype simple.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
public void OnGUI()
{
// Pressing this button loads the additive scene
if (GUI.Button(new Rect(20, 30, 150, 30), "Other Scene Additive"))
{
SceneManager.LoadScene("Performance", LoadSceneMode.Additive);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class RandomNumberGenerator : MonoBehaviour
{
// This is a random number generator that generates numbers between 1 and 6
public GameObject notificationText;
public int TheNumber;
public void RandomGenerate ()
{
TheNumber = Random.Range(1, 7);
Debug.Log(TheNumber);
}
private string badEvent1 = "The pianist isn't feeling the rhythm";
private string badEvent2 = "The pianist is playing notes for the sake of it";
private string badEvent3 = "The pianist isn't listening to the band";
private string goodEvent1 = "The pianist is tickling the ivories!";
private string goodEvent2 = "The pianist plays a melodic interlude";
private string goodEvent3 = "The pianist's comping is tasty!";
public void PerformanceNotification ()
{
if (TheNumber == 1)
{
notificationText.GetComponent<Text>().text = "" + badEvent1;
}
else if (TheNumber == 2)
{
notificationText.GetComponent<Text>().text = "" + badEvent2;
}
else if (TheNumber == 3)
{
notificationText.GetComponent<Text>().text = "" + badEvent3;
}
else if (TheNumber == 4)
{
notificationText.GetComponent<Text>().text = "" + goodEvent1;
}
else if (TheNumber == 5)
{
notificationText.GetComponent<Text>().text = "" + goodEvent2;
}
else if (TheNumber == 6)
{
notificationText.GetComponent<Text>().text = "" + goodEvent3;
}
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
// A Space key press changes the performance notification shown on screen
// Up to six unique notifications are shown, half good, half bad
if (Input.GetKeyDown(KeyCode.Return))
{
Invoke("RandomGenerate", 0);
Invoke("PerformanceNotification", 0);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerController : MonoBehaviour
{
// This script will create a Text GameObject in the UI when the user
// presses the Space key. The Space key will also change the message shown on screen.
private enum UpDown { Down = -1, Start = 0, Up = 1 };
private Text text;
private UpDown textChanged = UpDown.Start;
void Awake()
{
// Load the Arial font from the Unity Resources folder.
Font arial;
arial = (Font)Resources.GetBuiltinResource(typeof(Font), "Arial.ttf");
// Create Canvas GameObject
GameObject canvasGO = new GameObject();
canvasGO.name = "NewCanvas";
canvasGO.AddComponent<Canvas>();
canvasGO.AddComponent<CanvasScaler>();
canvasGO.AddComponent<GraphicRaycaster>();
// Get canvas from the GameObject
Canvas canvas;
canvas = canvasGO.GetComponent<Canvas>();
canvas.renderMode = RenderMode.WorldSpace;
// Create the Text GameObject.
GameObject textNotificationBox = new GameObject();
textNotificationBox.transform.parent = canvasGO.transform;
textNotificationBox.AddComponent<Text>();
// Set Text component properties.
text = textNotificationBox.GetComponent<Text>();
text.font = arial;
text.text = "Press space key";
text.fontSize = 34;
text.alignment = TextAnchor.MiddleCenter;
// Provide Text position and size using RectTransform.
RectTransform rectTransform;
rectTransform = text.GetComponent<RectTransform>();
rectTransform.localPosition = new Vector3(0, 0, 0);
rectTransform.sizeDelta = new Vector2(600, 200);
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
// Press the space key to change the Text message.
if (Input.GetKeyDown(KeyCode.Space))
{
if (textChanged != UpDown.Down)
{
text.text = "Text changed";
textChanged = UpDown.Down;
}
else
{
text.text = "Text changed back";
textChanged = UpDown.Up;
}
}
}
}