如何在Unity中使用BillboardRenderer?


11

从版本5(?)开始,Unity具有新的component-type BillboardRenderer。不幸的是,文档非常差。

可以通过单击“添加组件->杂项->广告牌渲染器”将其添加到检查器中,但是显然它需要Billboard Asset执行任何操作。似乎没有任何方法可以从Unity界面中创建一个。

BillboardAsset 同样糟糕的文档中的几句话之一是:

imageCount 从不同角度查看广告牌时可以切换的预烘焙图像数。

我最新的项目将具有精灵/多边形混合图形,因此我可以真正利用某个组件,该组件根据视角呈现具有不同精灵的广告牌。但是似乎没有任何方法可以添加此类图像。

所以我想知道您是否可以举一个示例说明如何使用此组件。


广告牌能达到我的期望吗?或者是其他东西?(我希望它可以使图像保持面向相机。)
Evorlor '16

@Evorlor这也是我所期望的,但是到目前为止,我还没有设法让它做任何事情
菲利普

Answers:


6

更新(2018):自从我编写此答案以来,暴露了更多属性。也许我们现在就可以创建它,也许不能。要研究。

您不能使用它。

这是反编译的BillboardAsset代码:

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

实际上,即使通过反射也无法设置图像。有人可能会想:“好吧,您不能直接做到这一点,但也许提供了某种工厂?”。我在反编译器中按“ 查找用法”,然后得到:BillboardAssetInspectorBillboardRenderer

这里是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()
        {
        }
    }
}

哇,这堂课真是愚蠢。它只是无逻辑的数据持有人。显然,所有工作都由来完成Renderer。更确切地说,通过其中的一种或几种[WraplessIcall]方法。我不会在这里放它的代码,因为它的清单很长而且没有用[WraplessIcall] -members。

UnityEngine.dll内容不同BillboardAssetInspector(位于UnityEditor.dll中)具有真实的代码。再说一次,我不会将其代码放在这里,因为从其名称可以明显看出,它不过就是Inspector而已。

与情况相同BillboardAssetInspector


知道了,仅供内部使用;但是它到底在哪里使用?

在SpeedTree系统中(尤其要看最后一张图像)。

为什么文档会解释无用的东西,而不是警告您不要立即使用它?

可能只是复制粘贴了内部开发文档中的所有内容,以及对新手和一般使用都很重要的改进部分;然后就忙于参与VR宣传,以免打磨文档的这些黑暗角落。

我们对于它可以做些什么呢?

告诉他们他们忽略了文档中的“暗角”,例如:在Unity Editor中,打开Help → Report a bug...,在What is problem related toselect中documentation,等等。

一个人能用什么代替呢?

可能的选项包括:


2
作为另一种选择:经常需要放置一堆广告牌时,我使用了一个粒子系统,该粒子系统的发射和动画已关闭,因此我可以将每个广告牌四边形手动放置在所需的位置。
DMGregory

@DMGregory不能不同意,Unity的粒子系统非常适合许多距离“粒子”不远的事物。更好的是,自Unity 5起,显着改善/优化了对粒子系统自定义的支持。我应该在答案中添加此选项,还是这些注释就足够了,您认为呢?
Maxim Kamalov'3

我认为可以保留评论。如果有人想了解更多详细信息,我认为它很实用,可以提出一个新问题。
DMGregory

我不认为这是内部使用,该文档说:“一旦知道广告牌的描述,您也可以创建自己的广告。” - docs.unity3d.com/ScriptReference/BillboardAsset.html
123iamking

@ 123iamking现在有更多公开的属性。因此,是的,现在有可能直接使用它们。
Maxim Kamalov '18

1

要使用BillboardRenderer,需要Billboard Asset,可以使用C#脚本构造Billboard Asset。检查这篇文章

广告牌资产具有以下内容: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}

这是用于生成上面文件的C#代码

 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
     }

有关更多详细信息,请检查我在答案开头给出的信息。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.