AssetBundle学习笔记:3、AssetBundle内部结构

本质

  • AssetBundle在本质上是一些被分组保存在一个序列化文件中的对象。被部署为一个数据文件,这些文件按照普通包和场景包的不同,在结构上有些差别。

Normal AssetBundle structure

image

  • 对于第一个块中的main serialized file应该是可以通过AssetBundle.mainAsset获取的,而谁是mainAsset呢?在build的时候第一个放置进去的资源就是mainAsset,所以可以采用将AssetBundle中所有的资源的名称写入一个文件,然后文件作为mainAsset来使用。具体代码参考引用的第二部分

AssetBundle学习笔记:2、压缩

格式

  • 谈压缩就要谈到格式,unity目前在制作AssetBundle时默认就是压缩的,当然也可以设置为不压缩,但是显然不科学尤其是在移动端的开发上。

  • LZMA:这个是一个序列化数据文件流,也是AssetBundle的默认压缩格式。LZMA提供最佳的压缩比,但是在使用的时候需要完全解压后才能使用,因此加载时需要的事件比较多。

  • LZ4:5.3以后才加入的一种压缩格式,被unity自己大量使用。这是一种基于块的压缩方式,当一个对象从LZ4压缩的AssetBundle中加载时,会按照需要解压部分的块。这样的好处在于快速的加载对象,后面会提到一个最佳实践。当然,按照这个原理,你也可以想象如果一个LZ4AssetBundle中只包含了一个GameObject,那么也不存在什么按需加载了。当使用AssetBundle.LoadFromFile加载LZ4格式的文件时,其实不会将问价加载到内容,而是加载AssetBundle的Header。

  • AssetBundle也可以选择不压缩,这样体积最大但是加载最快。

我所了解的法线贴图

两篇文章

AssetBundle学习笔记:1、概述和创建

前言

  • 打算彻底搞清楚AssetBundle的原理和使用,目前计划刷完官方文档和最佳实践系列文章,而且笔记中的内容会大量是官方文档的内容。

概述

  • AssetBundle可以包含任意unity能识别的类型文件,甚至是一个场景。如果想包含自定义的二进制文件,需要文件后缀名是.bytes,unity会将这样的文件导入为TextAsset。

SendMessage测试

  • 5.5.2中没有了以前那种参数是对象的SendMessage方法,WTF.
  • obj.SendMessage(“Foo”, 1, SendMessageOptions.DontRequireReceiver);如果设置了DontRequireReceiver,那么找不到Foo方法不会报错,如果没有写这个参数默认是RequireReceiver,则报错。
  • 如果Foo的参数不对,会提示MissingMethodException: The best match for method Foo has some invalid parameter.

关于AssetBundle解压的讨论结果

  • 一切的起源在于这篇文章,在文中对AssetBundle的加载进行了详细的描述,但是疑问也由此而生。以下是我在UWA讨论群的提问:

    在讲WWW的时候有这样一段话【解压后的内容,通常为原Bundle文件的4~5倍大小,纹理资源比例可能更大】,在我理解就是www这样的方式获取到的资源(压缩形式的)会被解压缩,并放置到webstream中。而在【AssetBundle加载进阶】部分的【前者劣势】部分,又有【每次加载都涉及到解压操作】,请问这个【加载】指的是什么?是www.assetBundle还是AssetBundle.Load?还有【解压缩】是指的什么?不是在WWW的时候已经解压缩了吗?

由一个美术需求引发的Custom Inspector

需求

  • Editor模式下,在运行或者非运行状态下,能够按照指定的变化率来自动改变material中属性数值。

需求分析

  • 如何在Editor模式下获得一个游戏对象及其组件,尤其是在非运行状态下?我们知道在Unity IDE运行起来后是很容易获得一个对象和组件的,在GameObject上挂一个脚本即可。但是在非运行状态下呢,transform.GetComponent这样的方法怎么执行?好在unity已经为我们考虑到了这个问题,提供了[ExecuteInEditMode]Attribute,通过指定这个attribute使得组件类中的方法可以在edit模式下执行,并且是在非运行状态下的。

  • 如何在非运行状态下匀速改变数值呢?update方法中配合Time.deltaTime是一个完美的方案,但是即使设置了[ExecuteInEditMode],update的表现在非运行和运行时也是完全不同的,查资料看到 is only called when something in the scene changed. 这句话时也有种吐槽的冲动。好在unity又为大家考虑到了这个问题(话说unity editor确实功能强大,AssetAtore里面那些插件真是厉害),Edit模式下提供了EditorApplication.update,这是一个事件,我们注册一个自己的方法就可以在非运行状态下实现update的功能。我个人比较推荐使用EditorCoroutine,一个基于EditorApplication.update的协程实现。

代码生成AnimatorController

0.出发点

  • 现在的项目需要设置多套动画组合,全部是由策划在XML文件中设置完成,如果完全的手动在AnimatorController中去做不但工作量大而且如果将来有配置修改了还要一个个去找到对应的自状态机并且修改。因此就萌生了用代码去生成状态机的想法,而且在网上也有了很多的教程可以参考,只是每个项目都不同,且对于一些参数和属性的设置也不尽相同,因此还是把自己的代码进行一些修改后分享出来,基本上应该是包含了状态机常用的功能。

  • 需要注意我的具体代码中是在一个已有的AnimatorController基础上创建的。如果完全是从0开始可以参考别的资料,其实道理是一样的都是代码创建对象。

1.数据来源

一个典型的XML文件

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="ISO-8859-1"?>
<config>
<datas>
<data INDEX="1" Clip1="jump" Clip1Count="1" Clip2="BackLeap" Clip2Count="2" Clip3="die" Clip3Count="1"></data>
<data INDEX="2" Clip1="BackLeap" Clip1Count="3" Clip2="jump" Clip2Count="0" Clip3="jump" Clip3Count="0"></data>
<data INDEX="3" Clip1="BackLeap" Clip1Count="1" Clip2="ForwardLeap" Clip2Count="1" Clip3="jump" Clip3Count="1"></data>
</datas>
</config>

LOD初探

概念

  • LOD全称是Level of Detail,也就是细节层级。
  • 为什么会产生这个技术?根据官方教程的解释是因为在一个很大的场景中,需要进一步考虑性能问题。LOD就是一个很好的解决性能问题的方案,它根据物体与摄像机的距离来展示这个物体不同的mesh,从而使得物体较远是使用面数比较少的mesh,而距离近的时候使用面数多的mesh。
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×