Jak korzystać z BillboardRenderer w Unity?

11

Od wersji 5 (?) Unity ma nowy typ komponentu BillboardRenderer. Niestety dokumentacja jest dość słaba.

Można go dodać w inspektorze, klikając „Dodaj komponent -> Nieprzyzwoicie -> Renderer billboardów”, ale najwyraźniej wymaga to Billboard Assetzrobienia czegokolwiek. Wydaje się, że nie ma sposobu, aby stworzyć taki z interfejsu Unity.

Jedno z niewielu zdań z równie słabej dokumentacji BillboardAsset brzmi:

imageCount Liczba wstępnie upieczonych obrazów, które można przełączać, gdy billboard jest oglądany pod różnymi kątami.

Mój najnowszy projekt będzie miał grafikę z miksowaniem duszka / wielokąta, więc mógłbym skorzystać z komponentu, który renderuje billboard z innym duszka w zależności od kąta widzenia. Ale wydaje się, że nie ma metody dodawania takich obrazów.

Zastanawiałem się więc, czy możesz opublikować przykład użycia tego komponentu.

Philipp
źródło
Czy billboard robi to, czego bym się spodziewał? Albo coś innego? (Spodziewałbym się, że obraz będzie skierowany w stronę kamery).
Evorlor
@Evorlor To, czego można oczekiwać zbyt, ale do tej pory nie udało się zmusić go do zrobienia czegoś .
Philipp

Odpowiedzi:

6

AKTUALIZACJA (2018): Od czasu, gdy napisałem tę odpowiedź, ujawniono więcej właściwości. Może możemy go teraz stworzyć, a może nie. Muszę zbadać.

Nie możesz tego użyć.

Oto zdekompilowany BillboardAssetkod:

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

Nie można dosłownie ustawić obrazów, nawet poprzez odbicie. Ktoś może pomyśleć: „w porządku, nie można tego zrobić bezpośrednio, ale może istnieje jakiś zakład fabryczny?”. Pędzę Znajdź Usages w dekompilator i uzyskać: BillboardAssetInspectora BillboardRenderer.

Oto 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, ta klasa jest jeszcze głupsza. To po prostu pozbawiony logiki posiadacz danych. Oczywiście cała praca jest wykonywana przez Renderer. Mówiąc dokładniej, za pomocą jednej lub kilku [WraplessIcall]metod. Nie umieszczę tutaj jego kodu, ponieważ jest to długa i bezużyteczna lista członków [WraplessIcall].

W przeciwieństwie do zawartości UnityEngine.dllBillboardAssetInspector (która znajduje się w UnityEditor.dll ) ma w niej prawdziwy kod. Ponownie nie umieszczę tutaj jego kodu, ponieważ z nazwy jasno wynika, że ​​i tak jest niczym więcej niż Inspektorem .

Ta sama sytuacja z BillboardAssetInspector.


Rozumiem, to jest do użytku wewnętrznego; ale gdzie to jest dokładnie używane?

W systemie SpeedTree (spójrz w szczególności na ostatnie zdjęcie).

Dlaczego dokumentacja wyjaśnia bezużyteczne rzeczy zamiast ostrzegać przed ich natychmiastowym użyciem?

Prawdopodobnie po prostu skopiowałem wszystko z wewnętrznej dokumentacji programistycznej, ulepszonych części, które są ważne dla początkujących i do ogólnego użytku; wtedy był zbyt zajęty uczestnictwem w hype VR, aby zawracać sobie głowę polerowaniem takich ciemnych kątów dokumentacji.

Co możemy z tym zrobić?

Powiedz im, że przeoczyli ten „ciemny kąt” w dokumentacji, na przykład: W edytorze Unity otwórz Help → Report a bug..., What is problem related towybierz documentation, itp.

Czego można zamiast tego użyć?

Możliwe opcje obejmują:

Maxim Kamałow
źródło
2
Jako kolejna alternatywa: często, gdy muszę umieścić kilka billboardów, używam układu cząstek, z wyłączoną emisją i animacją, dzięki czemu mogę ręcznie ustawić każdy billboard w miejscu, w którym chcę.
DMGregory
@DMGregory Nie można się nie zgodzić, system cząstek Unity doskonale nadaje się do wielu rzeczy, które nie są nawet w niewielkim stopniu zbliżone do „cząstek”. Co więcej, od Unity 5 obsługa dostosowywania układów cząstek została wyraźnie poprawiona / zoptymalizowana. Czy powinienem dodać tę opcję do odpowiedzi, czy te komentarze wystarczą, co myślisz?
Maxim Kamalov
Myślę, że można zostawić komentarz. Jeśli ktoś chce uzyskać więcej informacji na ten temat, myślę, że jest wystarczająco mięsisty, aby zadać nowe pytanie.
DMGregory
Nie wierzę w to do użytku wewnętrznego, doktor powiedział: „Możesz także stworzyć swój własny, gdy wiesz, jak opisany jest billboard”. - docs.unity3d.com/ScriptReference/BillboardAsset.html
123iamking
@ 123iamking A teraz dostępnych jest więcej nieruchomości. Tak, prawdopodobnie można je teraz wykorzystać bezpośrednio.
Maxim Kamalov,
1

Aby korzystać z BillboardRenderer, potrzebujesz Zasób Billboard, możesz zbudować Zasób Billboard za pomocą skryptu C #. Sprawdź ten post .

Zasób Billboard ma takie treści: 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}

Oto kod C #, który posłużył do wygenerowania powyższego pliku

 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
     }

Aby uzyskać więcej informacji, sprawdź post podany na początku odpowiedzi.

123iamking
źródło