Samstag, 26. Dezember 2020

Unity Tilemap Bitmap Font Printing Example

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
using UnityEditor;

/// <summary>
/// Class to print text onto a Tilemap by string, position and destiantion Tilemap based on a bitmap font asset. How to: Add an empty gameObject to the scene and call it for instance MyTilemapTextManager and then add this script to it. Move the gameObject into the prefabs Folder of your projects Assets subfolder.
/// </summary>
public class MyTilemapTextManagerScript : MonoBehaviour
{
    public static MyTilemapTextManagerScript Instance; // to refer the singleton instance of the class
    public Tilemap DestinationTilemap; // to provide a Tilemap surface to print on
    [System.Serializable]
    private struct TileItem
    {
        public int Index;
        public Tile Tile;
    }
    [System.Serializable]
    private struct FontItem
    {
        //public int Index;
        public string TileNamesStartWith;
        public string TilePaletteAssetPath;
        public List<TileItem> TileItems;
    }
    [SerializeField]
    private List<FontItem> _fontItems;
    private int _lastUsedFontIndex = 0;
    private void Awake()
    {
        DontDestroyOnLoad(gameObject); // keep the instance of the parent empty game object over several scenes after it was once initalized/instantiated
        if (Instance == null)
        {
            Instance = this; // make it resuable by referencing it statically using MyTilemapTextManagerScript.Instance.Print(...); Print is a public method defined in this class here!
        }
        else
        {
            Destroy(gameObject);
            return;
        }
        fillTileItemCollectionByLoadingFromAssets(); // load the Tiles unattended and fill the _tileItems collection
    }

    private void fillTileItemCollectionByLoadingFromAssets()
    {
        for (int i = 0; i < _fontItems.Count; i++)
        {
            FontItem fontItem = _fontItems[i];
            fontItem.TileItems = new List<TileItem>();
            var assets = AssetDatabase.FindAssets(fontItem.TileNamesStartWith, new string[] { fontItem.TilePaletteAssetPath }); // for instance "kromagrad_16x16_" and "Assets/TilePalettes"
            int indexCount = 0;
            foreach (var guid in assets)
            {
                Tile assetTile = AssetDatabase.LoadAssetAtPath<Tile>(AssetDatabase.GUIDToAssetPath(guid));
                fontItem.TileItems.Add(new TileItem { Index = indexCount++, Tile = assetTile });
            }
            if (indexCount == 0)
                Debug.Log($"Code 2012251527 - Unable to find any asset using the folder '{fontItem.TilePaletteAssetPath}' and the search string mask of '{fontItem.TileNamesStartWith}'!");
            // foreach (TileItem tileItem in _tileItems)
            // {
            //     print($"Tile Index='{tileItem.Index}', Tile Object='{tileItem.Tile}'");
            // }
            _fontItems[i] = fontItem;
        }
    }

    private void Start()
    {
        Print("hello world", new Vector3Int(-5, -4, 0)); // ensure to assign a Tilemap in the inspector to DestinationTilemap before starting it
        SelectFont("kromasky");
        Print("RVDH was here", new Vector3Int(-6, 4, 0)); // ensure to assign a Tilemap in the inspector to DestinationTilemap before starting it
    }


    public void SelectFont(string fontName)
    {
        int index = 0;
        foreach (FontItem fontItem in _fontItems)
        {
            if (fontItem.TileNamesStartWith.ToUpper().Contains(fontName.ToUpper()))
            {
                _lastUsedFontIndex = index;
                break;
            }
            index++;
        }
        if (index == _fontItems.Count)
        {
            _lastUsedFontIndex = 0;
            Debug.Log($"Code 2012252159 - Unable to find a font containing the name of '{fontName}'!");
        }
    }

    /// <summary>
    /// Print a text on the Tilemap at a certain position.
    /// </summary>
    /// <param name="text"></param>
    /// <param name="position">negative is left,bottom orientation; positiv is right,top orientation</param>
    /// <param name="destinationTilemap"></param>
    public void Print(string text, Vector3Int position, int lastUsedFontIndex = -1, Tilemap destinationTilemap = null)
    {
        if (destinationTilemap != null)
            DestinationTilemap = destinationTilemap;
        if (text == null || DestinationTilemap == null)
        {
            Debug.Log("Code 2012251531 - Unable to print a text when the text or the destination Tilemap is null!");
            return;
        }
        if (text != "")
        {
            if (lastUsedFontIndex > -1)
                _lastUsedFontIndex = lastUsedFontIndex;
            FontItem fontItem = _fontItems[_lastUsedFontIndex];
            text = text.ToUpper();
            for (int i = 0; i < text.Length; i++)
            {
                char ch = text[i];
                int chOffset = Convert.ToInt16(ch) - 33; // 'A' is ASCII code 65 ; 'A' is index 32 represented by asset 'kromagrad_16x16_32' ; the delta is therefore 65-32=33
                if (chOffset < 0)
                    DestinationTilemap.SetTile(position, null);
                else
                {
                    Tile tile = fontItem.TileItems[chOffset].Tile;
                    if (tile == null)
                        Debug.Log($"Code 2012251551 - Unable to index character '{ch}' by the use of an appropriate Tile!");
                    else
                        DestinationTilemap.SetTile(position, tile);
                }
                position.x++;
            }
        }
    }
}

0 Kommentare:

Kommentar posten

Abonnieren Kommentare zum Post [Atom]

<< Startseite