内容网上搜集,旨在记录整理Unity的面试题,为面试做好准备。白底黑字看的太难受了,加点颜色。
目录
AssertBundle基本理论
AssertBundle资源加载框架设计
Awake()和Start区别
Csharp属性访问器
Profile性能优化基础
SerializeField的用法
UGUI事件系统
UGUI渲染层级
UI框架设计
Unity5如何进行AssetBundle
Unity中Update和FixUpdate和LaterUpdate
Unity事件管理器
最简单的AssertBundle打包方式:
Unity需要加载模型经常需要AssertBundle。
Unity中模型文件大多是.prefab,加载prefab的方式只有两个:
这时,assertBundle发挥除了很大用处。通过WWW加载AssertBundle。接下来的问题就是如何打包AssertBundle,利用
public static AssetBundleManifest BuildAssetBundles
(string outputPath, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform);
在Editor文件夹下创建脚本,放入脚本,这时才会出现AssertBundle选项
AssertBundle功能开发好后,怎么用呢???
AssertBundle需要对资源进行分组:
按逻辑实体进行分组:
按资源类型分组:
按照使用分组:
解包:
IEnumerator LoadBundle(string url)
{
WWW www = new WWW(url);
yield return www;
if(www.error != null)
{
Debug.LogError();
yield break;
}
}
资料:
实力封装:Unity打包AssetBundle(番外篇)
http://实力封装:Unity打包AssetBundle(二)
实力封装:Unity打包AssetBundle(一)
目的:
生成AssertBundle文件的基本流程:
资料
unity 资源加载框架设计
Awake()在Monobehaviour创建后立刻被调用,Start()在MonoBehaviour创建后在该帧update前执行。
void Awake()
{
//初始化函数,主要用来创建变量
//不可执行协同程序
}
void Start()
{
}
Awake方法的调用顺序在object之间时随机的,当所有对象的Awake方法都调用完成后,才会执行第一个Start方法,Awake方法就像构造函数一样,Awake方法不论脚本是否启用,都会调用
类成员包括变量和方法,希望其他类访问成员变量,则定义为共有public,那么这个成员变量就可随意访问,但是不利于数据安全性。
c#通过属性特性读取和写入字段【成员变量】,而非直接读取和写入,借此提供对类中字段的保护,属性作为c#面相对象技术中封装性的体现。
属性和字段的区别:
使用属性的情况:
使用字段的情况:
设计字段是为了便于内部方法使用,而尽量与外界隔绝;设计属性考虑的是方便外界的使用,但是不让外界知道的数据一律不给。
Profile介绍:
CPU:
A. WaitForTargetFPS:
Vsync(垂直同步)功能所,即显示当前帧的CPU等待时间
B. Overhead:
Profiler总体时间-所有单项的记录时间总和。用于记录尚不明确的时间消耗,以帮助进一步完善Profiler的统计。
C. Physics.Simulate:
当前帧物理模拟的CPU占用时间。
D. Camera.Render:
相机渲染准备工作的CPU占用量
E. RenderTexture.SetActive:
设置RenderTexture操作.
底层实现:
F. Monobeaviour.OnMouse_ :
用于检测鼠标的输入消息接收和反馈,主要包括:SendMouseEvents和DoSendMouseEvents。(只要Edtor开起来,这个就会存在)
G. HandleUtility.SetViewInfo:
仅用于Editor中,作用是将GUI和Editor中的显示看起来与发布版本的显示一致。
H. GUI.Repaint:
GUI的重绘(说明在有使用原生的OnGUI)
I. Event.Internal_MakeMasterEventCurrent:
负责GUI的消息传送
J. Cleanup Unused Cached Data:
清空无用的缓存数据,主要包括RenderBuffer的垃圾回收和TextRendering的垃圾回收。
K. Application.Integrate Assets in Background:
遍历预加载的线程队列并完成加载,同时,完成纹理的加载、Substance的Update等.
L. Application.LoadLevelAsync Integrate:
加载场景的CPU占用,通常如果此项时间长的话70%的可能是Texture过长导致.
M. UnloadScene:
卸载场景中的GameObjects、Component和GameManager,一般用在切换场景时.
N. CollectGameObjectObjects:
执行上面M项的同时,会将场景中的GameObject和Component聚集到一个Array中.然后执行下面的Destroy.
O. Destroy:
删除GameObject和Component的CPU占用.
P. AssetBundle.LoadAsync Integrate:
多线程加载AwakeQueue中的内容,即多线程执行资源的AwakeFromLoad函数.
Q. Loading.AwakeFromLoad:
在资源被加载后调用,对每种资源进行与其对应用处理.
GPU:
A. Device.Present:
device.PresentFrame的耗时显示,该选项出现在发布版本中.
B. Graphics.PresentAndSync:
GPU上的显示和垂直同步耗时.该选项出现在发布版本中.
C. Mesh.DrawVBO:
GPU中关于Mesh的Vertex Buffer Object的渲染耗时.
D. Shader.Parse:
资源加入后引擎对Shader的解析过程.
E. Shader.CreateGPUProgram:
根据当前设备支持的图形库来建立GPU工程.
Memory Profiler:
A. Used Total:
当前帧的Unity内存、Mono内存、GfxDriver内存、Profiler内存的总和.
B. Reserved Total:
系统在当前帧的申请内存.
C. Total System Memory Usage:
当前帧的虚拟内存使用量.(通常是我们当前使用内存的1.5~3倍)
D. GameObjects in Scene:
当前帧场景中的GameObject数量.
E. Total Objects in Scene:
当前帧场景中的Object数量(除GameObject外,还有Component等).
F. Total Object Count:
Object数据 + Asset数量.
Detail Memory Profiler:
A. Assets:
Texture2d:记录当前帧内存中所使用的纹理资源情况,包括各种GameObject的纹理、天空盒纹理以及场景中所用的Lightmap资源.
B. Scene Memory:
记录当前场景中各个方面的内存占用情况,包括GameObject、所用资源、各种组件以及GameManager等(天般情况通过AssetBundle加载的不会显示在这里).
C. Other:
ManagedHeap.UseSize:代码在运行时造成的堆内存分配,表示上次GC到目前为止所分配的堆内存量.
SerializedFile(3):
WebStream:这个是由WWW来进行加载的内存占用.
System.ExecutableAndDlls:不同平台和不同硬件得到的值会不一样。
优化的关键点:
A. CPU-GC Allow:
关注原则:1.检测任何一次性内存分配大于2KB的选项 2.检测每帧都具有20B以上内存分配的选项.
B. Time ms:
记录游戏运行时每帧CPU占用(特别注意占用5ms以上的).
C. Memory Profiler-Other:
D. Memory Profiler-Assets:
如果a是公有的序列化变量。
public int a;
[HideInInspector]
public int a;
这样a可以在程序中被代码赋值,但不会在面板中看到,也不能手动设置赋值。
[SerializeField]
private int a;
[HideInInspector][SerializedField]
private int a;
public int b
{
get{return a;}
}
[HideInInspector][SerializedField]
private int a;
public int b
{
get{return a;}
set{a = value;}
}
Unity UGUI的可触发事件系统:
继承基础接口实现:
创建ClickObject脚本,继承MonoBehaviour和PointerClickHander
public ClickObject : MonoBehaviour,IPointerClickHandelr{
void Start(){
}
void Update(){
}
public void OnPointerClick(PointerEventData eventData){
Debug.Log("click");
}
}
实现public void OnPointerClick(PointerEventData eventData)
创建名为 Panel_IPointer的空白对象,并且把ClickObject脚本挂在对象上
启动。点击Panel_IPointer对象,Console输出
Unity3D编辑器操作设置实现:
Button提供OnClick操作,实现事件
步骤一:创建c#脚本,添加OnTestClick()
步骤二:创建Empty对象,接受和响应点击事件,创建名为Panel的UI对象,于触发点击事件。
步骤三:Panel对象添加EventTrigger组件," Add New" -> 选择" PointerClick"。
将Empty对象拖拽到触发者位置。然后点击"No Function"选择我们写在Test脚本中的OnTestClick事件。
Unity中的渲染顺序自上而下大致分为三层。 分别是Camera - > Sorting Layer - > Sorting order
最高层为Camera层,可以在Camera的depth那里设置,设置之后,图形的渲染顺序就是先绘制depth低的相机下的物体,
再绘制depth高的相机下的物体,也就是说,depth高的相机会覆盖depth低的相机(具体的覆盖关系有don't clear, solid color等等几种)
UGUI渲染模式:Canvas -- Render Mode:ScreenSpace-Overlay
此模式下不依赖摄像机Camera的渲染
Hierachy下存在各层级遮挡,
改变控件之间的层级关系
同一canvas下:
改变控件transform的SiblingIndex,
transform.GetSiblingIndex();
transform.SetSiblingIndex(int index); //index值越大,越后渲染,层级越大,越显示在前面
不同Canvas下:
设置Canvas下的Sort Order //Sort Order值越大,越后渲染,层级越大,越显示在前面
渲染顺序与hierarchy面板里物体的摆放顺序也有关
面板里越靠上的物体越先被渲染,越后被渲染的显示在越前面。
注意:
如果是多个Canvas的渲染先后顺序 http://blog.csdn.net/huutu/article/details/43636241
调Canvas下面有一个Sort Order值,默认为0,越大越在后面。
创建任意UGUI元素时自动生成一个Canvas物体,Canvas下的所有物体从上往下渲染,即排在下面的会遮盖排上面的。同理,子元素会覆盖父元素。
在游戏运行中如何修改UGUI的显示层级?
在代码中调整该元素的层级位:使用RectTransform类的函数。
Canvas的渲染模式【Render Mode】:ScreenSpace Overlay,ScreenSpace Camera,World Space
ScreenSpace-Overlay:
1.遵循刷油漆规则
2.依次由Render Camera的Depth值、Sorting Layer先后顺序、Order in Layer值决定
Render Camera不同时,由Render Camera的Depth决定
Render Camera相同时,由Sorting Layer先后顺序决定
Render Camera相同时,Sorting Layer相同,由Order in Layer值决定。
UI框架的设计:
UI框架用于管理场景中的所有面板,控制面板之间的切换,加快开发进度,提高代码质量。【主要在于管理面板】
实现思路:
实现步骤:
缺点明显,使用栈用来存储场景中依次打开的界面,只能够依次从栈顶界面开始关闭。
OnEnter()->OnPause()->OnResume()->OnExit()
UI框架类图:
UIPanelType :存储面板路径和类型
UIManager :
panelPathDict:Dictionary
panelDict:Dictionary
panelStack:Stack
BasePanel:
开始创建一个AssetBundle,从项目文件夹中选择一个想要的自愿的对象,
在Inspector检查器的底部是AssetBundle菜单,
如果资源是第一次打包,请不要设置第二个附加选项,否则打包报错。
默认情况下,AssetBundle名称设置为None,这意味着资源不能进行AssetBundle打包。
如果还没有定义包,单机new.输入包名。这样可以创建一个或者多个AssetBundle
FixedUpdate () 和 Update () :
Monobehaviour激活后,在每一帧被调用,实现更新。
Update()每一帧的时间不固定,即第一帧与第二帧的时间t1和第三帧与第四帧的时间t2不一定相同。FixedUpdate()每帧与每帧之间相差的时间是固定的.
FixUpdate是按照帧进行更新的。
通常
FixedUpdate()
{
i++;
time += Time.deltaTime;
Debug.Log(“这是第”);
}
c#语言本身具有一个事件管理器event delegate,为何需要自己建立事件管理器??虽然不是必须,
但是c#的delegate本质是回调函数。因为回调函数是双向引用关系,而事件管理器就是为了让游戏内部逻辑
的类和类之间的关系结构变成单向引用关系,是类和类之间的降低耦合度,大都是通过事件类型【字符串】进行内部沟通。
EventManager事件管理器:
主要函数:添加监听,移除监听,调度事件
主要变量:事件list,事件结构,回调委托
MyEvent:事件类型:
public class MyEvent{
private EventType type;
private string content;
}
public enum EventType{
EVENT_0 = "UI";
//。。。。
}
public class EventManager : MonoBehaviour{
private Dictionary eventDictionary; //字典
}
资料:
https://blog.csdn.net/wanzhihui0000/article/details/52839631
http://www.newbieol.com/information/1048.html
https://www.jianshu.com/p/bf82beb41f7f
http://www.cnblogs.com/RainPaint/p/10124051.html
https://blog.csdn.net/u013108312/article/details/52351826
https://blog.csdn.net/VRunSoftYanlz/article/details/80862879
http://www.manew.com/blog-52341-2366.html