Не все так просто, но вот как вы можете достичь чего-то подобного. Для этого требуется, чтобы ваши 3D-модели были правильно отображены в УФ-свете, чтобы вы могли просто применить к ним плоскую текстуру. Настройка может показаться сложной, но она действительно крутая;)
Создайте RenderTexture
: в Asset
do щелкните правой кнопкой мыши → Create
→ RenderTexture
и назовите его так, как вам нравится, например TextTexture
- Чтобы иметь более высокое разрешение, увеличьте его
size
, например, 2048*2048
, исходя из ваших потребностей.
Создать новый материал
- используя только что созданный
RenderTexture
как Albedo
- и установите для
RenderingMode
значение Fade
(для того, чтобы позже сделать его фон прозрачным)
Создайте новый Слой и назовите его, например, TEXT
У вас обычный основной Camera
под Culling Mask
исключить тон только что создал TEXT
слой.Таким образом, он не будет отображать наш текстовый контент
Добавить новый Camera
к вашей сцене (он будет только отображатьтекст) и назовите его, например, TextCamera
и выполните следующие настройки:
- Удалите
AudioListener
компонент Clear Flags
→ Solid Color
Background
→ Цвет на самом деле не имеет значения, но обязательно установитеальфа-уровень до 0
! Culling Mask
→ Ничего, кроме созданного TEXT
слоя Target Texture
→ Созданного RenderTexture
Теперь у вас уже есть Материал с динамически изменяемой текстурой с прозрачным фоном и любым другим содержимым, которое вам нравится.Итак, давайте сделаем это, например, UI.Text
Для вашей сцены (я сделал это просто как потомок TextCamera
, чтобы я мог просто переместить его из поля зрения в SceneView во время работыдобавьте Text
(включая Canvas и т. д. - Unity обычно добавляет его автоматически)
- Сделать все GameObjects (Canvas)и текст) имеют слой
TEXT
, поэтому они не будут отображаться обычным Camera
, а только TextCamera
.
- Убедитесь, что
Canvas
использует RenderMode = WorldSpace
(он не будет работать с наложенным холстом)! - Поместите
Canvas
около например 3
единиц перед TextCamera
(или где угодно, чтобы текст был виден в текстуре позже)
- Чтобы получить лучшее разрешение текста, я бы также включил
Text
- в
RectTransform
set width = 1000
, height = 1000
, Scale = 0.001, 0.001, 0.001
- В компоненте
Text
установить Font Size = 300
- Просто чтобы отключить
Raycast Target
опция
И теперь вы можете просто применить созданный материал к своему 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;
}
}
По существу воспроизводя все шаги, сделанные ранее.Поскольку мы не можем создавать или редактировать слои во время выполнения, вы должны знать их заранее и ввести их как LayerToUse
.
Я создал каждую вещь как дочерний элемент исходного объекта, поэтому его легко контролировать и изменятьтакже позже во время выполнения.