将文本放置在游戏对象的按钮上,就像将其绘制一样

icb*_*tes 0 c# text rendering unity-game-engine gameobject

我一直在网上寻找这个答案。但是显然我的搜索短语是错误的,或者真的很难。但我对此表示怀疑。

想象一下,我有任何3D身体。球体,圆柱体或立方体。

我想在该对象上添加文字。好像它是一个贴纸或画在该对象上。意思是,如果包裹在对象的曲线或边缘上,它将遵循对象的曲线或边缘。我设法创建了一些总是在对象前面或后面的文本。但这不是我想要的。

最接近我想要的内容是这样的:

在此处输入图片说明

我不敢相信,我需要为此编写代码。必须通过孩子/父母,画布和文本来实现,仅使用检查器和组件即可。

是这样吗?

der*_*ugo 9

并不是那么简单,但是这里是您可以实现类似目标的方法。这要求您的3D模型必须正确进行UV贴图,因此您可以简单地对其应用平面纹理。设置听起来可能很复杂,但确实很酷;)

  1. 创建RenderTexture:在Assetright mouse click→交通Create→交通RenderTexture以及但是叫什么你喜欢如TextTexture

    在此处输入图片说明

    • 为了获得更高的分辨率,以后要提高分辨率size,例如2048*2048根据您的需求来降低分辨率。

    在此处输入图片说明

  2. 创建一个新材质

    在此处输入图片说明

    • 使用刚创建RenderTextureAlbedo
    • 并将其设置RenderingModeFade(以便以后使其背景透明)

    在此处输入图片说明

  3. 创建一个新的图层并命名为TEXT

    在此处输入图片说明 在此处输入图片说明

  4. 在您的常规main Camera下,Culling Mask 排除刚刚创建的TEXT图层。因此它将不会呈现我们的文本内容

    在此处输入图片说明

  5. Camera向场景添加一个新场景(它只会渲染文本)并调用它,例如TextCamera

    在此处输入图片说明

    并进行以下设置:

    在此处输入图片说明

    • 删除其AudioListener组件
    • Clear FlagsSolid Color
    • Background→颜色实际上并不重要,但请确保将Alpha级别设置为0
    • Culling Mask→除了创建的TEXT图层外没有其他
    • Target Texture →创建 RenderTexture

    现在,您已经拥有具有可动态更改的材质的材质,该材质具有透明的背景以及您喜欢的任何内容。因此,使它成为一个UI.Text

  6. 在您的场景中(我只是作为孩子的孩子来做的,TextCamera因此我可以在处理其他内容时将其移出SceneView的视线之外)添加一个Text(包括Canvas等-Unity通常会自动添加它)

    在此处输入图片说明

    • 使所有GameObject(画布和文本)都具有Layer,TEXT以便它们不会由法线渲染,Camera而仅由渲染TextCamera

    在此处输入图片说明 在此处输入图片说明

    • 确保Canvas用途RenderMode = WorldSpace(不适用于覆盖画布)!
    • Canvas大约3单位等放置在的前面TextCamera(或任何您喜欢的位置,以便稍后在纹理中看到文本)

    在此处输入图片说明

    • 为了获得更好的文本分辨率,我还将 Text
    • RectTransformwidth = 1000height = 1000Scale = 0.001, 0.001, 0.001
    • Text组件集中Font Size = 300
    • 只是要确保禁用该Raycast 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

我将所有东西都创建为原始对象的子对象,因此很容易在以后的运行时进行控制和更改。

在此处输入图片说明

  • 请参阅我的更新..我刚刚添加了一个脚本版本,可以为您在一个对象上完成整个设置。然而,您仍然需要事先设置图层 (2认同)