相关技术:Text、TextMesh、Rigidbody(刚体)、BoxCollider(碰撞体)、TextGenerator、文本网格、文字网格
原理:使用UGUI Text获取其文字的每个字符网格坐标,转世界坐标生成对应的3D文本(TextMesh)并挂上刚体、碰撞体实现掉落。
UGUI Text直接挂Canvas(World Space) 将它挪到镜头前,然后我是调整它的透明度为0的(不会影响网格生成),并挂载Gravity3DText组件,Gravity3DText组件参数拖拽自身Canvas和一个TextMesh物体预制体(3D文本),运行游戏后点击空格生成3D文本
预制体组件情况:
UGUI Text物体组件情况:
地板物体:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Gravity3DText : MonoBehaviour
{public Canvas canvas;public GameObject gravity3DTextPrefab;private Text textMesh;private List<GameObject> tempTextList;public class CharData{public Vector3 pos;public Vector2 size;}void Start(){tempTextList = new List<GameObject>();textMesh = GetComponent<Text>();textMesh.GraphicUpdateComplete();}public void Update(){if (Input.GetKeyDown(KeyCode.Space)){string textStr = textMesh.text;int textLength = textStr.Length;TextGenerator textGenerator = new TextGenerator(textLength);Vector2 size = textMesh.rectTransform.rect.size;textGenerator.Populate(textStr, textMesh.GetGenerationSettings(size));List<UIVertex> vertexList = textGenerator.verts as List<UIVertex>; List<CharData> charDataList = new List<CharData>();for (int i = 0; i <= vertexList.Count - 4; i += 4){CharData charData = new CharData();Vector3 pos1 = vertexList[i].position;Vector3 pos2 = vertexList[i + 1].position;Vector3 pos3 = vertexList[i + 2].position;Vector3 pos4 = vertexList[i + 3].position;Vector3 pos = (pos1 + pos2 + pos3 + pos4) / 4.0f;pos /= canvas.scaleFactor;charData.pos = pos;Vector3 charMinPos = Vector3.Min(pos1, pos2);charMinPos = Vector3.Min(charMinPos, pos3);charMinPos = Vector3.Min(charMinPos, pos4);Vector3 charMaxPos = Vector3.Max(pos1, pos2);charMaxPos = Vector3.Max(charMaxPos, pos3);charMaxPos = Vector3.Max(charMaxPos, pos4);charData.size = new Vector2(charMaxPos.x - charMinPos.x, charMaxPos.y - charMinPos.y);charDataList.Add(charData);}//统一字体大小 float sameY = transform.localPosition.y;string trimStr = textStr.Replace(" ", "");Debug.Log("trimStr:" + trimStr);int subMeshCount = Mathf.Min(textMesh.text.Length, charDataList.Count);for (int i = 0; i < subMeshCount; i++){CharData charData = charDataList[i];Vector3 pos = transform.TransformPoint(charData.pos);pos.y = sameY;Debug.Log($"第{i + 1}个字,中心点:{pos}, size:{charData.size}, char:{trimStr[i]}");GameObject tempTextGo = GameObject.Instantiate(gravity3DTextPrefab);Transform tempTextTrans = tempTextGo.transform;tempTextTrans.position = pos;TextMesh tempTextMesh = tempTextGo.GetComponent<TextMesh>();tempTextMesh.text = trimStr[i].ToString();tempTextMesh.fontSize = textMesh.fontSize * 5;tempTextMesh.characterSize = 10 / 5; //minSize;tempTextList.Add(tempTextGo);}}}private void OnDestroy(){foreach (var v in tempTextList){GameObject.Destroy(v);}tempTextList.Clear();}
}