如何显示 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);
有没有什么简单的方法可以在摄像机前(在游戏中)显示文本通知并使其在玩家移动时跟随摄像机?
我们正在创建一款游戏,玩家可以在其中通过语音发出命令,当命令被识别时,必须显示一些文本通知(例如 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);