个人测试记录项目,又琐碎又长.....
目录
1_0_1:添加RuntimeProfiler功能,显示运行时的状态信息
1_1_0:场景中添加模型fbx1.prefab的一部分(Cube)
1_1_1:场景中只留下fbx1.fbx中的teapot,加上性能参数界面
1_1_2:场景中保留fbx5.fbx,一个有11个茶壶的模型塌陷成的比较大的模型。
1_1_3:用fbx1中的茶壶,复制10份,留11个茶壶在场景中
1_1_7:fbx1里面的teapot做出预设,并留在场景中。
1_1_11:fbx1.prefab放到Resources里面
1_1_12:teaport.prefab放到Resources里面
1_1_13:fbx1.fbx放到Scene2里面,没有在Resources里面
一、疑问
Unity中模型到底是什么?
Mesh+Material(Shader+Texture)?:https://docs.unity3d.com/Manual/class-Mesh.html
外部导入的模型的文件格式可以是obj/fbx/3ds等格式。
能否自己保存模型格式?
预设文件又是什么?
Scene文件是什么?
打包后模型是已怎样的方式存在的?
运行过程中,内存中的模型是怎样的?
由什么方式能够高效的保存模型信息,像是正方形,其实可以用一个中心和边的长度来标识,一个圆形,可以用一个圆心和一个半径表示。
obj/fbx/3ds等格式是如何保存模型信息的?
Resource/Prefab/Scene/AssetBundle中的模型又是怎样的?对打包后的模型的影响。
二、模型文件格式
我们公司用3dmax建模,以前导入unity用3ds/obj,现在都用fbx了。
Unity支持的文件格式:https://docs.unity3d.com/cn/2020.1/Manual/3D-formats.html
Unity 支持从两种不同类型的文件导入网格和动画:
导出的 3D 文件格式,如 .fbx 或 .obj。您可以使用通用格式从 3D 建模软件导出文件,此类格式的文件可以由各种不同的软件导入和编辑。
Unity 可读取 .fbx、.dae (Collada)、.3ds、.dxf 和 .obj 文件
专有的 3D 或 DCC(数字内容创作)应用程序文件,例如来自 Autodesk® 3ds Max® 或 Blender 的 .max 和 .blend 文件格式。只能在创建专有文件的软件中编辑这些文件。专有文件通常无法在未经转换和导入的情况下直接由其他软件编辑。
注意:除非在计算机上安装了相应的 3D 建模软件,否则保存为 .ma、.mb、.max、.c4d 或 .blend 文件的资源将无法导入。这意味着,处理 Unity 项目的每个人都必须安装正确的软件。例如,如果您使用 Autodesk® Maya LT™ 许可证来创建 ExampleModel.mb 并将其复制到项目中,那么任何打开该项目的用户也需要在他们的计算机上安装 Autodesk® Maya LT™。
三维文件格式知多少| abc、glTF、fbx、obj、dae、stl、3ds
才知道3ds格式都快被淘汰了,fbx是autodesk家族的格式,
abc,gITF,dae以前都没接触过。
gITF说是要成为三维界的jpeg,但是3dmax导出需要插件,unity导入也需要插件,你这个怎么算呢?
Unity导入glTF格式模型:https://blog.csdn.net/beihuanlihe130/article/details/94544255
常见建模软件导出glTF:https://www.yuque.com/kivicube/manual/3d-gltf-export
从官方文档来看,unity似乎推荐fbx或者obj格式,相当于由动画的模型用fbx,没有动画的用obj吧。
警告:建议导出 FBX,而不是直接保存为项目应用中的默认格式。建议不要在生产中直接使用原生文件格式。
---------------------------------
三、模型加载测试:
fbx:正常,Convert Units不去掉模型很小;旋转轴不一致,模型带有(-90,0,0)的角度;导出时使用y轴向上或者z轴向上都一样。
obj:正常,把3dmax里面的编辑颜色也带出来了。
3ds:正常
dae:正常,旋转轴不一致,模型带有(-90,0,0)的角度
dxf:模型没有内容
abc:不识别模型
材质、贴图、动画、平滑组就不做比较了。
这么看来,还是obj好。
. obj 格式, 静态多边形模型 - 附带 UV 信息及材质路径!不包含动画、材质特性、贴图路径、动力学、粒子等信息。主要支持多边形(Polygons)模型。是最受欢迎的格式。
fbx格式:一个茶壶100k,10个1M,100个10M,1000个1000M
一个茶壶在3dmax中:4096个三角形
在Unity中:
---------------------------------------------------
四、模型设置
https://docs.unity3d.com/cn/2020.1/Manual/class-FBXImporter.html
https://docs.unity3d.com/cn/2020.1/Manual/FBXImporter-Model.html
五、Prefab/Scene文件内容
Prefab文件
里面存的是预制内的所有组件的内容,也就是说组件越多,文件越大。
里面的Transform的基本信息是明文存在的,Mesh信息是用FileID和guid标识的,基本模型的Mesh我怀疑是基本的一个资源,默认已经保存在项目中的某一处了,这里引用就行了。
这个文件最开始的部分说明它是用 YAML格式的,YAML详解 是什么:https://blog.csdn.net/lilun517735159/article/details/79230732
Scene文件:
预设在场景中用PrefabInstance表示
六、打包测试
用mono打包:
打包文件说明:
参考:https://github.com/imadr/Unity-game-hacking
│ *.exe
└───*_Data
│ globalgamemanagers
│ globalgamemanagers.assets
│ level0
│ level0.resS
...
| levelN
| levelN.resS
│ sharedassets0.assets
│ sharedassets0.assets.resS
...
| sharedassetsN.assets
| sharedassetsN.assets.resS
| resources.assets
├───Managed
│ Assembly-CSharp.dll
│ Assembly-UnityScript.dll
│ Mono.Security.dll
│ mscorlib.dll
│ System.Core.dll
│ System.dll
│ UnityEngine.dll
│ UnityEngine.dll.mdb
│ UnityEngine.Networking.dll
│ UnityEngine.UI.dll
├───Mono
│ │ mono.dll
│ └───etc
│ └───mono
│ │ browscap.ini
│ │ config
│ ├───1.0
│ │ DefaultWsdlHelpGenerator.aspx
│ │ machine.config
│ ├───2.0
│ │ │ DefaultWsdlHelpGenerator.aspx
│ │ │ machine.config
│ │ │ settings.map
│ │ │ web.config
│ │ └───Browsers
│ │ Compat.browser
│ └───mconfig
│ config.xml
└───Resources
unity default resources
unity_builtin_extra
参考2:https://www.programmersought.com/article/23411832588/
参考3:https://docs.unity3d.com/ScriptReference/Build.Reporting.CommonRoles.html
七、基本项目打包测试:
0:项目中没有模型,场景中没有模型,纯粹的空项目
1:项目中有模型,场景中没有模型
0和1的打包后的结果是一样的
Textures 128.2 kb 0.9%
Meshes 0.0 kb 0.0%
Animations 0.0 kb 0.0%
Sounds 0.0 kb 0.0%
Shaders 7.4 kb 0.1%
Other Assets 0.7 kb 0.0%
Levels 5.3 kb 0.0%
Scripts 737.4 kb 5.0%
Included DLLs 13.4 mb 93.9%
File headers 14.3 kb 0.1%
Total User Assets 14.3 mb 100.0%
Complete build size 52.3 mb
用CompareTo比较发现只有\Data\globalgamemanagers有一点点差异。
0_1:项目中没有模型,场景中添加基本模型
0_1_1:在0_1基础上创建场景2
场景2是从场景1复制并删除灯光和摄像头的,场景2仅仅是存在,运行后不加载
和0_1比较,多了level1和sharedassets1.asserts,少了shareassert0.assets.resS(为什么呢?)
0_1_2:复制2,增加3、4场景,
和0_1_1比较:
0_1_3:减少3、4场景中的模型
0_1_4:再添加一个空场景 5
空场景的大小是4516
0_1_5:将主场景内的东西移动到另一个场景中 1
场景的文件名称LevelN是由在Build界面中的顺序决定的
0_1_6:将摄像头和灯光留在启动主场景中
这里level1和level2的大小相同了,但是为什么sharedassets1比shareasserts2大很多呢?
0_1_7:将灯光移动到场景1
好像.resS中保存了灯光的信息,灯光在哪个场景,它就在哪
0_1_8:将灯光移动到场景5
确定了,灯光信息保存在resS中
0_1_9:主场景也添加一个灯光
奇怪了,这说明什么?
0_1_10:将场景1、2、3、4里面的模型部分创建预设
预设内的模型越多,预设文件越大
Level文件大小不变,内容变化了
0_1_11:添加一个空的resources文件夹
globalgamemanagers文件变化
0_1_12:将预设文件放到Resources文件夹中
resources.asserts出现了。
sharedassets1.assets文件小很多了,感觉像是移动到resources.asserts里面了,看了一下内容好像还真是。
这部分内容一开始在sharedassets1.assets文件里面,现在在resources.asserts里面了。
0_1_13:项目中的其他场景不包括在打包的内容中
打包后其他Level都不见了
八、场景加载替换测试:
测试打包的文件levelN能否被替换,能替换的话,通过这种方式就能替换场景了,某种程度上。
先做一个加载场景的代码和界面
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class LoadScene : MonoBehaviour
{
public InputField sceneNameInput;
public Toggle IsAsyncToggle;
public Text ResultText;
public string sceneName;
Stack<Scene> scenes = new Stack<Scene>();
public void LoadClick()
{
sceneName = sceneNameInput.text;
if (IsAsyncToggle.isOn)
{
StartCoroutine(LoadAsync(sceneName));
}
else
{
Load(sceneName);
}
}
public void UnloadClick()
{
StartCoroutine(UnloadAsync());
}
public void ShowLog(string txt)
{
ResultText.text = txt;
}
public void Load(string sname)
{
try
{
float start = Time.time;
Debug.Log(sname);
SceneManager.LoadScene(sname, LoadSceneMode.Additive);
float usedTime = Time.time - start;
ShowLog("Load:" + sname + "|Time:" + usedTime);
}
catch (System.Exception ex)
{
ShowLog(ex.ToString());
}
}
public IEnumerator LoadAsync(string sname)
{
float start = Time.time;
Debug.Log(sname);
AsyncOperation op=SceneManager.LoadSceneAsync(sname, LoadSceneMode.Additive);
while (op.isDone == false)
{
Debug.Log("progress:" + op.progress);
yield return null;
}
float usedTime = Time.time - start;
Scene scene = SceneManager.GetSceneByName(sname);
scenes.Push(scene);
ShowLog("LoadAsync:" + sname + "|Time:" + usedTime);
}
public IEnumerator UnloadAsync()
{
float start = Time.time;
//Scene scene = SceneManager.GetSceneByName(sname);
if (scenes.Count>0)
{
Scene scene = scenes.Pop();
AsyncOperation op = SceneManager.UnloadSceneAsync(scene);
while (op.isDone == false)
{
Debug.Log("progress:" + op.progress);
yield return null;
}
float usedTime = Time.time - start;
ShowLog("UnloadAsync:" + scene.name + "|Time:" + usedTime);
}
else
{
ShowLog("scenes.Count ==0");
}
}
}
0_2:基准打包程序、能够运行中加载其他场景
0_2_1:修改场景1,添加Cube
比较:
如果我把差异的两个文件都替换过来,老的打包也就变成了新的打包了。那应该是可以的。
但是如果只替换了level1会怎样?
测试结果是,也是可以的。可以再老的包里面加载新的模型了。
这个测试是用来确认,能够通过scene的方式存储,替换场景中的模型。假如通过Scene加载模型的方式是最快的话。
刚刚的是简单Cube,如果是fbx模型呢?老的项目中本来没有的fbx模型。
0_2_2:添加一个fbx的模型
level1修改了,sharedassets1.asserts修改了,增加了一个sharedassets1.asserts.resS了。
把这三个替换过去,可以加载fbx模型。
0_2_3:添加材质、设置材质、上颜色
和0_2_2比较:
sharedassets1.asserts和level1都复制,可以。
只复制sharedassets1.asserts则会崩溃。
只复制level1,则fbx模型消失。
0_2_4:增加贴图
只复制sharedassets1.asserts.resS:不知道什么情况
再复制sharedassets1.asserts:崩溃
再复制level1:好了。
只复制level1:有贴图的模型没有显示
0_2_5:材质参数(颜色等)修改
Material是存在sharedassets1.asserts里面?
Texture是存在.resS里面?
0_2_6:项目添加脚本
添加一个模型旋转的脚本
public class RotateSelf : MonoBehaviour
{
public Vector3 Speed = new Vector3(0, 0, 0);
public Transform t;
void Start()
{
t = this.transform;
}
// Update is called once per frame
void Update()
{
t.Rotate(Speed, Space.Self);
}
}
和0_2_5比较:
C#代码编译为dll
globalgamemanagers.asserts保存类列表吗?
0_2_7:脚本代码修改
0_2_8:场景添加脚本
和0_2_7比较
只复制sharedassets1.asserts:没有效果
只复制level1:可以
2个都复制:可以
和0_2比较
需要复制globalgamemanagers外的所有文件
0_2_9:场景中脚本参数修改
level1修改了,
替换level1后,可以了。
0_2_10:场景中脚本参数修改
和0_2_9比较
0_2_11:Shader添加项目中
应该和前面的0_2_3之前测试的,那时有点急了,一次多步。
0_2_12:Shader的Material添加项目中
0_2_13:Material添加到场景中
复制sharedassets1.asserts就行
0_2_14:Shader代码修改
复制sharedassets1.asserts就行
0_2_15:场景2中也加上fbx1模型
这个应该接在0_2_2后面的
0_2_16:场景3中加上fbx2模型
0_2_17:场景4中加上fbx2模型
感觉像是fbx模型第一次放到哪个场景中,则存储在哪个场景的shadredasserts.asserts里面
0_2_18:修改模型预设的内容,场景不变
预设的内容是保存在level中吗?
总结:预设、材质参数、脚本参数保存在level中,材质、模型保存在shadredasserts.asserts中,贴图保存在shadredasserts.asserts.resS中
大概这样。
九、模型加载打包测试:
测试内容:内存占用、加载速度、加载流畅度
测试项:
1:基准打包,项目组有模型,场景中没有模型
添加脚本,程序运行过程中,应该是先加载场景,再运行脚本的吧,脚本Start运行的时间是多少
打包前Editor:
打包后
1_0:去掉启动页面后:
内存情况:刚启动38.5MB,慢慢增加,大概30s后稳定在45MB左右
第2列是CPU,第3列是GPU,这台电脑是家里的小米笔记本(GeForceMX150)。
后来测试过程中,发现有时候GPU100%了,原本最初这个测试7%左右的,现在大部分25%了。另外现在电池快没电了。
本来从7%变成25%以为是Update中更新时间信息代码导致的,结果去掉后发现不是。
多次打开相同的程序,GPU使用率会被分散,如4个时是25%左右,6个时是15%左右了。
1_0_1:添加RuntimeProfiler功能,显示运行时的状态信息
参考:https://resources.unity.com/unitenow/onlinesessions/capturing-profiler-stats-at-runtime
Editor和Builded后的参数,*是不支持的参数。
1_0_2:去掉天空盒子
1_1:场景中添加模型fbx1.fbx
1_1_0:场景中添加模型fbx1.prefab的一部分(Cube)
虽然内存还是增加到36MB了,但是从打包信息来看,虽然和上面的打包fbx1.FBX都有,但是这个fbx1.FBX应该只有Cube打包进来了。
------------
本来想用Profiler.GetRuntimeMemorySizeLong获取一个模型的内存占用情况,结果发现无论多大的模型(GameObject占用都是28KB)
然后用3dmax把1000个茶壶塌陷为一个,导入模型,结果导入了25分钟都没结束。之前没有塌陷的模型导入很快的。干嘛了?
100个茶壶塌陷的导入挺快的。
1_1_1:场景中只留下fbx1.fbx中的teapot,加上性能参数界面
Editor
打包后
Editor中,teapot的内存是266kb,打包后运行是78kb,打包中的fbx1.fbx是78.4kb,也就是打包是是多少,运行后内存大概也是多少。
1_1_2:场景中保留fbx5.fbx,一个有11个茶壶的模型塌陷成的比较大的模型。
Editor
Runtime
2.84MB->857.23KB,打包中是857.7KB
266*11/1024=2.857MB,78*11=858,78.4*11=862.4
1_1_3:用fbx1中的茶壶,复制10份,留11个茶壶在场景中
1_1_4:用fbx1中的茶壶,复制1000个茶壶在场景中
这是的MainThread已经是60ms左右了,那fps=1000/60=20了。
从资源管理器来看,占有内存是有所提高,不明显,56.3MB->58.8MB。
性能参数里面的Total Memory从144.71MB/36.6MB->146.24MB/40.11MB,提升不明显。
总之结论是,相同模型无论拷贝多少份,实际上在打包和内存中都只是占有了一份的空间,大体上。
DrawCall会增加,但是内存不会增加,这个和《Unity游戏优化中的》3.5.2里面写的一致。
3.5.2:通常,渲染一个、十个或一百万个相同对象,消耗的内存是相同的,因为它们都引用相同的网格数据。在这种情况下,对象之间的唯一区别是每个对象的变换。
Transform是不同的,Transform、MeshRender、MeshFilter还是会占用一些空间的。
1_1_5:2K个茶壶
这里的MainThread有500ms了,那帧率就只有2了。
1k是20,2k是2。这个有意思
1_1_6:fbx1作成预设,并留在场景中
和不是预设的情况一样,1_1_0
1_1_7:fbx1里面的teapot做出预设,并留在场景中。
和不是预设的情况一样,1_1_1,
1_1_8:代码引用了模型预设fbx1。
和1_1_0的情况一样,
99.6 kb 0.2% Assets/Models/fbx/fbx1.FBX
1_1_9:代码引用了模型预设teapot。
和1_1_1的情况一样,
78.4 kb 0.1% Assets/Models/fbx/fbx1.FBX
0.3 kb 0.0% Assets/Models/Prefabs/Teapot001.prefab
1_1_10:fbx1.fbx放到Resources里面
和1_1_0的情况一样
99.6 kb 0.2% Assets/Resources/Models/fbx1.FBX
1_1_11:fbx1.prefab放到Resources里面
和1_1_0的情况一样
98.6 kb 0.2% Assets/Models/fbx/fbx1.FBX
1.0 kb 0.0% Assets/Resources/Models/Prefabs/fbx1.prefab
1_1_12:teaport.prefab放到Resources里面
和1_1_1的情况一样,
78.4 kb 0.1% Assets/Models/fbx/fbx1.FBX
0.3 kb 0.0% Assets/Resources/Models/Prefabs/Teapot001.prefab
1_1_13:fbx1.fbx放到Scene2里面,没有在Resources里面
和1_1_0的情况一样
98.6 kb 0.2% Assets/Models/fbx/fbx1.FBX
0.3 kb 0.0% Assets/Models/Prefabs/Teapot001.prefab
1_1_14:read/write=true
在1_1_2的基础上,设置fbx5的read/write=true。
1.0 mb 2.0% Assets/Models/fbx/fbx5.FBX
857.7Kb->1MB
运行后的模型也是增加了,1.03MB,差别不大嘛?
1_1_15:模型压缩 High
1MB->433.8 kb 0.8% Assets/Models/fbx/fbx5.FBX
44%的压缩率?
运行后占用内存不变。
1_1_16:模型压缩 Medium
514.7 kb 1.0% Assets/Models/fbx/fbx5.FBX
1_1_17:模型压缩Low
857.7 kb 1.6% Assets/Models/fbx/fbx5.FBX
哦,这么看来前面的其实就是Low了。
Off:1.03MB
Low:857.7Kb
Medium:514.7Kb
High:433.8KB
合并模型
十、模型加载速度测试
1.在Scene中
2.从项目文件中实例化
3.从预设中实例化
4.从Resource中实例化
5.从其他Scene中加载
6.从AssetBundle实例化
7.从网络实(本地)例化
8.从网络实(远程)例化
十一、物理测试