Here’s sample piece of code in C# (for Unity). It is a simple and generic status message system, and should give some idea of what kind of practices I use when writing code. The core of the system is MessageManager, messages are held in Message objects and at the bottom is MessageManagerDemo, a simple Unity component for demonstrating usage. If you want to test the system in action, copy the three classes to a Unity project, add MessageManagerDemo component to a gameobject, and press play.
MessageManager.cs
using UnityEngine; using System.Collections; using System.Collections.Generic; using System.Linq; namespace Lusmu.GenericTools { /// <summary> /// Message manager. /// /// Manages status messages, but does not render them on screen. /// One instance can be accessed statically through MessageManager.Main, /// or you can create separate instances with new MessageManager(). /// /// Add messages with Add(Message message), Add(string text) or /// Add(string title, string text, int priority, float lifeTime, Texture image) /// Get messages with GetTopmost() or GetMessage(int index) /// Remove messages with RemoveTopmost(), RemoveMessage(Message message) /// or RemoveById(int id) /// </summary> public class MessageManager { private static MessageManager instance; public static MessageManager Main { get { if (instance == null) { instance = new MessageManager (); } return instance; } } public event System.Action<Message> MessageAdded; public int MessageCount { get { return Messages.Count; } } public List<Message> Messages { get; set; } public int DefaultPriority { get; set; } public bool OrderMessagesByPriority { get; set; } private int _maxMessages = 1000; public int MaxMessages { get { return _maxMessages; } set { if (_maxMessages > 0) _maxMessages = value; } } private float _defaultLifeTime = 10; public float DefaultLifeTime { get { return _defaultLifeTime; } set { if (_defaultLifeTime > 0) _defaultLifeTime = value; } } public MessageManager () { Messages = new List<Message> (); } public MessageManager ( int maxMessages, float defaultLifeTime, int defaultPriority, bool orderMessagesByPriority) { this.MaxMessages = maxMessages; this.DefaultLifeTime = defaultLifeTime; this.DefaultPriority = defaultPriority; this.OrderMessagesByPriority = orderMessagesByPriority; } // ================================================================ #region public API /// <summary> /// Gets the message that should be displayed next. /// </summary> public Message GetTopmost() { return GetMessage(0); } /// <summary> /// Gets the message with specified index from the message queue. /// </summary> public Message GetMessage (int index) { if (index < Messages.Count) return Messages [index]; else return null; } /// <summary> /// Adds a message to its appropriate place in the message queue. /// </summary> public void AddMessage (string text) { AddMessage (string.Empty, text, DefaultPriority, DefaultLifeTime, null); } /// <summary> /// Adds a message to its appropriate place in the message queue. /// </summary> public void AddMessage (string title, string text, int priority, float lifeTime, Texture image) { Message message = new Message (title, text, priority, image, lifeTime); AddMessage (message); } /// <summary> /// Adds a message to its appropriate place in the message queue. /// </summary> public void AddMessage (Message message) { if (OrderMessagesByPriority) { int index = 0; for (index = 0; index < Messages.Count; index++) { if (message.priority > Messages [index].priority) break; } Messages.Insert (index, message); } else { Messages.Add (message); } if (Messages.Count > MaxMessages) { RemoveLowestOldest(); } OnAddMessage(message); } /// <summary> /// Removes the topmost message from the message queue. /// </summary> public void RemoveMessage (Message message) { Messages.Remove (message); } /// <summary> /// Removes the topmost message from the message queue. /// </summary> public void RemoveTopmost() { RemoveMessage(0); } /// <summary> /// Removes a message from message queue by its id number. /// </summary> public void RemoveById(int id) { Message message = Messages.FirstOrDefault(m => m.messageId == id); if (message != null) Messages.Remove(message); } /// <summary> /// Removes a message by its index in the message queue. /// </summary> public void RemoveMessage(int index) { if (index >= 0 && index < MessageCount) { Messages.RemoveAt(index); } } /// <summary> /// Removes all messages at or below the specified priority. /// </summary> public void RemoveByPriority(int priorityToRemove) { for (int i = Messages.Count - 1; i >= 0; i--) { if (Messages[i].priority <= priorityToRemove) { Messages.RemoveAt(i); } } } /// <summary> /// Removes the oldest message of the lowest priority. /// </summary> public void RemoveLowestOldest() { Message messageToRemove = Messages.OrderByDescending(m => m.priority).FirstOrDefault(); if (messageToRemove != null) { Messages.Remove(messageToRemove); } } /// <summary> /// Clears the message list. /// </summary> public void Clear() { Messages.Clear(); } #endregion void OnAddMessage(Message message) { // Only raise the event if message was added successfully if (MessageAdded != null && Messages.Contains(message)) { MessageAdded(message); } } } }
Message.cs
using UnityEngine; namespace Lusmu.GenericTools { /// <summary> /// A message. /// /// Can contain title, text and image. /// Also has priority, lifetime and timestamp. /// The message is equipped with a readonly messageId, /// that is based on static messageCount. /// </summary> public class Message { public string title = string.Empty; public string text; public Texture image = null; public int priority = 10; public System.DateTime timestamp; public readonly int messageId; public float lifeTime = 10; public static int messageCount { get; private set; } public Message (string text) : this (string.Empty, text, 10, null, 10) {} public Message (string title, string text, int priority) : this (title, text, priority, null, 10) {} public Message (string title, string text, int priority, Texture image, float lifeTime) { this.title = title; this.text = text; this.priority = priority; this.timestamp = System.DateTime.Now; this.image = image; this.lifeTime = lifeTime; messageId = messageCount; messageCount ++; } public override string ToString() { return messageId + " " + title + " " + text; } } }
MessageManagerDemo.cs
using UnityEngine; using Lusmu.GenericTools; public class MessageManagerDemo : MonoBehaviour { MessageManager manager; Message current; void Start() { manager = MessageManager.Main; manager.MessageAdded += OnAddMessage; } void OnDestroy() { // Remember to remove event listener if (manager != null) manager.MessageAdded -= OnAddMessage; } void Update () { if (current != null) { // Age the current message, // and remove if lifeTime spent current.lifeTime -= Time.deltaTime; if (current.lifeTime <= 0) { manager.RemoveTopmost(); current = manager.GetTopmost(); } } } void OnAddMessage(Message newMessage) { // When a message is added, show it unless it has a lower // priority then current if (current == null || newMessage.priority > current.priority) { current = newMessage; } } void OnGUI() { if (current != null) { // Draw current message text GUI.Label(new Rect(10, 10, Screen.width - 20, 30), current.text); // Button for removing the current, and showing next if (GUI.Button(new Rect(10, 100, 250, 50), "Next")) { manager.RemoveTopmost(); current = manager.GetTopmost(); } } // Show how many messages in queue if (manager.MessageCount > 1) { GUI.Label(new Rect(10, 50, Screen.width - 20, 30), (manager.MessageCount - 1) + " more messages in queue"); } // Button for adding a message with random message if (GUI.Button(new Rect(10, 170, 250, 50), "Add Random message")) { manager.AddMessage("A message with a number " + Random.Range(1, 999)); } } }