如何显示 3D 文本 notification/toast

How to show 3D text notification/toast

有没有什么简单的方法可以在摄像机前(在游戏中)显示文本通知并使其在玩家移动时跟随摄像机?

我们正在创建一款游戏,玩家可以在其中通过语音发出命令,当命令被识别时,必须显示一些文本通知(例如 Android 中的 toast 通知)。

我知道文本网格,我们可以将它放在镜头前 show/hide,但我们需要以编程方式完成它。

我最终创建了一个 class,它可以在运行时生成 toast。
代码是这样的(初始版本,需要小的重构):

using UnityEngine;

public class ToastText3D : MonoBehaviour
{
    public static ToastText3D Instance { get; private set; }

    private static bool isShowingTextMessage;
    private static GameObject textMeshGameObject;

    // Preventing instantiation of class by making constructor protoected (or private)
    protected ToastText3D() { }

    private void Awake()
    {
        // Check if instance already exists
        if (Instance == null)
            // if not, set instance to this
            Instance = this;
        else if (Instance != this)
            // Then destroy this. This enforces our singleton pattern, meaning there can only ever be one instance of a GameManager.
            Destroy(gameObject);

        // Sets this to not be destroyed when reloading scene
        DontDestroyOnLoad(gameObject);
    }

    private void Update()
    {
        if (!isShowingTextMessage)
            return;

        var headPosition = Camera.main.transform.position;
        var gazeDirection = Camera.main.transform.forward;

        float distanceFromCamera = 2; // TODO: Move this to const

        Vector3 desiredPosition = headPosition + gazeDirection * distanceFromCamera;
        textMeshGameObject.transform.position = desiredPosition;

        // Rotate the object to face the user.
        Quaternion toQuat = Camera.main.transform.localRotation;
        toQuat.x = 0;
        toQuat.z = 0;
        textMeshGameObject.transform.rotation = toQuat;
    }

    // Returns current text mesh or creates new one if there is no
    private TextMesh getCurrentTextMesh()
    {
        if (!textMeshGameObject)
            textMeshGameObject = new GameObject();

        TextMesh curTextMesh = textMeshGameObject.GetComponent(typeof(TextMesh)) as TextMesh;
        if (!curTextMesh)
        {
            // TODO: Make constants
            curTextMesh = textMeshGameObject.AddComponent(typeof(TextMesh)) as TextMesh;
            MeshRenderer meshRenderer = textMeshGameObject.GetComponent(typeof(MeshRenderer)) as MeshRenderer;
            meshRenderer.enabled = true;
            curTextMesh.anchor = TextAnchor.MiddleCenter;
            curTextMesh.alignment = TextAlignment.Center;
            curTextMesh.fontStyle = FontStyle.Bold;
            curTextMesh.fontSize = 20;

            curTextMesh.transform.localScale = new Vector3(0.02f, 0.02f, 0.02f);
        }

        return curTextMesh;
    }

    public void Show3DTextToast(string textToShow, int timeout = 5)
    {
        if (timeout < 0 || textToShow == "")
            return;

        TextMesh curTextMesh = getCurrentTextMesh();

        curTextMesh.text = textToShow;

        textMeshGameObject.SetActive(true);
        isShowingTextMessage = true;

        // Canceling message hiding invokation if there was any
        CancelInvoke("Hide3DTextToast"); // TODO: Move function name to const
        // Hiding text if there is any timeout
        if (timeout != 0)
            Invoke("Hide3DTextToast", timeout);
    }

    public void Hide3DTextToast()
    {
        textMeshGameObject.SetActive(false);
        isShowingTextMessage = false;
    }
}

现在我们只需要通过传递文本和间隔来调用函数Show3DTextToast
示例:

ToastText3D.Instance.Show3DTextToast("Text Message", 10);