Item Description System - HelpMeGame/Sniffle6-SOInventory-Changes GitHub Wiki

-- Developed by HelpMeGame --

Note: Some of this might not work right away. If you encounter a bug, please join the discord server and ping me for help.

A tool tip is a piece of UI that pops up to describe an item. We will be implementing this to show the tool tip when an item is hovered over in an UserInterface. To start, we need a UI Element. I did this in the form of a prefab. That way, we can delete it, edit it, and spawn it on any UserInterface. First, we need a new class. I just named this class Description. I added some code to handle the text changing, and this is what I ended with:

using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class Description : MonoBehaviour
{
    public TextMeshProUGUI name, description, buffs;
    public Image item;

    public static Description Instance;

    private void Start()
    {
        if (Instance == null)
            Instance = this;
        else
        {
            Debug.LogError("Error: There are multiple descriptions present, deleting old one");
            Destroy(Instance);
            Instance = this;
        }
    }

    private void OnDisable()
    {
        Instance = null;
    }

    public void AssignValues(string _name, string _description, string _buffs, Sprite _itemSprite)
    {
        name.text = _name;
        description.text = _description;
        buffs.text = _buffs;
        item.sprite = _itemSprite;
    }
}

The static reference allows us to access the description from anywhere, in case we need to edit the content. However, this means only 1 Description is allowed to exist, which should work for most cases. The function AssignValues() just updates the TextMeshPro text located on the prefab.

Now, we need to actually spawn in the prefab, and populate it. To do this, head over to your UserInterface class, and add in a new function. This function will create a description, position it, and populate the text. Lets start by adding these four variables into the UserInterface class:

public Transform parent; 
GameObject description;
public GameObject descriptionPrefab;
private Transform canvas;
private bool dragging;

The parent transform in the above code should be a reference to whatever GameObject you want the description to have as a Parent. Typically, this should be a top-level (Above any UserInterface Objects) UI element.

We need to add one last thing, to allow us to transfer our list of buffs into something readable. Adding the following variable under the ones we just created should do the trick.

TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;

We need a couple of dependancies first, so lets add the following. To actually use the TextInfo, we need System.Globalization. Enviroment.NewLine needs System, so lets add that as well.

using System;
using System.Globalization;

Then, we can actually create the code.

void CreateDescription(InventorySlot hoveringItem)
    {
        Transform _trans;
        if (parent == null)
            _trans = canvas;
        else
            _trans = parent;

        description = Instantiate(descriptionPrefab, Vector2.zero, Quaternion.identity, _trans);
        string _buffs = "";
        for (int i = 0; i < hoveringItem.item.buffs.Count; i++)
        {
            _buffs= string.Concat(_buffs, " ", hoveringItem.item.buffs[i].stat.ToString(), ": ", hoveringItem.item.buffs[i].value.ToString(), Environment.NewLine);
        }
        _buffs = _buffs.Replace("_", " ");

        var _item = hoveringItem.item;

        description.GetComponent<Description>().AssignValues(_item.Name, hoveringItem.GetItemObject().description, textInfo.ToTitleCase(_buffs), hoveringItem.ItemObj.uiDisplay);
    }

Thats good and ready to go, but now we need to actually call that function. Luckily, theres a spot we can do that from. The OnEnter() function will trigger any time the cursor passes over an item, which is a great stop to call CreateDescription.

public void OnEnter(GameObject obj)
    {
        MouseData.slotHoveredOver = obj;
        if (!dragging)
        {
            InventorySlot hoveringItem = slotsOnInterface[obj];
            if (hoveringItem.item.Id >= 0)
            {
                CreateDescription(hoveringItem);
            }
        }
    }

Now, if everything is set up right, a Description should appear. But, it won't disappear. So lets add that next.

public void OnExit(GameObject obj)
{
    MouseData.slotHoveredOver= null;
    if (description != null)
        Destroy(description);
}

Tada! The Description should appear and disappear now! Although, you may have noticed a slight issue when swapping items. Sometimes, the item that was swapped will stay as the description. Obviously, that won't do. So, we can make some small changes to the swap code in OnDragEnd() to fix this. First, we need to make sure there are no null values, otherwise we are just dropping the item. Then, we can take the required actions. We destroy the current Description, which allows for a new one to be made.

if (MouseData.slotHoveredOver && MouseData.interfaceMouseIsOver)
            {
                InventorySlot mouseSlotData = MouseData.interfaceMouseIsOver.slotsOnInterface[MouseData.slotHoveredOver];
                inventory.SwapItems(slotsOnInterface[obj], mouseSlotData);
                if (description != null)
                    Destroy(description);
            }

Now, there is one last part. We need to add some code to move the description around with the cursor. The following code can go in your UserInterface class.

private void Update()
    {
        if (description)
        {

            Vector2 _pos = new Vector2(Input.mousePosition.x + 140, Input.mousePosition.y);
            if (_pos.x > Screen.width - 140)
                _pos.x = Input.mousePosition.x - 140;
            else
                _pos.x = Input.mousePosition.x + 140;

            if (_pos.y + 288.09 > Screen.height)
                _pos.y = Screen.height - 288.09f;
            else //if (_pos.y - 288.09f <= 0)
                _pos.y = +288.09f;

            description.transform.position = _pos;
        }
    }

The above code should do it, along with making sure the description doesn't move off the screen.

And that's it! You should have a working Description System!