Unity3D lightmap的assetbundle和动态载入

 风刀的项目是一款用unity3d引擎制作的3D页游,为了达到在光影效果和效率之间的平衡,我们使用了lightmap,事实上unity3d烘培出来的效果非常好。

    关于烘培部分,U3D的文档讲的很详细,这里就不多用文字解释了。直接上干货。

    我们的项目抛弃了unity3d的多场景的开发方式,在程序实现上,整个游戏就只有一个场景,目的是可以对资源管理可以控制到很细的一个粒度。关卡的组织我们也自己实现了一套机制。

    lightmap的动态载入主要有两方面的问题,lightmap的assetbundle和载入恢复场景的lightmap。

    关于lightmap的assetbundle,最原始的思路是将所有的lightmap贴图全部bundle成一个包(这里需要记录下所有贴图的名字),然后客户端下载好lightmap包后,将所有贴图加载到内存里,然后设置到LightmapData里面去。另外一种思路是直接讲lightmapdata里面的信息通过scriptableobject序列化成asset,然后再对该asset进行bundle.鉴于第一种方法略微复杂,风刀直接使用了第二种方式。

    ScriptableObject序列化的类,要求类型本身支持序列化,风刀测试了,LightMapData是不支持序列化的,不过这不会成为阻碍,我们把纹理数据从LightMapData里面取出来,序列化就OK了。因此,用于序列化lightmapdata的类

    public class LightMapAsset : ScriptableObject
    {
        public Texture2D[] lightmapFar;
        public Texture2D[] lightmapNear;
    }


    // 制作Asset
    LightMapAsset lightmapAsset = ScriptableObject.CreateInstance();
    int Count = LightmapSettings.lightmaps.Length;
    lightmapAsset.lightmapFar = new Texture2D[Count];
    lightmapAsset.lightmapNear = new Texture2D[iCount];


    for(int i=0; i
    {
        // 这里把直接把lightmap纹理存起来
        lightmapAsset.lightmapFar = LightmapSettings.lightmaps.lightmapFar;
        lightmapAsset.lightmapNear = LightmapSettings.lightmaps.lightmapNear;
    }

    AssetDatabase.CreateAsset(asset, “Assets/”+AssetName);

    UnityEngine.Object obj = AssetDatabase.LoadAssetAtPath(“Assets/” + AssetName, typeof(LightMapAsset));


    // 打包
    string ExportTargetPath = Application.dataPath + “/” + targetPath;

    if (!File.Exists(ExportTargetPath))
    {
        Directory.CreateDirectory(ExportTargetPath);
     }

     string lightmapBundleName = SceneName + “_lightmap.bundle”;
     BuildPipeline.BuildAssetBundle(obj, null, ExportTargetPath + lightmapBundleName.ToLower());


     // 删除临时文件
     AssetName = SceneName + “_lightmap.asset”;
     AssetDatabase.DeleteAsset(“Assets/” + AssetName);

    // 在游戏运行时恢复Lightmap数据就非常简单了,下面是风刀的测试代码片段
    if (info. www.assetBundle.mainAsset  is LightMapAsset)
    {
        LightMapAsset lightmapAsset = info. www.assetBundle.mainAsset  as LightMapAsset;
        int Count = lightmapAsset.lightmapFar.Length;
        LightmapData[] lightmapDatas = new LightmapData[Count];

         for(int i=0; i
       {
            LightmapData Lightmap = new LightmapData();
            Lightmap.lightmapFar = lightmapAsset.lightmapFar;
            Lightmap.lightmapNear = lightmapAsset.lightmapNear;
            lightmapDatas = Lightmap;
        }
        LightmapSettings.lightmaps = lightmapDatas;
     }


     还需要提到的一点是,在记录场景物件的信息时,需要记录GameObject的lightmapIndex和lightmapTilingOffset。当LightMap数据从外部加载完成后,要恢复物件lightmapIndex和lightmapTilingOffset。当Lightmap数据还没加载完成的时候,要把lightmapIndex设置为-1(不使用LightMap),否则会出现渲染错误。

你可能感兴趣的:(U3D)