02 Floating Text

This example scene is located in Assets/Plugins/Weaver/Examples/02 Floating Text. It demonstrates Asset Injection again, but instead of a singleton-like approach with only one prefab it uses a different prefab for each kind of text. It also demonstrates the use of Object Pooling to efficiently reuse each text instance.

In this example we are making a system to manage various different kinds of text that can be floating in the scene:

  • Damage numbers so you know how much damage is dealt with each hit.
  • Status effect notifications like “stunned”, “frozen”, etc.
  • Speech bubbles for characters talking.

Those text types all have a few things in common:

  • They aren’t tied to a specific scene or object: they are global systems that should be shared by everything in the game. All fire damage shows the same color text, all speech uses the same font, and so on.
  • They all use the same general logic: spawn at a position, always face the camera, fade out after a time, use Object Pooling to maximise performance, etc.
  • But they can each have totally different appearances and extra behaviour added: damage numbers bounce around, status effects fade out gradually, speech bubbles make their text only appear one letter at a time, and so on.
  • This means they’re perfect candidates for prefabs assigned using asset injection.

The scripts in this example are split into two groups: the System Scripts contain the actual functionality of the floating text system and could potentially be reused in a real game while the Example Scripts are simply the bare minimum required to show the system in action for the purpose of the example.

System Scripts

  • These scripts are located in Assets/Plugins/Weaver/Examples/02 Floating Text/Code/Floating Text.
  • FloatingText is the base script which manages the lifetime of the text.
  • BillboardManager controls the rotation of the text objects to keep them constantly facing the camera (or whatever object the manager is attached to).
  • FloatingTextBounce, FloatingTextFade, and FloatingTextTypewriter are all "modifiers" that can be added alongside a FloatingText to alter its behaviour.
  • If you wish to use any of these scripts in your game, it is recommended that you make a new script, copy the contents into it, and change the namespace. Otherwise updating Weaver may alter that script and cause errors where your other code references it.

Example Scripts

  • These scripts are located in Assets/Plugins/Weaver/Examples/02 Floating Text/Code.
  • FollowMouse is a very simple script to represent a moving player object by having it follow the mouse cursor around.
  • DamageOnContact and StunOnContact are simple representations of a damage system and a status effect (debuff).
  • Conversation plays through a simple sequence of lines of text as if several characters were talking to each other.
  • TextManager provides a central location for accessing various the different kinds of used in this example.
    • It contains several private ObjectPool<FloatingText> fields which are injected by [AssetPool] attributes.
    • This means each field targets its own prefab just like with the previous Frame Rate example, but instead of getting that prefab directly assigned to it they each get constructed into an ObjectPool<FloatingText> that can create new instances of the prefab on demand and recycle them after they are used.
    • The name of the Text Manager folder and the prefabs it contains follow one of the Asset Naming rules to automatically match up with the script and field names when you first import Weaver.

Floating Text Mesh Pro

In order to avoid tieing the FloatingText system to a specific type of output, the base class is abstract with all the references to Unity's inbuilt TextMesh component are instead contained in the FloatingTextUnity child class. This is known as the Facade Pattern which allows you to easily use another text system such as Text Mesh Pro by writing a script like the one below. Any code that expects a FloatingText would be able to use a FloatingTextUnity or a FloatingTextMeshPro without needing to know or care which system was used.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Kybernetik;

namespace Weaver.Examples
{
    public sealed class FloatingTextMeshPro : FloatingText
    {
        /************************************************************************************************************************/

        /// <summary>The component used to display the actual text.</summary>
        [SerializeField]
        private TMPro.TextMeshPro _TextMesh;

        /// <summary>The component used to display the actual text.</summary>
        public TMPro.TextMeshPro TextMesh => _TextMesh;
        
        /************************************************************************************************************************/

        /// <summary>The text string currently being shown.</summary>
        public override string Text
        {
            get => _TextMesh.text;
            set => _TextMesh.text = value;
        }
        
        /************************************************************************************************************************/

        /// <summary>The height of the text in world-space.</summary>
        public override float Size
        {
            get => _TextMesh.fontSize * 0.1f;
            set => _TextMesh.fontSize = value * 10;
        }
        
        /************************************************************************************************************************/

        /// <summary>The <see cref="UnityEngine.Color"/> of the text.</summary>
        public override Color Color
        {
            get => _TextMesh.color;
            set => _TextMesh.color = value;
        }
        
        /************************************************************************************************************************/

        /// <summary>
        /// Called by Unity when this component is first added (in Edit Mode) or the "Reset" function is used.
        /// </summary>
        public override void Reset()
        {
            base.Reset();
            _TextMesh = gameObject.GetOrAddComponent<TMPro.TextMeshPro>();
        }

        /************************************************************************************************************************/
    }
}