111.
[动画系统]如何将其他类型的动画转换成关键帧动画?
动画->点缓存->关键帧
112.
[动画]Unity引擎Mecanim动画系统功能优点?
答:
l 简单化对类人角色动画设计与功能实现的工作流程。
l Mecanim动画系统使用一个可视化编程工具来管理动画之间复杂的交互。
l 对完成绑定骨骼的类人角色,能够对身体不同的地方使用不同的逻辑进行动画控制。
l 可以在角色动画播放过程中添加动画事件。
l 人形动画骨骼动画可重复使用。
113.
[UI]请简述NGUI中Panel和Anchor的作用 。
答:Panel是一个容器,它将包含所有UI小部件,并负责将所包含的部件组合。
Anchor是NGUI中屏幕分辨率的自适应性,来适应不同的分辨率的屏幕显示。
注:
114.
[碰撞]怎么判断两个平面是否相交?不能用碰撞体,说出计算方法。
答:以平面任意两点,取两平面法向量,链接两点线段,线段是否与法向量的夹角来判断是否平行。
法向量如果平行,看线段与法向量的夹角,如果平行则两平面重合,判断边界是否相交。
如果平行,且有夹角,说明不重合两平面平行,一定不相交。
如果法向量不平行,将该线段的在两平面投影方向上的射线判断与平面的边界条件,如果两条射线的交点都在边界内,则相交,否则不相交。
注:
115.
[碰撞]MeshCollider和其他Collider的一个主要不同点?
答:MeshCollider是网格碰撞器,对于复杂网状模型上的碰撞检测,比其他的碰撞检测精确的多,但是相对其他的碰撞检测计算也增多了,所以一般使用网格碰撞也不会在面数比较高的模型上添加,而会做出两个模型,一个超简模能表示物体的形状用于做碰撞检测,一个用于显示。
MeshCollider有Mesh属性
116.
[碰撞]Unity3d中的碰撞器和触发器的区别?
答:
碰撞器物体不能互相进入到对方内部,触发器可以。
触发器角色控制器可以使用,碰撞器中不能使用。
触发器没有物理属性了,碰撞器可以有力存在。
碰撞器调用OnCollisionEnter/Stay/Exit函数,触发器调用OnTriggerEnter/Stay/Exit函数。
117.
[碰撞]物体发生碰撞的必要条件。
答:两个物体都必须带有碰撞器(Collider),其中一个物体还必须带有Rigidbody刚体。
注:动的物体,你希望发生碰撞效果的物体要带能接受物理引擎的操作,最常见的就是挂载Rigidbody组件。
118.
[碰撞]CharacterController和Rigidbody的区别?
答:CharacterController自带胶囊碰撞器,里面包含有刚体的属性;
Rigidbody就是刚体,使物体带有刚体的特征。
注:
119.
[碰撞]当一个细小的高速物体撞向另一个较大的物体时,会出现什么情况?如何避免?
答:穿透(碰撞检测失败)。将物体移动放在FixedUpdate中,尽量使用物理引擎自己的移动方法。
避免的方法:把刚体的实时碰撞检测打开Collision
Detection修改为Continuous
Dynamic
注:
120.
[碰撞]在unity3d中物体发生碰撞的整个过程中,有几个阶段,分别列出对应的阶段函数?
答:
主要是三个阶段:
1.Collider.OnCollisionEnter 进入碰撞,当collider/rigidbody开始触动另一个rigidbody/collider时OnCollisionEnter被调用。
2.Collider.OnCollisionStay
逗留碰撞,每个collider/rigidbody触动rigidbody/collider,将在每帧调用OnCollisionStay。通俗的说,一个碰撞器或刚体触动另一个刚体或碰撞器,在每帧都会调用OnCollisionStay,直到它们之间离开不接触。
3.Collider.OnCollisionExit 退出碰撞,当 collider/rigidbody停止触动另一个
rigidbody/collider时,OnCollisionExit被调用。
121.
[动画]一个简单的游戏,怪物会走动\攻击\死亡,游戏角色会走动,跳跃\攻击\格挡\死亡,还会接受玩家从输入端输入的指令,NPC会走动,他们彼此之间可以互相通信.请画出以上三种角色的UML图示.
答:
122.
[动画]请描述游戏动画有哪几种,以及其原理?
答:主要有关节动画、单一网格模型动画(关键帧动画)、骨骼动画。
1.关节动画:把角色分成若干独立部分,一个部分对应一个网格模型,部分的动画连接成一个整体的动画,角色比较灵活,Quake2中使用这种动画。
2.单一网格模型动画由一个完整的网格模型构成,在动画序列的关键帧里记录各个顶点的原位置及其改变量,然后插值运算实现动画效果,角色动画较真实。
3.骨骼动画,广泛应用的动画方式,集成了以上两个方式的优点,骨骼按角色特点组成一定的层次结构,有关节相连,可做相对运动,皮肤作为单一网格蒙在骨骼之外,决定角色的外观,皮肤网格每一个顶点都会受到骨骼的影响,从而实现完美的动画。
123.
[动画]反向旋转动画的方法是什么?
答:反转动画,将动画的播放速度调到-1。
124.
[动画]写出Animation的五个方法。
答:AddClip 添加剪辑、Blend 混合、Play 播放、Stop 停止、Sample 采样 、CrossFade淡入淡出切换动画、IsPlaying是否正在播放某个动画
125.
[动画]动画层(AnimationState Layers)的作用是什么?
答:动画层作为一个具有层级动画编辑概念的工具,可以用来制作和处理任何类型的动画。202,203题
126.
[动画]Itween插件的作用是什么,Itween作用于世界坐标还是局部坐标,请列举出3个其常用方法?
答:ITween是补间动画的一个插件,主要作用就是给出开始、结束的值、时间,此插件实现各种动画,晃动,旋转,移动,褪色,上色,音量控制等等。
方法: 1.MoveTo 物体移动
2.ColorTo:随着时间改变对象的颜色组
3.LookTo:随时间旋转物体让其脸部朝向所提供的Vector3或Transform位置
127.
[动画]什么是法线贴图 、CG动画 ?
答:
法线贴图:是一种特殊的纹理,可以应用在3D表面,让低模呈现出更明显的凹凸效果。一
般应用在CG动画、美术效果要求较高的单机游戏
CG动画:游戏中的CG动画其实是用3D模拟引擎制作的游戏短片,一般画面效果比较真实。
128.
[线程和协程]Unity3D是否支持写成多线程程序?如果支持的话需要注意什么?(?)
答:Unity支持多线程,如果同时要处理很多事情或者与Unity的对象互动小可以用thread,否则使用coroutine。
注意:1.虽然支持多线程,但是仅能从主线程中访问Unity3D的组件,对象和Unity3D系统调用,所以如果使用的话需要把组件中的数值传到开启的新线程中。
2.C#中有lock这个关键字,以确保只有一个线程可以在特定时间内访问特定的对象
129.
[线程和协程]Unity3D的协程和C#线程之间的区别是什么?
答:多线程程序同时运行多个线程,除主线程之外的线程无法访问Unity3D的对象、组件、方法,而在任一指定时刻只有一个协程在运行。
130.
[线程和协程]什么是协同程序?
答:在主线程运行时同时开启另一段逻辑处理,来协助当前程序的执行。使用户可以编写更灵活的程序来控制运动、序列以及对象的行为。
131.
[3D数学]四元数是什么?主要作用什么?对欧拉角的优点是什么?
答:所谓四元数,就是把4个实数组合起来的东西。4个元素中,一个是实部,其余3个是虚部
作用:四元数用于表示旋转
优点:
1)能进行增量旋转
2)避免万向锁
3)给定方位的表达方式有两种,互为负(欧拉角有无数种表达方式)
四元数不会有欧拉角存在的 gimbal lock 问题[万向节死锁]
四元数由4个数组成,旋转矩阵需要9个数
两个四元数之间更容易插值
四元数、矩阵在多次运算后会积攒误差,需要分别对其做规范化(normalize)和正交化 (orthogonalize),对四元数规范化更容易
与旋转矩阵类似,两个四元组相乘可表示两次旋转
132.
[摄像机]在场景中放置多个Camera并同时处于活动状态会发生什么?
答:游戏界面可以看到很多摄像机的混合。
133.
[摄像机]Unity摄像机有几种工作方式,分别是什么?
答:正交和透视。
正交无法看到一个物体距离自己有多远,或者远近的变化,物体也不会随着距离而收缩,所以一般做2D游戏或者是UI时会使用正交摄像机。
透视一般看物体会随着距离有大小的变化,一般3D游戏里经常使用这种摄像机。
134.
[预制件]Prefab的作用?如何在移动环境的设备下恰当地使用它?
答:Prefab是预制件(预制物),一般当游戏中需要频繁创建一个物体时,使用预制物可以节省内存,方便创建,方便对游戏物体进行操作,方便对属性进行修改。
135.
[预制件]unity当需要频繁创建一个物体对象时,怎样减少内存?
答:动态加载再实例化,如果自己不主动清理内存的话,再次加载不会增加内存的,会自动去取之前已经加载好的assets,如果这一个assets你都嫌多的话,那你只能减资源了,比如,模型面数,纹理尺寸等
136.
[ Shader]写出光照计算中的diffuse的计算公式
答:实际光照强度l=环境光(lambient)+漫反射光(Idiffuse)+镜面高光(lspecular)
环境光:lambient=环境光强度(Aintensity)*环境光颜色(Acolor)
漫反射光:ldiffuse=镜面光照强度(Dintensity)*镜面光颜色(Scolor)*(光的反射向量(R).观察者向量(V))^镜面光指数(n)
137.
[ Shader]MeshRender中material和shader的区别?
答:MeshRender是模型渲染的组件,有此组件物体才能显示出来
Material是材质球,实际就是shader的实例,并进行赋值,贴图、纹理、颜色等。
Shader是着色器,实际上是一段程序,还可以用来实现一些仅靠贴图不容易实现的效果,如玻璃。
Shader大致分为:1.表面着色器
2.顶点和片元着色器
3.固定功能着色器
138.
[ Shader]alpha blend工作原理
答:Alpha Blend是 实现透明效果,Color = 原颜色*alpha/255+目标色*(255-alpha)/255
139.
[ Shader]光照贴图 的优势是什么?
答:1.使用光照贴图比使用实时光源渲染要快
2.可以降低游戏内存消耗
3.多个物体可以使用同一张光照贴图
140.
[ Shader]Vertex Shader是什么,怎么计算?
答:顶点着色器:顶点着色器是一段执行在GPU上的程序,用来取代fixed pipeline中的
transformation和lighting,Vertex Shader主要操作顶点。
Vertex Shader对输入顶点完成了从local space到homogeneous space(齐次空间)的变换过程,homogeneous space即projection space的下一个space。在这其间共有world transformation, view transformation和projection transformation及lighting几个过程。
141.
[ Shader] Unity3d提供了几种光源,分别是什么?
答:4种,Directionl light ,Point Light ,Spot Light,Area Light
平行光:Directional Light
点光源:Point Light
聚光灯:Spot Light
区域光源:Area Light
142.
[Unity]物理更新一般在哪个系统函数里?
答:FixedUpdate,每固定帧绘制时执行一次,和Update不同的是FixedUpdate是渲染帧执行,如果你的渲染效率低下的时候FixedUpdate调用次数就会跟着下降。FixedUpdate比较适用于物理引擎的计算,因为是跟每帧渲染有关。Update就比较适合做控制。
143.
[Unity]OnEnable、Awake、Start运行时的发生顺序?哪些可能在同一个对象周期中反复的发生?
答:Awake –>OnEnable->Start
OnEnable在同一周期中可以反复地发生
Awake用于在游戏开始之前初始化变量或游戏状态。在脚本整个生命周期内它仅被调用一次.Awake在所有对象被初始化之后调用,所以你可以安全的与其他对象对话或用诸如GameObject.FindWithTag这样的函数搜索它们。每个游戏物体上的Awke以随机的顺序被调用。因此,你应该用Awake来设置脚本间的引用,并用Start来传递信息。
Start在脚本的生命周期中只被调用一次。它和Awake的不同是Start只在脚本实例被启用时调用。你可以按需调整延迟初始化代码。Awake总是在Start之前执行。这允许你协调初始化顺序。
但Start可以作为协程,达到在同一周期调用多次的效果。不过实质上依然是调用一次。
144.
[Unity]接上题,在上题当中假设有一物体,一个脚本挂了两次,请指出Awake的执行顺序。
答:ExcutionOrder有关,不设定顺序的时候初始化Start的顺序不确定。
145.
[Unity]Unity3d脚本从唤醒到销毁有着一套比较完整的生命周期,请列出系统自带的几个重要的方法。
答:
方法名(按脚本声明周期排列)
作用
备注
Editor
Reset
重置为默认值。
在用户点击见识版面的Reset按钮或者首次添加该组件时被调用。此方法只在编辑模式下被调用。
Initialization
Awake
OnEnable
Start
Start在behaviour的生命周期中只被调用一次。它和Awake的不同是Start只在脚本实例被启用时调用。你可以按需调整延迟初始化代码。Awake总是在Start之前执行。这允许你协调初始化顺序。
Start仅在Update方法第一次被调用前调用。
Physics
FixedUpdate
处理Rigidbody时,需要用FixedUpdate代替Update。例如:给刚体加一个作用力时,你必须应用作用力在FixedUpdate里的固定帧,而不是Update中的帧。(两者帧长不同)
如果固定时间步长小于实际帧更新时间,那么每一帧物理周期将会可能发生不止一次。
yield WaitForFixedUpdate
Internal physics update
OnTriggerXXX
OnCollisionXXX
Input events
OnMouseXXX
Game logic
Update
如果一个协成之前已经yield了,但是现在由于恢复了,那么将执行剩下的部分。
yield null
yield WaitForSeconds
yield WWW
yield StartCoroutine
Internal animation update
LateUpdate
Scene rendering
OnWillRenderObject
如果对象可见每个相机都会调用它。此函数在消隐过程中被调用,在渲染所有被消隐的物体之前被调用。你可以用它来创建具有依赖性的纹理并且只有在被渲染的物体可见时才更新这个纹理。举例来讲,它已用于水组件中。
OnPreCull
消隐决定哪个物体对于相机来说是可见的.OnPreCull仅是在这个过程被调用。
只有脚本被附加到相机上时才会调用这个函数。
OnBecameVisible
OnBecameInvisible
OnPreRender
在相机渲染场景之前被调用。
只有脚本被附加到相机并被启用时才会调用这个函数。
OnRenderObject
OnPostRender
在相机完成场景渲染之后被调用。
只有该脚本附于相机并启用时才会调用这个函数。OnPostRender可以是一个协同程序。
OnRenderImage
Gizmo rendering
OnDrawGizmos
只在编辑模式下调用
GUI
renderingOnGUI
在每一帧更新时调用多次
End of frame
yield WaitForEndOfFrame
Pausing
OnApplicationPause
在程序检测到暂停时,会在帧的结尾处被调用。
Disable/enable
OnDisable
在脚本是失效时被调用,被销毁时也会被调用。如果再启用的话,OnEnable会再一次被调用。
Decommissioning
OnDestroy
OnApplicationQuit
146.
[Unity]物理更新一般放在哪个系统函数里?
答:FixedUpdate因为不受到计算机帧频的影响,所以适合于做物理方面的更新。
147.
[Unity]移动摄像机的动作放在哪个系统函数中,为什么放在这个函数中?
答:LateUpdate,它是在Update结束后才调用。一般来说摄像机的跟随,都是在所有Update操作完成后进行的,以免出现摄像机已经推进了,但是还有角色未刷新的空帧出现。
148.
[Unity]请简述OnBecameVisible及OnBecameInvisible的发生时机,以及这一对回调函数的意义?
答:当物体是否可见切换之时。可以用于只需要在物体可见时才进行的计算。
当renderer(渲染器)在任何相机上都不可见时调用:OnBecameInvisible
当renderer(渲染器)在任何相机上可见时调用:OnBecameVisible
149.
[Unity]Unity3d提供了一个用于保存和读取数据的类(PlayerPrefs),请列出保存和读取整形数据的函数。
答:PlayerPrefs.SetInt()
PlayerPrefs.GetInt()
150.
[动画]动画状态是动画状态机的基本构件。每种状态包含的可能性有哪两种?
答:单独的动画状态,混合树。
151.
[动画]简述一下动画层中权重(Weight )的概念
答:
动画层中的权重是指某个动画层在整个动画中的影响,Weight的取值范围为(0~1)
若权重值为1则此层动画将与整个动画融合
若权重值为0则此层动画与整个动画完全不融合
152.
[动画]简述一下Mecanim动画层中动画层的作用?
答:使用动画层来管理身体不同部分的复杂状态机。比如:你可以使用下半身(动画)层来管理走动/跑动;使用上半身(动画)层来控制攻击/挥手动作。
153.
[动画]简述一下以下代码的功能?
Animator anim
;
int
idle = Animator.StringToHash("Base Layer.Idle");
AnimatorStateInfo
currentBaseStage;
void
Start () {
anim
= GetComponent();
}
void
Update () {
currentBaseStage
= anim.GetCurrentAnimatorStateInfo(0);
if
(currentBaseStage.nameHash == idle && !anim.IsInTransition(0)) {
anim.SetBool("hit",
false);
}
答:判断当前播放的动画名字若是默认层的Idle,并且没有在进行动画切换,则设置hit动画参数为false。
154.
[动画]若想让寻路的物体在Walkable跟Red层可以寻路GetComponent().
areaMask等于几?
答案:9
155.
[动画]若想实现敌人攻击动画播放一半的时候角色减血,可用Mecanim动画系统中的哪个功能处理比较好?
答:动画事件。
156.
[动画]Mecanim动画系统中2DBlendTree与1DBlendTree的区别?
答:
1D是使用一个动画参数来控制blend tree中几个动画判断的融合,
2D是使用两个动画参数来控制blend tree中几个动画判断的融合。
157.
[物理引擎]如何实现把射线碰到的点(hit)转为非主摄像机的屏幕坐标?
答:
public Camera myCamera;
myCamera.WorldToScreenPoint(hit);
158.
[Unity]Unity中的寻路系统属于那种寻路方式?
答:网格寻路。
159.
[Unity]动态加载资源的方式?区别是什么?
答:
1.Resources.Load();
2.AssetBundle
区别:
Resources资源的加载是动态加载内部的,AssetBundle 是动态加载外部的。
Resources是动态内部调用,Resources在编辑环境下是project窗口的一个文件夹,调用里面的资源,可以用Resources类,比如Resources.Load,打包后这个文件夹是不存在的,会统一生成Assets资源。
AssetBundle 是外部调用,要用AssetBundle 首先要先把资源打包为.assetbundle文件,再动态的去加载这个文件,本地或者网络服务器都可以。
WWW读取文件
160.
[Unity]以下哪个函数在游戏进入新场景后会被马上调用?
答: MonoBehaviour.OnLevelWasLoaded
161.
[Unity]如何销毁一个UnityEngine.Object及其子类
答:Destory
162.
[Unity]获取、增加、删除组件的命令分别是什么?
答:获取:GetComponent
增加:AddComponent
没有删除组件只有让组件不生效:enable
163.
[Unity]Application.loadLevel命令是什么?//过时了
答:加载关卡 。
UnityEngine.SceneManagement名称空间下
SceneManager.LoadScene//加载场景
SceneManager.LoadSceneAsync//异步加载场景
164.
[Unity]调试记录到控制台的命令是什么?
答: Debug.Log();
165.
[Unity]LayerMask.NameToLayer()这个方法有什么作用?
答:层索引。射线。
166.
[Unity]localPosition与Position的使用区别?
答:
localPosition:自身位置,相对于父级物体的变换的位置,局部坐标其实就是自身的坐标。
Position:在世界坐标transform的位置,世界坐标是不会变的,一直以世界坐标轴的XYZ为标准。
167.
[Unity]物体自身旋转使用的函数?
答:Transform.Rotate()。
168.
[Unity]现有物体A和物体B,使物体A围绕B旋转并保持物体A的Y轴朝向不变,请写出你的方法。
答:
public class TestAround : MonoBehaviour
{
public GameObject ObjA;
public GameObject ObjB;
Vector3 NormalVector3;//法线
float speed = 5;
void Start()
{
GetNormal(AroundType.Horizontal);
}
private void GetNormal(AroundType aroundType)
{
Vector3 temp = ObjB.transform.position - ObjA.transform.position;
switch (aroundType)
{
case AroundType.Vertical:
NormalVector3=Vector3.Cross(Vector3.forward,temp);
break;
case AroundType.Horizontal:
NormalVector3 =
Vector3.Cross(Vector3.up, temp);
break;
default:
break;
}
}
void Update()
{
Debug.DrawLine(NormalVector3,ObjA.transform.position);
Vector3 temp = ObjB.transform.position - ObjA.transform.position;
Debug.DrawLine(temp, ObjA.transform.position);
Around(ObjA, ObjB);
}
private void Around(GameObject objA, GameObject objB)
{
Quaternion quater=Quaternion.Euler( NormalVector3*Time.deltaTime*speed);
objB.transform.position = quater * objB.transform.position;
}
}
enum AroundType
{
Vertical,
Horizontal
}
169.
[Unity]U3D中用于记录节点空间几何信息的组件名称,及其父类名称。
答:Transform 父类是 Component
170.
[物理引擎]<愤怒的小鸟>给予初速度以后,怎么让小鸟受到重力和空气阻力的影响而绘制抛物线轨迹,说出具体的计算方法。
答:添加刚体使小鸟模拟受到重力和空气阻力影响。不添加刚体的话写受力分析。
设横轴为方向的加速度为ax,垂直轴为ay。
小鸟的Vx,Vy
Vx=Vx+t*ax;(Vx>=0)
Vy=Vy+t*ay;
171.
[物理引擎]Material和Physic Material区别?
答:PhysicMaterial 物理材质:主要是控制物体的摩擦,弹力等物理属性。
Material材质:主要是控制一个物体的颜色,质感等显示。
172.
[物理引擎]Unity3d的物理引擎中,有几种施加力的方式,分别描述出来。
答:rigidbody.AddForce/AddForceAtPosition,都在rigidbody系列函数中。
173.
[物理引擎]什么叫做链条关节?
答:Hinge Joint,可以模拟两个物体间用一根链条连接在一起的情况,能保持两个物体在一个固定距离内部相互移动而不产生作用力,但是达到固定距离后就会产生拉力。
174.
[自动寻路]什么是导航网格( NavMesh)?
答: Unity内一种用于实现自动寻路的网格。
175.
[
Unity]简述Unity3D支持的作为脚本的语言的名称。
答: JavaScript,C#,Boo
176.
[3D数学]向量的点乘、叉乘以及归一化的意义?
答:1)点乘计算两个向量之间的夹角,还可表示某一方向的投影。
2)叉乘得到的是法向量。
3)标准化向量:用在只关系方向,不关心大小的时候。
177.
[3D数学]矩阵相乘的意义及注意点?
答:用于表示线性变换:旋转、缩放、投影、平移、仿射。
注意:矩阵的蠕变:误差的积累。
178.
[Unity引擎]为什么dynamic font在unicode环境下优于static font?
答:Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。
使用动态字体时,Unity将不会预先生成一个与所有字体的字符纹理。当需要支持亚洲语言或者较大的字体的时候,若使用正常纹理,则字体的纹理将非常大。
179.
[Unity引擎]Render的作用?描述MeshRender和SkinnedMeshRender的关系与不同。
答:render是渲染器,渲染器可以使物体显示在屏幕上。
MeshRender是网格渲染,SkinnedMeshRender是蒙皮网格渲染器
180.
[Unity引擎]简述SkinnedMesh的实现原理。
答:骨骼蒙皮动画,模型本身是静态的,是因为通过蒙皮,使模型每个点都有Skin数据,Skin数据包括顶点受到哪些骨骼影响以及这些骨骼影响顶点的权重值,还有动画数据,有了Skin数据的模型就可以根据动画数据进行显示动画了。
181.
[Unity引擎]如何安全的在不同工程间安全地迁移asset数据?三种方法。
答:1)将Assets目录和Library目录一起迁移。
2)导出包。
3)用unity自带的assets Server功能。
182.
[
Unity引擎]Lod是什么,优缺点是什么?
答:LOD是Level of detail简称,意为多层次细节,是最常用的游戏优化技术,LOD技术指根据物体模型的几点在显示环境中所处的位置和重要性,决定物体渲染的资源分配,降低非重要物体的面数和细节度,从而获得高效率的渲染运算。
优点:可根据距离动态的选择渲染不同细节的模型
缺点:增加美工工作量,增大了游戏的容量。
注:精简文字描述。
答:LOD(Level of detail)多层次细节,是最常用的游戏优化技术,LOD技术指根据物体模型的几点在显示环境中所处的位置和重要性,决定物体渲染的资源分配,降低非重要物体的面数和细节度,从而获得高效率的渲染运算。
优点:可根据距离动态的选择渲染不同细节的模型
缺点:增加美工工作量,增大了游戏的容量。
183.
[
Unity]两种阴影判断的方法、工作原理。
答:自身阴影:因物体自身的遮挡而使光线照射不到它上面的某些可见面
工作原理:利用背面剔除的方法求出,即假设视点在点光源的位置。
投射阴影:因不透明物体遮挡光线使得场景中位于该物体后面的物体或区域收不到光照照射而形成的阴影。
工作原理:从光源处向物体的所有可见面投射光线,将这些面投影到场景中得到投影面,再将这些投影面与场景中的其他平面求交得出阴影多边形,保存这些阴影多边形信息,然后在按视点位置对场景进行相应处理得到所要求的视图(利用空间换时间,每次只需依据视点位置进行一次阴影计算即可,省去了一次消隐过程)若是动态光源此方法就无效了。
184.
[
Unity]MipMap是什么,作用?
答:MipMapping:在三维计算机图形的贴图渲染中有常用的技术,为加快渲染进度和减少图像锯齿,贴图被处理成由一系列被预先计算和优化过的图片组成的文件,这样的贴图被称为MipMap。
185.
[
Unity]Mecanim系统中,Body Mask的作用是?
答:指定身体的某一部分是否参与渲染
186.
[
Unity]Unity连接数据库。
答:需要得到Mono.Data.Sqlite.dll 文件与System.Data.dll文件。
187.
[ Unity]如何优化内存?
答:1.压缩自带类库;
2.将暂时不用的以后还需要使用的物体隐藏起来而不是直接Destroy掉;
3.释放AssetBundle占用的资源;
4.降低模型的片面数,降低模型的骨骼数量,降低贴图的大小;
5.使用光照贴图;
6.使用多层次细节(LOD);
7.使用着色器(Shader);
8.使用预设(Prefab)等。
解析:内存开销无外乎三大部分:1.资源内存占用;2.引擎模块自身内存占用;3.托管堆内存占用
资源内存占用。
在一个较为复杂的大型项目中,资源的内存占用往往占据了总体内存的70%以上。因此,资源使用是否恰当直接决定了项目的内存占用情况。一般来说,一款游戏项目的资源主要可以分为以下几种:纹理(Texture),网络(Mesh),动画片段(AnimationClip)、音频片段(AudioClip)、材质(Material)、着色器(shader)、字体资源(Font)以及文本资源(TextAsset)等等。其中,纹理,网格、动画片段和音频片段则容易造成较大内存开销的资源。
纹理
纹理资源可以说是几乎所有游戏项目中占据最大内存开销的资源。一个6万片的场景,网格资源最大才不过10MB,但一个2048*2048的纹理,可能直接就达到16MB,因此,项目中纹理资源的使用是否恰当会及大地印象项目的内存占用。
那么,纹理资源再使用时应该注意哪些地方呢?
纹理格式。纹理格式是研发团队最需要关注的纹理属性。因为它不仅影响纹理的内粗你占用,同时还决定了纹理的加载效率。一般来说,我们建议开发团队尽可能根据硬件的种类选择硬件支持的纹理格式比如Android平台的ETC、iOS平台的PVRTC、WindowsPC上的DXT等等。因此,我们在UWA测评报告中,将纹理格式进行了罗列,一边开发团队进行快速查找,一步定位。
在使用硬件支持的纹理格式时,你可能会遇到以下几个问题:
色阶问题
由于ETC、PVRTC等格式均为有损压缩,因此,当纹理色差范围跨度较大时,均不可避免地造成不同程度的阶梯状的色阶问题。因此,很多研发团队使用RGBA32/ARGB32格式来实现更好的效果。但是,这种做法将造成很大的内存占用。比如,同样一张1024*1024的纹理,如果不开启Mipmap,并且为PVRTC格式,则其内存占用为512KB,而如果转换为RGBA32位,则很可能占用更达到4MB。所以,研发团队在使用RGBA32或ARGB32格式的纹理时,一定要慎重考虑,更为明智的选择是尽量减少纹理的色差范围,时期尽可能使用硬件支持的压缩格式进行存储。
ETC1不支持透明通道问题
在Android平台上,对于使用OpenGLES2.0的设备,其纹理格式仅能支持ETC1格式,该格式有个较为严重的问题,即不支持Alpha透明通道,使得透明贴图无法直接通过ETC1格式来进行存储。对此。我们建议研发团队将透明贴图尽可能分成两张,即一张RGB24位纹理记录原始纹理的颜色部分和一张Alpha8纹理记录原始纹理的透明通道部分。然后,将这辆张贴图分别转化为ETC1格式的纹理,并通过特定的Shader来进行渲染,从而来达到支持透明贴图的效果。该种方法不仅可以极大程度上逼近RGBA透明贴图的渲染效果,同时还可以降低纹理的内存占用,是我们非常推荐的使用方式。
当然,目前已经有越来越多的设备支持了OpenGLES3.0这样Android平台上你可以进一步使用ETC2甚至ASTC,这些纹理格式均为支持透明通道且压缩比更为理想的纹理格式。如果你的游戏适合人群为中高端设备用户,那么不妨直接使用这两种格式来作为主要存储格式。
纹理尺寸
一般来说,纹理尺寸越大,占用内存越大。
Mipmap功能
Mipmap旨在有效降低渲染带宽的压力,提升游戏的渲染效率。但是,开启Mipmap会有将纹理内存提升1.33倍。对于具有较大纵深感的3D游戏来说,3D场景模型和角色我们一般是建议开启Mipmap功能的,但很多2DUI纹理就不必要了。
Read&Write
一般情况下,文理资源“Read&Write”功能在Unity引擎中是默认关闭的。但是,我们仍然在项目深度优化时发现了不少项目的纹理资源会开启该选项。对此,我们建议压发团队密切关注文理资源中该选项的使用,因为开启该选项将会使文理内存增大一倍。
网格
网格资源在比较复杂的游戏中,往往占据较高的内存。对于网格资源来说,它在使用时应该注意那方面呢?
1)
Normal\Color和Tangent(切线)
在我们深度优化过的大量项目中,Mesh资源的数据经常会含有大量的Color数据,Normal数据和Tangent数据。这些数据的存在将大幅增加Mesh资源的文件体积和内存占用。其中Color数据和Normal数据主要为3DMax、Maya等建模软件导出时设计所生成,而Tangent一般为导入引擎时生成。
更为麻烦的是,如果项目对Mesh进行DrawCallBatching操作的话,那么狠有可能进一步增加总体内存的占用。正因如此,我们在UWA测评报告中为每个Mesh展示了其Normal,Color和Tangent属性的具体使用情况,研发团队可以直接针对每种属性进行排序查看,直接定位出现冗余数据的资源。一般来说这些数据主要为Shader所用,来生成较为酷炫的效果。所以,建议研发团队针对项目中的网格资源进行详细检测,查看该模型的渲染Shader中是否需要这些数据进行渲染。
动画片段
音频片段
引擎模块自身内存占用。
托管堆内存占用
188.
[
Unity]如何优化CPU?
答:
解析:CPU方面
就目前Unity移动游戏而言,CPU方面的性能开销主要可归结为两大类:引擎模块性能开销和自身代码性能开销。其中,引擎模块中又可细致划分为渲染模块、动画模块、物理模块、UI模块、粒子系统、加载模块和GC调用等等。
通过大量的性能测评数据,我们发现渲染模块、UI模块和加载模块,往往占用了CPU性能开销的Top3。
1.渲染模块
1降低DrawCall
降低DrawCall的方法则主要是减少渲染物体的材质种类,并通过DrawCallBatching来减少其数量。Unity文档对DrawCallBatching的原理和注意事项非常详尽,感兴趣的朋友可以直接查看Unity官方文登。
但是,需要注意的是游戏性能并非DrawCall越小越好。这是因为,决定渲染模块心梗的除了DrawCall之外,还有用于传输渲染数据的总先带宽。当我们使用DrawCallBatching将同种的材质和网络模型拼合在仪器室,可能会造成同一时间需要传输的数据(Texture、VB/IB等)大大增加,以至于造成堵塞。在资源无法计时传输过去的情况下,GPU只能等待,从而反倒降低了游戏的运行帧率。
DrawCall和总线带宽是天平的两端,我们需要做的是尽可能维持天平的平衡,任何一边过高或过低,对性能来说都是无益的。
2简化资源
简化资源师非常行之有效的优化手段。在大量的移动游戏中,其渲染资源其实是过量的。过量的过量的网络资源、不合规的纹理资源等等。
关于渲染模块在CPU方面的优化方法还有很多,比如LOD、Occlusion Culling和Culling Distance等等。
2 UI模块
UI模块同样也是几乎所有的游戏项目中必备的模块。一个性能优异的UI模块可以将游戏的用户体验再抬高一个档次。
在NGUI优化方面,UIPanel.LateUpdate为性能优化的重中之重。
对于UIPanel.LateUpdate的优化,主要着眼与UIPanel的布局,其原则如下:
尽可能将动态UI元素和静态UI元素分离到不同的UIPanel中,从而尽可能将因为变动的UI元素引起的冲欧控制在较小的范围内;
尽可能让动态UI元素按照同步性进行划分,即运动帧率不同的UI元素尽可能分离放在不同的UIPanel中;
控制同一个UIPanel中动态UI元素的数量,数量越多,所创建的Mesh越大,从而使得重构的开销曾加。比如战斗过程中的HUD运动协调会出现的比较多,此时,建议研发团队将运动血条分离成不同的UIPanel,每组UIPanel下5~10个动态UI为宜。这种做法,其本质是从概率上尽可能降低单振中UIPanel的重建开销。
3加载模块
加载模块同样也是任何游戏项目中所不可缺少的组成成分。与之前两个模块不同的是,加载模块的性能开销比较集中,主要出现于场景切换处,且CPU占用峰值均较高。
这里,我们先来说说场景切换时,其性能开销的主要体现形式。对于目前的Unity版本而言,场景切换时的主要性能开销主要体现在两个方面,前一场景的场景卸载和下一场景的场景加载。下面,我们就具体来说说两个方面的性能瓶颈:
1场景卸载,对于Unity引擎而言,场景卸载一般是由引擎自动完成的,即当我们调用类似Application.LoadLevel的API时,引擎即会开始对上一场景进行处理,其性能开销主要被以下几部分占据。
Destroy
引擎在切换场景时会手机为表示成DontDestoryOnLoad的GameObject及其Component,然后进行Destroy。同时,代码中的OnDestory被触发执行,这里的性能开销主要取决于OnDestroy回调函数中的代码逻辑。
Resources.UnloadUnusedAssets
一般情况下,场景切换过程中,该API会被调用两次,依次为引擎在切换场景是自动调用,另一次则为用户手动调用(一般出现在场景加载后,用户调用它来确保上一场景的资源被卸载干净)。在我们测评过的大量项目中,该API的CPU开销主要集中在500ms~3000m之间。其耗时开销主要取决于场景中Asset和Object的数量,数量越多,则耗时越慢。
2场景加载
场景加载过程的性能开销又可细分成以下几个部分:
资源加载
资源加载几乎占据整个加载过程的90%以上,其加载效率主要取决于资源的加载方式(Resource.Load或AssetBundle加载)、加载量(纹理、网格、材质等资源数据的大小)和资源格式(纹理、音频格式等)。不同的加载方式、不同的资源格式,其加载效率可谓千差万别。
Instantiate实例化
在场景加载过程中,往往伴随着大量的Instantiate实例化操作。在Instantiate实例化时,引擎底层会查看相关的资源是否已经被加载,如果没有,则会先加载其相关资源,再进行实例化,这其实是大家遇到大多数“Instantiate”实例化问题的根本原因。
AssetBundle文章中所提倡的资源依赖关系打包并进行预加载,从而来缓解Instantiate实例化的压力。
另一方面,Instantiate实例化的性能开销还体现在脚本代码的序列化上,如果脚本中序列化的信息很多,则Instantiate实例化时的时间亦会很长。最直接的例子就是NGUI,其代码中存在很多SerializedField标识,从而在实例化时带来了较多的代码序列化开销。因此,在打架增加序列化信息时,这一点是需要大家时刻关注的
以上是游戏项目中性能开销最大的三个模块,当然,游戏类型的不同、设计的不同,其他模块仍然会有较大的CPU占用。比如ARPG游戏中动画系统和物理系统,音乐休闲类游戏中的音频系统和例子系统等。
4代码效率
逻辑代码在一个较为复杂的游戏项目中往往占据较大的CPU开销。这种情况在MOBA\ARPG\MMORPG等游戏类型中非常常见。
在项目优化过程中,我们经常会想知道,到底哪些函数占据了大量的CPU开销。同时,绝大多数的项目其中性能开销都遵循着“二八原则”,即80%的性能消耗都集中在20%的函数上。
189.
[
Unity]你用过哪些插件?
答:
插件功能
插件名称
界面制作
NGUI
2D游戏制作
2D Toolkit
可视化编程
PlayMaker
插值插件
iTween、HOTween
路径搜寻
SimplePath
美术及动画制作
RageSpline、Smooth Moves
画面增强
Bitmap2Material、Strumpy Shader Editor
摄像机管理
Security Camera
资源包
Nature Pack
造路插件
EasyRoads3D
即时遮挡剔除/LOD多细节层次
Instant Occlusion Culling
190.
[3D图形学]什么是渲染管道?
答:是指在显示器上为了显示出图像而经过的一系列必要操作。
渲染管道中的很多步骤,都要将几何物体从一个坐标系中变换到另一个坐标系中去。
主要有三步:应用程序阶段,几何阶段
光栅阶段
本地坐标->视图坐标->背面裁剪->光照->裁剪->投影->视图变换->光栅化。
191.
[3D图形学]什么是矢量图 ?
答:计算机中显示的图形一般可以分为两大类——矢量图和位图。矢量图使用直线和曲线来描述图形,这些图形的元素是一些点、线、矩形、多边形、圆和弧线等等,它们都是通过数学公式计算获得的。例如一幅花的矢量图形实际上是由线段形成外框轮廓,由外框的颜色以及外框所封闭的颜色决定显示出的颜色。由于矢量图形可通过公式计算获得,所以矢量图形文件体积一般较小。矢量图形最大的优点是无论放大、缩小或旋转等不会失真;最大的缺点是难以表现色彩层次丰富的逼真图像效果。
192.
[3D图形学]什么是矩阵?矩阵运算?
答:矩阵:横轴排列的二维数据表格
矩阵运算:
加减
限制条件:行和列必须相同,对应相加相减得到结果
乘法
限制条件:要求左矩阵的行和右矩阵的列必须同,行数和左矩阵相等,列数和右矩阵相等,结果的第i行第j列,是左矩阵的第i行和右矩阵的第j列逐个相乘并把结果相加,得到结果是结果
的
第i行第j列。
193.
[3D图形学]角度和弧度的转换。
答:角度和弧度
度和弧度之间的换算 1弧度 = 180度 /pi(约57.3)
1度=pi/180弧度(约0.017)
194.
[3D图形学]矢量标量。
答:矢量有方向如力速度 标量只有大小没有方向如温度
矢量取模就是只要大小不要方向
单位向量
有方向 大小为1的向量
矢量的加法:是矢量的几何和,服从平行四边形规则
矢量满足交换律,满足结合律
在直角坐标系中,矢量等于骑在坐标轴上投影的矢量之和(二维矢量可以看做三维矢量的特例也就是说,三维成立,二维也成立)
矢量减法:
大小相等
方向相反
称为逆矢量。
任意多个矢量首尾相连接组成闭合多边形,其结果必为0
矢量的乘法:点积(内积、标量积)、叉积(外积)结果是矢量
点积方法 dot
注:这题要问什么?
195.
[
Unity]动态加载资源的方式?
答:
1.Resources
2.AssetBundle
3.WWW
196.
[ Unity]场景中有大量物体及实时光源,会对性能带来影响吗?应该如何解决?
答:实时光源会对性能有影响,解决方案有以下几种:
1使用unity的烘焙系统烘焙替代实时光源。
2使用三维建模软件的烘焙系统烘焙代替实时光源。
3一般移动端开发实时光源只为了提供实时阴影效果,所以设置实施光照的有效层。
197.
[ Unity]如何实现游戏的暂停、加速和减速?
答:
Time.timeScale = 0;即可让游戏暂停。
Time.timeScale =
1时,Update、LateUpdate、FixedUpdate 都按正常的时间来执行。
Time.timeScale =
2时,Update和 LateUpdate的执行速度是之前的2倍,而FixedUpdate还是按正常时间来执行
198.
[ Unity]请描述Prefab的作用,并描述如何在移动设备的环境下恰当的使用它?
答:Prefab可以理解为是一个游戏对象及其组件的集台,作用是使游戏对象及资源能够被重复使用。相同的对象可以通过一个预设来创建,此过程可理解为实例化,预设可以进行批量修改。
199.
[
Unity]请简述如何在不同分辨率下保持 UI 的一致性?
答:NGUI 很好的解决了这一点,屏幕分辨率的自适应性,原理就是计算出屏幕的宽高比跟原来的预设的屏幕分辨率求出一个对比值,然后修改摄像机的 size 。
注:
200.
[
Unity]加载关卡和异步加载关卡的方法?
答:
SceneManager.LoadScene//加载场景
SceneManager.LoadSceneAsync//异步加载场景
201.
[Shader]在unity中,开发者可以编写几种类型的Shader?
答:1、表面着色器(surface shaders)
通常情况下用户都会使用这种Shader,它可以与灯光、阴影、投影器进行交互。表面着色器的抽象层次比较高,它可以容易地以简洁方式实现复杂的着色器效果。表面着色器可同时正常工作在前向渲染及延迟渲染模式下。表面着色器以句Cg/HLsL语言进行编写。
2、顶点和片段着色器(Vertex and fragment Shaders)
如果需要一些表面着色器无法处理的酷炫效果,或者编写的Shader不需要与灯光进行交互,或是想要的只是全屏图像效果,那么可以使用顶点和片段着色器。这种Shader可以非常灵活地实现需要的效果,但是需要编写更多的代码,并且很难与Unity的渲染管线完美集成。顶点和片段着色器同样是用Cg/HLsL语言来编写。
3、固定功能管线着色器(Fixed Function Shaders)
如果游戏要运行在不支持可编程管线的老旧硬件上,那么需要编写这种Shader了。固定功能管线着色器可以作为片段或表面着色器的备用选择,这在当硬件无法运行那些酷炫Shader的时候,还可以通过固定功能管线着色器来绘制出一些基本的内容。固定功能管线着色器完全以ShaderLab语言编写,类似于微软的Effects或是Nvidia的CgFX。
202.
[
UI]什么用途的纹理通常可以不强制使用2次幂的宽高数值?
答:UI纹理不需要强制使用2次幂,以NGUI举例,NGUI会制作图集,图集是2次幂的。
203.
[Unity引擎]unity中碰撞器(Collider)和触发器(Trigger)的区别?
答:
碰撞器(Collider)有碰撞效果,IsTrigger=false,可以调用OnCollisionEnter/Stay/Exit函数
触发器(Trigger)没有碰撞效果,isTrigger=true,可以调用OnTriggerEnter/Stay/Exit函数
204.
[网络]请简述TCP与UDP的区别。
答:TCP是基于连接的,UDP基于无连接的
TCP对系统资源的要求多,UDP较少
UDP程序结构较简单
TCP是面向流数据的,UDP是数据报
TCP保证数据正确性,UDP可能丢包。
TCP保证数据的顺序,UDP不保证。
205.
[网络]为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?
答:这是因为服务段的LISTEN状态下的SOCKET当收到SYN报文的建立请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你未必会马上关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发的。
206.
[网络]为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?
答:这是因为虽然双反都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,案例可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但是因为我们必须要家乡网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LASK_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是来重发可能都是的ACK报文。
207.
[Unity引擎]请简述角色控制器中Move和SimpleMove函数的区别。
答:角色控制器中Move和SimpleMove函数都是用于实现角色游戏对象移动的函数,它们的区别在于当我们在每一帧调用SimpleMove函数时,引擎将为该角色控制器对象添加一个重力,而Move函数则不会添加重力,需要我们通过代码去实现重力的效果。
208.
[Unity引擎]请简述一下什么是游戏引擎?
答:游戏引擎是指一些已经编写好的可编辑电脑游戏系统或者一些交互式实时图像应用程序的核心组件。这些系统为游戏设计者提供各种编写游戏所需要的各种工具,其目的在于让游戏设计者能容易和快速地做出游戏程序而不用由零开始。大部分都支持多种操作系统平台,如Linux、Mac
OS、微软Windows。游戏引擎包含以下系统:渲染引擎(即“渲染器”,含二维图像引擎和三维图像引擎)、物理引擎、碰撞检测系统、音效、脚本引擎、电脑动画、人工智能、网络引擎以及场景管理。
209.
[Unity引擎]请简述Unity中有哪些特殊文件夹及其作用?
1.Editor
Editor文件夹可以在根目录下,也可以在子目录里,只要名子叫Editor就可以。比如目录:/xxx/xxx/Editor
和 /Editor
是一样的,无论多少个叫Editor的文件夹都可以。Editor下面放的所有资源文件或者脚本文件都不会被打进发布包中,并且脚本也只能在编辑时使用。一般呢会把一些工具类的脚本放在这里,或者是一些编辑时用的DLL。
比如我们现在要做类似技能编辑器,那么编辑器的代码放在这里是再好不过了,因为实际运行时我们只需要编辑器生成的文件,而不需要编辑器的核心代码。
2.Editor Default
Resources
Editor Default
Resources注意中间是有空格的,它必须放在Project视图的根目录下,如果你想放在/xxx/xxx/Editor Default
Resources
这样是不行的。你可以把编辑器用到的一些资源放在这里,比如图片、文本文件、等等。它和Editor文件夹一样都不会被打到最终发布包里,仅仅用于开发时使用。
3.Gizmos
我觉得这个文件夹其实没什么用处,如下代码所示它可以在Scene视图里给某个坐标绘制一个icon。它的好处是可以传一个Vecotor3 作为图片显示的位置。
4.Plugins
如果做手机游戏开发一般 andoird 或者 ios
要接一些sdk 可以把sdk依赖的库文件 放在这里,比如 .so
.jar .a 文件。这样打完包以后就会自动把这些文件打在你的包中。
5.Resources
可以在根目录下,也可以在子目录里,只要名子叫Resources就可以。比如目录:/xxx/xxx/Resources
和 /Resources
是一样的,无论多少个叫Resources的文件夹都可以。Resources文件夹下的资源不管你用还是不用都会被打包进.apk或者.ipa
Resource.Load :编辑时和运行时都可以通过Resource.Load来直接读取。
Resources.LoadAssetAtPath()
:它可以读取Assets目录下的任意文件夹下的资源,它可以在编辑时或者编辑器运行时用,它但是它不能在真机上用,它的路径是”Assets/xx/xx.xxx” 必须是这种路径,并且要带文件的后缀名。
AssetDatabase.LoadAssetAtPath():它可以读取Assets目录下的任意文件夹下的资源,它只能在编辑时用。它的路径是”Assets/xx/xx.xxx” 必须是这种路径,并且要带文件的后缀名。
我觉得在电脑上开发的时候尽量来用Resource.Load() 或者
Resources.LoadAssetAtPath() ,假如手机上选择一部分资源要打assetbundle,一部分资源Resource.Load().那么在做.apk或者.ipa的时候
现在都是用脚本来自动化打包,在打包之前
可以用AssetDatabase.MoveAsset()把已经打包成assetbundle的原始文件从Resources文件夹下移动出去在打包,这样打出来的运行包就不会包行多余的文件了。打完包以后再把移动出去的文件夹移动回来。
6. StreamingAssets
这个文件夹下的资源也会全都打包在.apk或者.ipa
它和Resources的区别是,Resources会压缩文件,但是它不会压缩原封不动的打包进去。并且它是一个只读的文件夹,就是程序运行时只能读不能写。它在各个平台下的路径是不同的,不过可以用Application.streamingAssetsPath
它会根据当前的平台选择对应的路径。
有些游戏为了让所有的资源全部使用assetbundle,会把一些初始的assetbundle放在StreamingAssets目录下,运行程序的时候在把这些assetbundle拷贝在Application.persistentDataPath目录下,如果这些assetbundle有更新的话,那么下载到新的assetbundle在把Application.persistentDataPath目录下原有的覆盖掉。
因为Application.persistentDataPath目录是应用程序的沙盒目录,所以打包之前是没有这个目录的,直到应用程序在手机上安装完毕才有这个目录。
StreamingAssets目录下的资源都是不压缩的,所以它比较大会占空间。
http://www.xuanyusong.com/archives/3229