C# 将文本放在游戏对象上,但就像它是被绘制的一样

C# 将文本放在游戏对象上,但就像它是被绘制的一样,c#,unity3d,text,rendering,gameobject,C#,Unity3d,Text,Rendering,Gameobject,我在网上寻找这个答案已经有一段时间了。 但显然我的搜索词组是错的,或者说真的很难。但我对此表示怀疑 想象一下,我有任何3d身体。球体、圆柱体或立方体 我想在那个物体上放一段文字。好像它是一张贴纸或画在那个物体上。 也就是说,如果环绕对象,它将跟随对象的曲线或边。我设法创造了一些文本,它们总是在我的对象的前面或后面。但这不是我想要的 最接近我想要的是: 我不敢相信,我需要为此编写代码。它必须通过子/父、画布和文本实现,只需使用检查器和组件 是这样吗 不是那么简单,但下面是如何实现类似目标的方法这

我在网上寻找这个答案已经有一段时间了。 但显然我的搜索词组是错的,或者说真的很难。但我对此表示怀疑

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

我想在那个物体上放一段文字。好像它是一张贴纸或画在那个物体上。 也就是说,如果环绕对象,它将跟随对象的曲线或边。我设法创造了一些文本,它们总是在我的对象的前面或后面。但这不是我想要的

最接近我想要的是:

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


是这样吗

不是那么简单,但下面是如何实现类似目标的方法这要求您的3D模型正确地进行UV映射,这样您就可以简单地对其应用平面纹理。设置听起来可能很复杂,但确实很酷;)

  • 创建:在
    资产中
    使用鼠标右键单击&rightarrow<代码>创建&右箭头
    RenderTexture
    并随意调用它,例如
    textTextTexture

    • 为了以后获得更好的分辨率,请根据您的需要将其大小增加到例如
      2048*2048

  • 创建新材质

    • 使用刚刚创建的渲染器as
      Albedo
    • 并将
      渲染模式设置为
      淡入
      (以便以后使其背景透明)

  • 创建一个新的并调用它,例如
    TEXT

  • 在您的普通主
    相机
    中,在
    剔除遮罩
    下排除刚刚创建的
    文本
    层。所以它不会呈现我们的文本内容

  • 向场景中添加一个新的
    摄影机
    (它将只渲染文本),并调用它,例如
    TextCamera

    并进行以下设置:

    • 删除其
      AudioListener
      组件
    • 清除标志
      &rightarrow<代码>纯色
    • 背景
      &rightarrow;颜色实际上并不重要,但请确保将Alpha级别设置为
      0
    • 剔除遮罩
      &rightarrow;除了创建的
      文本
      层外,没有其他内容
    • 目标纹理
      &rightarrow;创建的
      RenderTexture
    现在,您已经拥有了一种材质,该材质具有动态可变的纹理、透明的背景以及您喜欢的任何内容。因此,让我们将其设置为例如UI.Text

  • 在你的场景中(我只是作为
    TextCamera
    的孩子做的,这样我就可以在处理其他东西的时候在场景视图中将它移到看不见的地方)添加
    Text
    (包括画布等-Unity通常会自动添加)

    • 使所有游戏对象(画布和文本)都具有层
      Text
      ,这样它们就不会被普通的
      Camera
      渲染,而只能被
      TextCamera
      渲染

    • 确保
      Canvas
      使用
      RenderMode=WorldSpace
      (它不适用于覆盖画布)
    • Canvas
      放置在
      TextCamera
      前面,例如
      3个
      单元(或您喜欢的任何位置,以便文本稍后在纹理中可见)

    • 为了获得更好的文本分辨率,我还需要在
      文本上
    • RectTransform
      上设置
      width=1000
      height=1000
      Scale=0.001,0.001
    • 文本中
      组件集
      Font Size=300
    • 只是为了确保禁用
      光线投射目标
      选项

  • 现在,你可以简单地将创建的材质应用到你的3D对象上,点击play,你会发现除了上面有文本之外,它是完全透明的

    因此,为了将其用作3D对象的覆盖,您可以(例如)简单地复制原始对象,调用一个,例如
    内部
    另一个
    外部
    ,并使
    内部
    成为
    外部
    的子对象。现在在
    外部
    设置我们的文本材料。这是因为使用“淡入淡出”作为渲染模式的材质在不同的渲染链上渲染,该渲染链在默认渲染链的顶部渲染

    &向右箭头;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;
        }
    }
    
    [RequireComponent(类型化(网格渲染器)、类型化(网格过滤器))]
    公共类TextOnObject管理器:MonoBehavior
    {
    //如有可能,通过检查员进行参考
    [SerializeField]专用摄像机主摄像机;
    [SerializeField]专用字符串层使用;
    私人空间
    {
    //0.将此克隆并使其成为子对象
    var innerObject=newgameobject(name+“_original”,typeof(MeshRenderer)).AddComponent();
    innerObject.transform.SetParent(transform);
    //在网格上复制
    innerObject.mesh=GetComponent().mesh;
    name=name+“_textdeal”;
    //1.创建和配置RenderTexture
    var rendertextre=newrendertextre(2048204824){name=name+“_rendertextre”};
    //2.创建材质
    var textmater=新材质(Shader.Find(“标准”);
    //将新渲染纹理指定为反照率
    textMaterial.SetTexture(“\u MainTex”,renderTexture);
    //