Wie verwende ich den BillboardRenderer in Unity?

11

Seit Version 5 (?) Hat Unity einen neuen Komponententyp BillboardRenderer. Leider ist die Dokumentation ziemlich schlecht.

Es kann im Inspektor hinzugefügt werden, indem Sie auf "Komponente hinzufügen -> Verschiedenes -> Billboard-Renderer" klicken. Anscheinend ist jedoch eine Aktion erforderlich Billboard Asset. Es scheint keine Möglichkeit zu geben, eine über die Unity-Oberfläche zu erstellen.

Einer der wenigen Sätze aus der ebenso schlechten Dokumentation von BillboardAsset lautet:

imageCount Anzahl der vorgebackenen Bilder, die umgeschaltet werden können, wenn die Werbetafel aus verschiedenen Blickwinkeln betrachtet wird.

Mein neuestes Projekt wird Sprite / Polygon-Mix-Grafiken haben, daher könnte ich eine Komponente, die je nach Betrachtungswinkel eine Werbetafel mit einem anderen Sprite rendert, wirklich nutzen. Es scheint jedoch keine Methode zu geben, solche Bilder hinzuzufügen.

Ich habe mich gefragt, ob Sie ein Beispiel für die Verwendung dieser Komponente veröffentlichen können.

Philipp
quelle
Tut die Werbetafel das, was ich erwarten würde? Oder etwas anderes? (Ich würde erwarten, dass das Bild der Kamera zugewandt
bleibt
@Evorlor Das ist , was ich erwarten, aber bisher habe ich es nicht geschafft, es zu tun zu bekommen nichts .
Philipp

Antworten:

6

UPDATE (2018): Seit ich diese Antwort geschrieben habe, sind mehr Eigenschaften verfügbar. Vielleicht können wir es jetzt schaffen, vielleicht auch nicht. Muss recherchieren.

Du kannst es nicht benutzen.

Hier ist dekompilierter BillboardAssetCode:

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);
    }
}

Es gibt buchstäblich keine Möglichkeit, Bilder zu setzen, auch nicht durch Reflexion. Man könnte denken: "Okay, Sie können es nicht direkt tun, aber vielleicht gibt es eine Art Fabrik?" Ich drücke Nutzungen finden in Decompiler und bekommen: BillboardAssetInspectorundBillboardRenderer .

Hier ist 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, diese Klasse ist noch dümmer. Es ist nur ein logischer Datenhalter. Offensichtlich wird alle Arbeit von erledigt Renderer. Genauer gesagt durch eine oder [WraplessIcall]mehrere Methoden darin. Ich werde den Code hier nicht einfügen, da es sich um eine lange und nutzlose Liste von [WraplessIcall]Mitgliedern handelt.

Im Gegensatz zu UnityEngine.dll- Inhalten BillboardAssetInspector(die sich in UnityEditor.dll befinden ) enthält sie echten Code. Auch hier werde ich den Code nicht einfügen, da aus dem Namen hervorgeht, dass es sowieso nichts anderes als Inspector ist.

Gleiche Situation mit BillboardAssetInspector.


Verstanden, es ist für den internen Gebrauch; aber wo wird es genau verwendet?

Im SpeedTree-System (siehe insbesondere das letzte Bild).

Warum erklärt die Dokumentation nutzlose Dinge, anstatt davor zu warnen, sie sofort zu verwenden?

Wahrscheinlich haben Sie einfach alles aus der internen Entwicklungsdokumentation kopiert, verbesserte Teile, die für Neulinge wichtig sind und im allgemeinen Gebrauch verwendet werden. war dann zu beschäftigt, am VR-Hype teilzunehmen, um sich die Mühe zu machen, solche dunklen Ecken der Dokumentation zu polieren.

Was können wir dagegen tun?

Sagen Sie ihnen, dass sie diese „dunkle Ecke“ in der Dokumentation übersehen haben, zum Beispiel: Öffnen Sie Help → Report a bug...im Unity-Editor, What is problem related towählen Sie documentationusw.

Was kann man stattdessen verwenden?

Mögliche Optionen sind:

Maxim Kamalov
quelle
2
Als weitere Alternative: Wenn ich eine Reihe von Werbetafeln platzieren muss, verwende ich häufig ein Partikelsystem, dessen Emission und Animation deaktiviert sind, damit ich jedes Quad mit Werbetafeln manuell an der gewünschten Stelle positionieren kann.
DMGregory
@DMGregory Das Partikelsystem von Unity eignet sich hervorragend für viele Dinge, die nicht einmal in der Nähe von „Partikeln“ liegen. Noch besser ist, dass seit Unity 5 die Unterstützung für die Anpassung von Partikelsystemen explizit verbessert / optimiert wurde. Sollte ich diese Option zur Antwort hinzufügen oder diese Kommentare reichen aus, was denkst du?
Maxim Kamalov
Ich denke, es ist in Ordnung, in den Kommentaren zu hinterlassen. Wenn jemand mehr Details darüber möchte, denke ich, dass es fleischig genug ist, um eine neue Frage zu stellen.
DMGregory
Ich glaube es nicht für den internen Gebrauch, sagte der Arzt: "Sie können auch Ihre eigenen erstellen, sobald Sie wissen, wie die Werbetafel beschrieben wird." - docs.unity3d.com/ScriptReference/BillboardAsset.html
123iamking
@ 123iamking Und jetzt gibt es mehr Eigenschaften ausgesetzt. Also, ja, es ist wahrscheinlich möglich, sie jetzt direkt zu nutzen.
Maxim Kamalov
1

Um BillboardRenderer verwenden zu können, benötigen Sie Billboard Asset. Sie können Billboard Asset mit dem C # -Skript erstellen. Überprüfen Sie diesen Beitrag .

Das Billboard-Asset enthält folgenden Inhalt: 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}

Hier ist der C # -Code, mit dem die obige Datei generiert wurde

 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
     }

Weitere Informationen finden Sie in dem Beitrag, den ich am Anfang der Antwort gegeben habe.

123iamking
quelle