¿Cómo usar el BillboardRenderer en Unity?

11

Desde la versión 5 (?) Unity tiene un nuevo tipo de componente BillboardRenderer. Lamentablemente, la documentación es bastante pobre.

Se puede agregar en el inspector haciendo clic en "Agregar componente -> Misceláneo -> Renderizador de vallas publicitarias", pero aparentemente requiere Billboard Assethacer algo. No parece haber ninguna forma de crear uno desde la interfaz de Unity.

Una de las pocas oraciones de la documentación igualmente pobre de BillboardAsset dice:

imageCount Número de imágenes precocinadas que se pueden cambiar cuando la cartelera se ve desde diferentes ángulos.

Mi proyecto más nuevo tendrá gráficos de mezcla de sprites / polígonos, por lo que un componente que represente una cartelera con un sprite diferente dependiendo del ángulo de visión es algo que realmente podría utilizar. Pero no parece haber ningún método para agregar tales imágenes.

Entonces, me preguntaba si podría publicar un ejemplo de cómo se usa este componente.

Philipp
fuente
¿La cartelera hace lo que esperaba? ¿O algo mas? (Espero que mantenga la imagen frente a la cámara.)
Evorlor
@Evorlor Eso es lo que yo también esperaría, pero hasta ahora no he logrado que haga nada .
Philipp

Respuestas:

6

ACTUALIZACIÓN (2018): hay más propiedades expuestas desde que escribí esta respuesta. Tal vez podamos crearlo ahora, tal vez no. Tengo que investigar.

No puedes usarlo.

Aquí está el BillboardAssetcódigo descompilado :

using System;

namespace UnityEngine
{
    /// <summary>
    ///   <para>BillboardAsset describes how a billboard is rendered.</para>
    /// </summary>
    public sealed class BillboardAsset : Object
    {
        /// <summary>
        ///   <para>Height of the billboard that is below ground.</para>
        /// </summary>
        public float bottom
        {
            [WrapperlessIcall]
            get;
            [WrapperlessIcall]
            set;
        }

        /// <summary>
        ///   <para>Height of the billboard.</para>
        /// </summary>
        public float height
        {
            [WrapperlessIcall]
            get;
            [WrapperlessIcall]
            set;
        }

        /// <summary>
        ///   <para>Number of pre-baked images that can be switched when the billboard is viewed from different angles.</para>
        /// </summary>
        public int imageCount
        {
            [WrapperlessIcall]
            get;
        }

        /// <summary>
        ///   <para>Number of indices in the billboard mesh. The mesh is not necessarily a quad. It can be a more complex shape which fits the actual image more precisely.</para>
        /// </summary>
        public int indexCount
        {
            [WrapperlessIcall]
            get;
        }

        /// <summary>
        ///   <para>The material used for rendering.</para>
        /// </summary>
        public Material material
        {
            [WrapperlessIcall]
            get;
            [WrapperlessIcall]
            set;
        }

        /// <summary>
        ///   <para>Number of vertices in the billboard mesh. The mesh is not necessarily a quad. It can be a more complex shape which fits the actual image more precisely.</para>
        /// </summary>
        public int vertexCount
        {
            [WrapperlessIcall]
            get;
        }

        /// <summary>
        ///   <para>Width of the billboard.</para>
        /// </summary>
        public float width
        {
            [WrapperlessIcall]
            get;
            [WrapperlessIcall]
            set;
        }

        /// <summary>
        ///   <para>Constructs a new BillboardAsset.</para>
        /// </summary>
        public BillboardAsset()
        {
        }

        [WrapperlessIcall]
        internal extern void MakeMaterialProperties(MaterialPropertyBlock properties, Camera camera);

        [WrapperlessIcall]
        internal extern void MakePreviewMesh(Mesh mesh);

        [WrapperlessIcall]
        internal extern void MakeRenderMesh(Mesh mesh, float widthScale, float heightScale, float rotation);
    }
}

Literalmente no hay forma de configurar imágenes, incluso por reflexión. Uno puede pensar: "está bien, no puedes hacerlo directamente, pero ¿tal vez hay algún tipo de fábrica proporcionada?". Presiono Encuentra Usos en decompilador y obtener: BillboardAssetInspectory BillboardRenderer.

Aqui esta BillboardRenderer:

using System;

namespace UnityEngine
{
    /// <summary>
    ///   <para>Renders a billboard.</para>
    /// </summary>
    public sealed class BillboardRenderer : Renderer
    {
        /// <summary>
        ///   <para>The BillboardAsset to render.</para>
        /// </summary>
        public BillboardAsset billboard
        {
            [WrapperlessIcall]
            get;
            [WrapperlessIcall]
            set;
        }

        /// <summary>
        ///   <para>Constructor.</para>
        /// </summary>
        public BillboardRenderer()
        {
        }
    }
}

Wow, esta clase es incluso más tonta. Es solo un titular de datos sin lógica. Obviamente, todo el trabajo lo realiza Renderer. Más precisamente, por uno o dos [WraplessIcall]métodos en él. No pondré su código aquí porque es una lista larga e inútil de [WraplessIcall]miembros.

A diferencia del contenido de UnityEngine.dll , BillboardAssetInspector(que reside en UnityEditor.dll ) tiene código real. De nuevo, no pondré su código aquí, porque de su nombre está claro que , de todos modos, no es más que Inspector .

La misma situación con BillboardAssetInspector.


Lo tengo, es para uso interno; pero donde se usa exactamente?

En el sistema SpeedTree (mira la última imagen en particular).

¿Por qué la documentación explica cosas inútiles en lugar de advertir contra su uso inmediato?

Probablemente, solo copie y pegue todo, desde la documentación de desarrollo interno, piezas mejoradas que son importantes para los recién llegados y en uso general; entonces estaba demasiado ocupado participando en exageraciones de realidad virtual para molestarse en pulir esos rincones oscuros de la documentación.

¿Qué podemos hacer al respecto?

Dígales que pasaron por alto este "rincón oscuro" en la documentación, por ejemplo: en Unity Editor, abrir Help → Report a bug..., What is problem related toelegir documentation, etc.

¿Qué se puede usar en su lugar?

Las posibles opciones incluyen:

Maxim Kamalov
fuente
2
Como otra alternativa: a menudo, cuando necesito colocar un montón de vallas publicitarias, utilizo un sistema de partículas, con su emisión y animación desactivadas para poder colocar manualmente cada quad con vallas publicitarias donde lo desee.
DMGregory
@DMGregory No puedo estar en desacuerdo, el sistema de partículas de Unity es ideal para muchas cosas que ni siquiera están cerca de las "partículas". Aún mejor, desde Unity 5, el soporte para la personalización del sistema de partículas se mejoró / optimizó explícitamente. ¿Debo agregar esta opción a la respuesta, o estos comentarios son suficientes, qué piensas?
Maxim Kamalov
Creo que está bien dejarlo en los comentarios. Si alguien quiere más detalles al respecto, creo que es lo suficientemente carnoso como para hacer una nueva pregunta.
DMGregory
No lo creo para uso interno, dijo el doctor: "También puedes crear el tuyo una vez que sepas cómo se describe la cartelera". - docs.unity3d.com/ScriptReference/BillboardAsset.html
123iamking
@ 123iamking Y ahora hay más propiedades expuestas. Entonces, sí, probablemente sea posible utilizarlos directamente ahora.
Maxim Kamalov
1

Para usar BillboardRenderer, necesita Billboard Asset, puede construir Billboard Asset con C # script. Mira esta publicación .

The Billboard Asset tiene contenido como este: Billboard.asset

 %YAML 1.1
 %TAG !u! tag:unity3d.com,2011:
 --- !u!226 &22600000
 BillboardAsset:
   m_ObjectHideFlags: 0
   m_CorrespondingSourceObject: {fileID: 0}
   m_PrefabInternal: {fileID: 0}
   m_Name: Billboard_Original
   serializedVersion: 2
   width: 10.350581
   bottom: -0.2622106
   height: 7.172371
   imageTexCoords:
   - {x: 0.230981, y: 0.33333302, z: 0.230981, w: -0.33333302}
   - {x: 0.230981, y: 0.66666603, z: 0.230981, w: -0.33333302}
   - {x: 0.33333302, y: 0, z: 0.33333302, w: 0.23098099}
   - {x: 0.564314, y: 0.23098099, z: 0.23098099, w: -0.33333302}
   - {x: 0.564314, y: 0.564314, z: 0.23098099, w: -0.33333403}
   - {x: 0.66666603, y: 0, z: 0.33333302, w: 0.23098099}
   - {x: 0.89764804, y: 0.23098099, z: 0.230982, w: -0.33333302}
   - {x: 0.89764804, y: 0.564314, z: 0.230982, w: -0.33333403}
   vertices:
   - {x: 0.47093, y: 0.020348798}
   - {x: 0.037790697, y: 0.498547}
   - {x: 0.037790697, y: 0.976744}
   - {x: 0.52906996, y: 0.020348798}
   - {x: 0.95930207, y: 0.498547}
   - {x: 0.95930207, y: 0.976744}
   indices: 040003000000010004000000050004000100020005000100
   material: {fileID: 2100000, guid: 6e680dda9368db5418f19388474277a2, type: 2}

Aquí está el código C # que se utilizó para generar el archivo anterior

 using System.Collections;
 using System.Collections.Generic;
 using UnityEditor;
 using UnityEngine;

     public class BillboardBaker : MonoBehaviour
     {
 #if UNITY_EDITOR
         public BillboardAsset m_outputFile;
         public Material m_material;

         [ContextMenu("Bake Billboard")]
         void BakeBillboard()
         {
             BillboardAsset billboard = new BillboardAsset();

             billboard.material = m_material;
             Vector4[] texCoords = new Vector4[8];
             ushort[] indices = new ushort[12];
             Vector2[] vertices = new Vector2[6];
             texCoords[0].Set(0.230981f, 0.33333302f, 0.230981f, -0.33333302f);
             texCoords[1].Set(0.230981f, 0.66666603f, 0.230981f,-0.33333302f);
             texCoords[2].Set(0.33333302f, 0.0f, 0.33333302f,0.23098099f);
             texCoords[3].Set(0.564314f, 0.23098099f, 0.23098099f,-0.33333302f);
             texCoords[4].Set(0.564314f, 0.564314f, 0.23098099f,-0.33333403f);
             texCoords[5].Set(0.66666603f, 0.0f, 0.33333302f,0.23098099f);
             texCoords[6].Set(0.89764804f, 0.23098099f, 0.230982f,-0.33333302f);
             texCoords[7].Set(0.89764804f, 0.564314f, 0.230982f,-0.33333403f);

             indices[0] = 4;
             indices[1] = 3;
             indices[2] = 0;
             indices[3] = 1;
             indices[4] = 4;
             indices[5] = 0;
             indices[6] = 5;
             indices[7] = 4;
             indices[8] = 1;
             indices[9] = 2;
             indices[10] = 5;
             indices[11] = 1;

             vertices[0].Set(0.47093f, 0.020348798f);
             vertices[1].Set(0.037790697f, 0.498547f);
             vertices[2].Set(0.037790697f, 0.976744f);
             vertices[3].Set(0.52906996f, 0.020348798f);
             vertices[4].Set(0.95930207f, 0.498547f);
             vertices[5].Set(0.95930207f, 0.976744f);

             billboard.SetImageTexCoords(texCoords);
             billboard.SetIndices(indices);
             billboard.SetVertices(vertices);

             billboard.width = 10.35058f;
             billboard.height = 7.172371f;
             billboard.bottom = -0.2622106f;

             if (m_outputFile != null)
             {
                 EditorUtility.CopySerialized(billboard, m_outputFile);
             }
             else
             {
                 string path;
                 path = AssetDatabase.GetAssetPath(m_material) + ".asset";
                 AssetDatabase.CreateAsset(billboard, path);
             }
         }
 #endif
     }

Para obtener más detalles, consulte la publicación que di al comienzo de la respuesta.

123iamking
fuente