icb*_*tes 0 c# text rendering unity-game-engine gameobject
我一直在网上寻找这个答案。但是显然我的搜索短语是错误的,或者真的很难。但我对此表示怀疑。
想象一下,我有任何3D身体。球体,圆柱体或立方体。
我想在该对象上添加文字。好像它是一个贴纸或画在该对象上。意思是,如果包裹在对象的曲线或边缘上,它将遵循对象的曲线或边缘。我设法创建了一些总是在对象前面或后面的文本。但这不是我想要的。
最接近我想要的内容是这样的:
我不敢相信,我需要为此编写代码。必须通过孩子/父母,画布和文本来实现,仅使用检查器和组件即可。
是这样吗?
并不是那么简单,但是这里是您可以实现类似目标的方法。这要求您的3D模型必须正确进行UV贴图,因此您可以简单地对其应用平面纹理。设置听起来可能很复杂,但确实很酷;)
创建RenderTexture:在Asset做right mouse click→交通Create→交通RenderTexture以及但是叫什么你喜欢如TextTexture
size,例如2048*2048根据您的需求来降低分辨率。创建一个新材质
RenderTexture为Albedo RenderingMode为Fade(以便以后使其背景透明)创建一个新的图层并命名为TEXT
在您的常规main Camera下,Culling Mask 排除刚刚创建的TEXT图层。因此它将不会呈现我们的文本内容
Camera向场景添加一个新场景(它只会渲染文本)并调用它,例如TextCamera
并进行以下设置:
AudioListener组件Clear Flags → Solid ColorBackground→颜色实际上并不重要,但请确保将Alpha级别设置为0!Culling Mask→除了创建的TEXT图层外没有其他Target Texture →创建 RenderTexture现在,您已经拥有具有可动态更改的材质的材质,该材质具有透明的背景以及您喜欢的任何内容。因此,使它成为一个UI.Text
在您的场景中(我只是作为孩子的孩子来做的,TextCamera因此我可以在处理其他内容时将其移出SceneView的视线之外)添加一个Text(包括Canvas等-Unity通常会自动添加它)
TEXT以便它们不会由法线渲染,Camera而仅由渲染TextCamera。Canvas用途RenderMode = WorldSpace(不适用于覆盖画布)!Canvas大约3单位等放置在的前面TextCamera(或任何您喜欢的位置,以便稍后在纹理中看到文本)TextRectTransform集width = 1000,height = 1000,Scale = 0.001, 0.001, 0.001Text组件集中Font Size = 300Raycast Target选项现在,您可以简单地将创建的材质应用于3D对象并进行播放,并且应该看到它完全透明,除了上面带有文字。
因此,为了将其用作3D对象的叠加层,您可以例如简单地复制原始对象,调用一个对象(例如Inner另一个对象)Outer并作为Inner的子对象Outer。现在,Outer您设置了我们的文本材料。这Fade是可行的,因为用作渲染模式的材质是在不同的渲染链上渲染的,该渲染链在默认渲染链的顶部渲染。
→Tadaaa 3D对象,其文本已应用到其表面,甚至可以动态更改文本及其属性(例如颜色等)
既然您问:是的,您可以在脚本中完成所有工作…… 除了创建新的图层!在运行时这是不可能的!
因此,您必须事先知道将要使用的所有图层,然后才能执行类似的操作
[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
public class TextOnObjectManager : MonoBehaviour
{
// reference via Inspector if possible
[SerializeField] private Camera mainCamera;
[SerializeField] private string LayerToUse;
private void Awake()
{
// 0. make the clone of this and make it a child
var innerObject = new GameObject(name + "_original", typeof(MeshRenderer)).AddComponent<MeshFilter>();
innerObject.transform.SetParent(transform);
// copy over the mesh
innerObject.mesh = GetComponent<MeshFilter>().mesh;
name = name + "_textDecal";
// 1. Create and configure the RenderTexture
var renderTexture = new RenderTexture(2048, 2048, 24) { name = name + "_RenderTexture" };
// 2. Create material
var textMaterial = new Material(Shader.Find("Standard"));
// assign the new renderTexture as Albedo
textMaterial.SetTexture("_MainTex", renderTexture);
// set RenderMode to Fade
textMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
textMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
textMaterial.SetInt("_ZWrite", 0);
textMaterial.DisableKeyword("_ALPHATEST_ON");
textMaterial.EnableKeyword("_ALPHABLEND_ON");
textMaterial.DisableKeyword("_ALPHAPREMULTIPLY_ON");
textMaterial.renderQueue = 3000;
// 3. WE CAN'T CREATE A NEW LAYER AT RUNTIME SO CONFIGURE THEM BEFOREHAND AND USE LayerToUse
// 4. exclude the Layer in the normal camera
if (!mainCamera) mainCamera = Camera.main;
mainCamera.cullingMask &= ~(1 << LayerMask.NameToLayer(LayerToUse));
// 5. Add new Camera as child of this object
var camera = new GameObject("TextCamera").AddComponent<Camera>();
camera.transform.SetParent(transform, false);
camera.backgroundColor = new Color(0, 0, 0, 0);
camera.clearFlags = CameraClearFlags.Color;
camera.cullingMask = 1 << LayerMask.NameToLayer(LayerToUse);
// make it render to the renderTexture
camera.targetTexture = renderTexture;
camera.forceIntoRenderTexture = true;
// 6. add the UI to your scene as child of the camera
var Canvas = new GameObject("Canvas", typeof(RectTransform)).AddComponent<Canvas>();
Canvas.transform.SetParent(camera.transform, false);
Canvas.gameObject.AddComponent<CanvasScaler>();
Canvas.renderMode = RenderMode.WorldSpace;
var canvasRectTransform = Canvas.GetComponent<RectTransform>();
canvasRectTransform.anchoredPosition3D = new Vector3(0, 0, 3);
canvasRectTransform.sizeDelta = Vector2.one;
var text = new GameObject("Text", typeof(RectTransform)).AddComponent<Text>();
text.transform.SetParent(Canvas.transform, false);
var textRectTransform = text.GetComponent<RectTransform>();
textRectTransform.localScale = Vector3.one * 0.001f;
textRectTransform.sizeDelta = new Vector2(2000, 1000);
text.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
text.fontStyle = FontStyle.Bold;
text.alignment = TextAnchor.MiddleCenter;
text.color = Color.red;
text.fontSize = 300;
text.horizontalOverflow = HorizontalWrapMode.Wrap;
text.verticalOverflow = VerticalWrapMode.Overflow;
Canvas.gameObject.layer = LayerMask.NameToLayer(LayerToUse);
text.gameObject.layer = LayerMask.NameToLayer(LayerToUse);
text.text = "This is a dynamically generated example!";
// 7. finally assign the material to the child object and hope everything works ;)
innerObject.GetComponent<MeshRenderer>().material = textMaterial;
}
}
Run Code Online (Sandbox Code Playgroud)
基本上重现了之前的所有步骤。由于我们无法在运行时创建或编辑图层,因此您必须事先了解它们并将其输入为LayerToUse。
我将所有东西都创建为原始对象的子对象,因此很容易在以后的运行时进行控制和更改。
| 归档时间: |
|
| 查看次数: |
84 次 |
| 最近记录: |