-
物体发生碰撞的必要条件?
两个物体都必须带有碰撞器(Collider),其中一个物体还必须带有Rigidbody刚体,而且必须是运动的物体带有Rigidbody脚本才能检测到碰撞。
2. Unity3d中的碰撞器和触发器的区别?
-
碰撞器是触发器的载体,而触发器只是碰撞器身上的一个属性。
-
当Is Trigger=false时,碰撞器根据物理引擎引发碰撞,产生碰撞的效果,可以调用OnCollisionEnter/Stay/Exit函数;
-
当Is Trigger=true时,碰撞器被物理引擎所忽略,没有碰撞效果,可以调用OnTriggerEnter/Stay/Exit函数。
-
如果既要检测到物体的接触又不想让碰撞检测影响物体移动或要检测一个物件是否经过空间中的某个区域这时就可以用到触发器。
3. 什么是协程程序?
在主线程运行的同时开启另一段逻辑处理,来协助当前程序的执行,协程很像多线程,但是不是多线程,Unity的协程实在每帧结束之后去检测yield的条件是否满足。
4. Unity3d脚本从唤醒到销毁有着一套比较完整的生命周期,列出系统自带的几个重要的方法。
一些常用的方法:
Awake —> OnEnable —> Start —> FixedUpdate —>Update —> LateUpdate—> OnGUl —> OnDisable —> OnDestroy
生命周期图:
5. 物理更新一般放在哪个生命周期函数里
在Unity中,物理更新通常放在FixedUpdate函数中,而不是放在Update函数中。Update函数是每一帧都会调用的函数,用于处理物体的位置、旋转和缩放等变换,但它不适用于物理计算,因为它的执行频率高于FixedUpdate。
具体分析参考这篇文章:深入探讨:Update和FixedUpdate
6. 移动相机一般放在哪个生命周期函数里
LateUpdate,是在所有的Update结束后才调用,比较适合用于命令脚本的执行。
7. Unity提供了几种光源,分别是什么?
四种。
-
平行光:Directional Light
-
点光源:Point Light
-
聚光灯:Spot Light
-
区域光源:Area Light
8. localPosition 与 Position 的使用区别
-
localPosition :自身坐标系,相对于父级的位置
-
Position :世界坐标系中的位置
9.简述Invoke与InvokeRepeating
单次调用和重复多次调用的区别。
Invoke
-
Invoke() 方法是 Unity3D 的一种委托机制
-
如:Invoke(“Test”, 3); 它的意思是:3 秒之后调用 Test() 方法;
使用 Invoke() 方法需要注意 以下3点:
1 :它应该在 脚本的生命周期里的(Start、Update、OnGUI、FixedUpdate、LateUpdate)中被调用;
2:Invoke(); 不能接受含有参数的方法;
3:在 Time.ScaleTime = 0; 时, Invoke() 无效,因为它不会被调用。
InvokeRepeating
-
InvokeRepeating(“Test”, 3 , 5);
-
这个方法的意思是指:3 秒后调用 Test() 方法,并且之后每隔 5 秒调用一次 Test() 方法。
10. 简述Invoke与协程的区别
-
Invoke方法:执行没有被挂起,相当于设置完被调用函数的执行时间后即时向下执行。应用到每隔一段时间执行某个函数很方便。
-
Coroutine方法:新开一条执行序列(跟新建线程差不多)并挂起,等待中断指令结束。开销不大。当需要挂起当前执行时使用。
-
协程的效率比Invoke高。
11. 正在运行的脚本,隐藏物体与禁止脚本导致触发OnDisable时,Invoke与coroutine是否正常运行?
-
只将脚本禁止:都会正常运行。
-
如果把物体直接隐藏:Invoke正常运行,coroutine不会正常运行。
原因:
-
因为游戏物体隐藏了,一切与游戏物体相关的脚本生命周期都会停止,协程自然也会停止 ;
-
如果游戏对象没有隐藏,只是将脚本隐藏,游戏对象照样可以通过反射获取协程迭代器对象继续协程的执行。
12. OnEnable、Awake、Start运行时的发生顺序?哪些可能在同一个对象周期中反复的发生
Awake –>OnEnable->Start,OnEnable在同一周期中可以反复地发生。
13. Unity3d提供了一个用于保存和读取数据的类(PlayerPrefs),请列出保存和读取整形数据的函数
-
PlayerPrefs类是一个本地持久化保存与读取数据的类
-
PlayerPrefs类支持3中数据类型的保存和读取,浮点型,整形,和字符串型。
分别对应的函数为:
-
SetInt();保存整型数据;GetInt();读取整形数据;
-
SetFloat();保存浮点型数据;GetFlost();读取浮点型数据;
-
SetString();保存字符串型数据;GetString();读取字符串型数据;
14. Image和RawImage的区别
-
Imgae比RawImage更消耗性能
-
Image只能使用Sprite属性的图片,但是RawImage什么样的都可以使用
-
Image适合放一些有操作的图片,裁剪平铺旋转什么的,针对Image Type属性
-
RawImage就放单独展示的图片就可以,性能会比Image好很多
15. 简述一下对象池,你觉得在FPS里哪些东西适合使用对象池?
对象池就存放需要被反复调用资源的一个空间。
比如游戏中要常被大量复制的对象,子弹,敌人,以及任何重复出现的对象。
16. 如何让已经存在的GameObject在LoadLevel后不被卸载掉?
DontDestroyOnLoad(transform.gameObject);
17. 请简述如何在不同分辨率下保持UI的一致性
多屏幕分辨率下的UI布局一般考虑两个问题:
-
布局元素的位置,即屏幕分辨率变化的情况下,布局元素的位置可能固定不动,导致布局元素可能超出边界;
-
布局元素的尺寸,即在屏幕分辨率变化的情况下,布局元素的大小尺寸可能会固定不变,导致布局元素之间出现重叠等功能。
为了解决这两个问题,在Unity UGUI体系中有两个组件可以来解决问题,分别是布局元素的Rect Transform和Canvas的Canvas Scaler组件。
CanvasScaler中UI Scale Mode有三种模式,Constant Pixel Size、Scale With Screen Size、Constant Physical Size,其中第二个就是根据屏幕分辨率来进行缩放适配。在这个模式下,有两个参数,一个是我们在开发过程中的标准分辨率,一个是屏幕的匹配模式,通过这里面的设置,就可以完成多分辨率下的适配问题。
18. 动态加载资源的方式?
-
instantiate:最简单的一种方式,以实例化的方式动态生成一个物体。
-
Assetsbundle:即将资源打成 asset bundle 放在服务器或本地磁盘,然后使用WWW模块get 下来,然后从这个bundle中load某个object,unity官方推荐也是绝大多数商业化项目使用的一种方式。
-
Resource.Load:可以直接load并返回某个类型的Object,前提是要把这个资源放在Resource命名的文件夹下,Unity不管有没有场景引用,都会将其全部打入到安装包中
-
AssetDatabase.loadasset :这种方式只在editor范围内有效,游戏运行时没有这个函数,它通常是在开发中调试用的。
19. 获取、增加、删除组件的命令分别是什么?
-
获取:GetComponent
-
增加:AddComponent
-
删除:Destroy
20. Addcomponent后哪个生命周期函数会被调用
-
对于AddComponent添加的脚本,其Awake,Start,OnEnable是在Add的当前帧被调用的
-
其中Awake,OnEnable与AddComponent处于同一调用链上
-
Start会在当前帧稍晚一些的时候被调用,Update则是根据Add调用时机决定何时调用:如果Add是在当前帧的Update前调用,那么新脚本的Update也会在当前帧被调用,否则会被延迟到下一帧调用。
21. 画布的三种模式.缩放模式
-
屏幕空间-覆盖模式(Screen Space-Overlay),Canvas创建出来后,默认就是该模式,该模式和摄像机无关,即使场景内没有摄像机,UI游戏物体照样渲染
-
屏幕空间:电脑或者手机显示屏的2D空间,只有x轴和y轴
-
覆盖模式:UI元素永远在3D元素的前面
-
-
屏幕空间-摄像机模式(Screen Space-Camera),设置成该模式后需要指定一个摄像机游戏物体,指定后UGUI就会自动出现在该摄像机的“投射范围”内,和NGUI的默认UI Root效果一致,如果隐藏掉摄像机,UGUI当然就无法渲染
-
世界空间模式(WorldSpace),设置成该模式后UGUI就相当于是场景内的一个普通的“Cube 游戏模型”,可以在场景内任意的移动UGUI元素的位置,通常用于怪物血条显示和VR开发
22. 有限状态机是什么?在游戏开发中的应用
有限状态机系统:是指在不同阶段会呈现出不同的运行状态的系统,这些状态是有限的、不重叠的。这样的系统在某一时刻一定会处于其所有状态中的一个状态,此时它接收一部分允许的输入,产生一部分可能的响应,并且迁移到一部分可能的状态。
具体分析:bilibili -> 打工人小棋 -> 有限状态机
(公众号不让放链接:有兴趣可以自己去b站搜下)
23. Animation和Animator的区别
-
Animation和Animator 虽然都是控制动画的播放,但是它们的用法和相关语法都是大有不同的。
-
Animation控制一个动画的播放,而Animator是多个动画之间相互切换,并且Animator有一个动画控制器,俗称动画状态机。
-
Animator利用它做动画的切换是很方便的,但是它有一个缺点就是占用内存比Animation大。
24. 介绍下ScriptableObejct
ScriptableObject是Unity中的一个特殊类型,它允许您创建可保存和重用的可编程对象。与MonoBehaviour不同,ScriptableObject不附加到游戏对象上,而是保存在Assets文件夹中,并可以在项目中共享和重用。
ScriptableObject在Unity中的主要用途之一是创建可配置的数据对象,例如游戏中的配置文件、状态机、事件系统等。它们可以在编辑器中创建和调整,并且在游戏运行时保持不变。这使得调整和测试游戏内容变得更加灵活和高效。
ScriptableObject的另一个常见用途是共享数据,例如全局变量、事件和消息系统等。通过创建ScriptableObject实例,您可以轻松地在不同的游戏对象之间传递数据,而无需使用单例模式或全局变量。
25. Unity中常用的资源路径
Application.dataPath; //Asset文件夹的绝对路径
//只读
Application.streamingAssetsPath; //StreamingAssets文件夹的绝对路径(要先判断是否存在这个文件夹路径)
Application.persistentData ; //可读写
26. 简述prefab的用处
在游戏运行时实例化,prefab相当于一个模板,对你已经有的素材、脚本、参数做一个默认的配置,以便于以后的修改,同时prefab打包的内容简化了导出的操作,便于团队的交流。
27. 在物体发生碰撞的整个过程中,有几个阶段,分别列出对应的函数
三个阶段,
-
OnCollisionEnter
-
2.OnCollisionStay
-
3.OnCollisionExit
28. 射线检测碰撞物的原理是?
射线是3D世界中一个点向一个方向发射的一条无终点的线,在发射轨迹中与其他物体发生碰撞时,它将停止发射 。
29. 简述四元数的作用,四元数对欧拉角的优点?
四元数用于表示旋转
相对欧拉角的优点:
1.能进行增量旋转
2.避免万向锁
3.给定方位的表达方式有两种,互为负(欧拉角有无数种表达方式)
详细分析:bilibili -> 3Blue1Brown ->四元数的可视化
(公众号不让放链接:有兴趣可以自己去b站搜下,有点难度)
30. 在编辑场景时将GameObject设置为Static有何作用?
设置游戏对象为Static时,这些部分被静态物体挡住而不可见时,将会剔除(或禁用)网格对象。因此,在你的场景中的所有不会动的物体都应该标记为Static。
31. 什么是DrawCall?DrawCall高了又什么影响?如何降低DrawCall?
Unity中,每次引擎准备数据并通知GPU的过程称为一次Draw Call。DrawCall越高对显卡的消耗就越大。降低DrawCall的方法:
1. Dynamic Batching
2. Static Batching
3. 高级特性Shader降级为统一的低级特性的Shader。
32. 摄像机有几种模式
摄像机(Camera)有三种模式:正交投影模式(Orthographic)、透视投影模式(Perspective)和物理相机(Physical Camera)。
正交投影模式:
在这种模式下,摄像机将场景以平行线方式进行投影。这种方式没有透视效果,即远离或靠近摄像头的物体大小不会改变。这种模式通常用于2D游戏或者需要特殊视觉效果的3D游戏。
透视投影模式:
在此设置下,摄像机将场景以收敛线方式进行投影。也就是说,远离镜头的物体会显得更小。这就产生了一种深度感或者三维空间感觉,使得画面看起来更加真实立体。
物理相机:
从Unity 2018版本开始引入了"Physical Camera"属性, 可以让你设置镜头、传感器和其他一些参数, 更接近现实世界中相机的工作原理.
33. Unity如何实现单例模式
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T _instance;
public static T Instance
{
get
{
if (_instance == null)
{
_instance = FindObjectOfType<T>();
if (_instance == null)
{
GameObject singleton = new GameObject();
_instance = singleton.AddComponent<T>();
singleton.name = typeof(T).ToString() + " (Singleton)";
// 确保单例不会被销毁
DontDestroyOnLoad(singleton);
}
}
return _instance;
}
}
}
你可以通过继承这个Singleton类来创建自己的单例类。例如:
public class MySingletonClass : Singleton<MySingletonClass>
{
// 这里是你自己的代码...
}
34. [MenuItem] 什么意思
在Unity中,[MenuItem]是一个特性(Attribute),它用于在Unity的菜单栏中创建新的菜单项。这个特性可以应用于静态方法。
using UnityEngine;
using UnityEditor;
public class MyEditorScript
{
[MenuItem("Custom/My Function")]
static void MyFunction()
{
// 这里是你自定义功能的代码...
Debug.Log("My Function Was Called!");
}
}
当你点击"Custom/My Function"这个菜单项时,就会执行MyFunction()方法,并在控制台打印出"My Function Was Called!"。
这个特性常常用来自测一些功能
35. 反射实现原理
网上说了一大堆,回想当初小棋自己也云里雾里的,我这里用通俗的话解释下。
在游戏开发过程中,很多配置内容是以文本形式保存起来的,比如Player的Level和Star。保存在某个文本文件中:
"{Level:1, Star:2}"
我们运行游戏时候去加载这些配置表,就根据字段名:"Level"去初始化Player。把字符串变成具体的对象,或者对象的属性,这样的过程就叫反射。
为什么叫反射呢,我理解他有点像是反向操作。因为我们通常是把对象属性保存成字符串,从字符串再反序列化为对象,叫做反射也很合理。
不知道大家理解吗,最后还是放下网上的解释吧:
反射是指程序在运行时可以访问、检测和修改它本身状态或行为的一种能力。
在 C# 中,反射主要是通过 System.Reflection 命名空间提供的类和接口来实现的。
反射的优点是能够实现程序的动态性和灵活性,缺点是反射操作较慢,因为反射的操作需要在运行时进行动态解析和调用,而不是在编译期确定。
此外,反射还可能导致安全性问题,因为它可以访问私有成员和调用私有方法。因此,在使用反射时需要谨慎处理,并遵守相关的安全规则。
36. U3D中,几种施加力的方式,描述出来
首先需要对象要有rigidbody组件
-
Rigidbody.AddForce /AddForceAtPosition
-
2D Constant Force
-
Force/Relative Force/Torque
37. 用代码实现第三人称角色控制器?第一人称角色控制器
小棋:答案太长了公众号不好展示,贴下几个参考链接,这个问题很值得思考,有助于你提升对相机控制的理解,如果有机会以后再出个视频。
github -> Unity3d_ThirdPersonController
github -> first-person-controller-for-unity
(公众号不让放链接:有兴趣可以自己去github搜下)
38. Mathf.Round和Mathf.Clamp和Mathf.Lerp含义?
-
Mathf.Round:四舍五入
-
Mathf.Clamp:左右限值
-
Mathf.Lerp:插值
39. 如何使子控件居中,如果使用UGUI怎么实现
锚点设置为中心
40. 启用MipMaps对内存的影响是?MipMap的作用?如何操作?
概念:
想象一下,假设我们有一个包含着上千物体的大房间,每个物体上都有纹理。有些物体会很远,但其纹理会拥有与近处物体同样高的分辨率。由于远处的物体可能只产生很少的片段,OpenGL从高分辨率纹理中为这些片段获取正确的颜色值就很困难,因为它需要对一个跨过纹理很大部分的片段只拾取一个纹理颜色。在小物体上这会产生不真实的感觉,更不用说对它们使用高分辨率纹理浪费内存的问题了。
OpenGL使用一种叫做多级渐远纹理(Mipmap)的概念来解决这个问题,它简单来说就是一系列的纹理图像,后一个纹理图像是前一个的二分之一。多级渐远纹理背后的理念很简单:距观察者的距离超过一定的阈值,OpenGL会使用不同的多级渐远纹理,即最适合物体的距离的那个。由于距离远,解析度不高也不会被用户注意到。同时,多级渐远纹理另一加分之处是它的性能非常好。
增加约33%的内存,1/4 +1/16
小棋:这部分是图形学基础知识,可以先了解个概念。具体分析可以参考:bilibili -> Games101,内容有点多,需要较长的学习时间。
41. 如何检测物体是否被其他对象遮挡
-
射线检测
-
EventSystem.IsPointerOverGameObject
42. 向量的点乘、叉乘以及归一化的意义?
叉乘cross:可以获得两个向量A和B所构成平面,垂直的向量C,和左手坐标系类似,可以用来判断角色移动方向,判断顺时针还是逆时针旋转
点乘 dot :用来求向量之间的夹角,判断向量是否在同一方向、以及B向量在A向量上的投影
a·b>0 方向基本相同,夹角在0°到90°之间
a·b=0 正交
a·b<0 方向基本相反,夹角在90°到180°之间
归一化normalized:用在只关系方向,不关心大小的情况下
43. CharacterController 和 Rigidbody 的区别
CharacterController一般用在人型角色,继承于Collider,可以认为是受限的Rigidbody
Rigidboy完全受物理引擎影响,质量,阻力等属性,Is Kinematic不受物理引擎影响,通过代码改变Transform。
44. 向量的运算有哪些?Unity有哪些API可以计算
-
加法减法:物理上计算两个力的合力或者几个速度分量的叠加Vertor3(a1+b1,a2+b2,a3+b3)
-
数乘:向量与一个标量相乘,变量的正负,表示方向的正反方向变化,对向量的长度进行缩放
-
点乘:a点乘b得到一个标量,集合意义是a和b长度相乘再乘以两者夹角的余弦
-
叉乘:a叉乘b得到一个新向量,满足unity的左手坐标系
Vector3类
-
单位化normalized
-
向量长度magnitude
-
叉乘cross
-
点乘 dot
-
两向量夹角 angle
-
距离 distance
-
投影 project
45. Unity3D中的协程(coroutine),C#线程和进程之间的区别是什么?
协程和线程区别
协程(协同程序Coroutine): 同一时间只能执行某个协程。开辟多个协程开销不大。协程适合对某任务进行分时处理。Unity提供了StartCoroutine来开启协程,当你在 StartCoroutine 的函数体里处理一段代码时,利用 yield语句等待执行结果,这期间不影响主程序的继续执行,可以协同工作。
举个例子:LoadLevelAsync(异步加载关卡)后台加载场景的方法。允许你在后台加载新资源和场景,再利用协同,你就可以在前台用 loading 条或动画提示玩家游戏处于加载中,同时后台协同处理加载的事宜。
进程progress:进程是线程的容器。
线程thread: 同一时间可以同时执行多个线程。开辟多条线程开销很大。线程适合多任务同时处理,并发并行。
协程:具体多返回点的方法,时间分片(帧),Unity只能是单线程,只能在主线程调用Api,对象
46. 什么是渲染管道?
是指在显示器上为了显示出图像而经过的一系列必要操作。渲染管道中的很多步骤,都要将几何物体从一个坐标系中变换到另一个坐标系中去。
主要步骤有:本地坐标->视图坐标->背面裁剪->光照->裁剪->投影->视图变换->光栅化。
47. 矩阵相乘的意义
用于表示线性变换:旋转、缩放、投影、平移、仿射
48. 将图片的TextureType选项分别选为Texture和Sprite有什么区别
Sprite作为UI精灵使用,Texture作用模型贴图使用。
49. 请描述游戏动画有哪几种,以及其原理?
主要有关节动画、⻣骼动画、单一网格模型动画(关键 帧动画)。
-
关节动画:把⻆色分成若干独立部分,一个 部分对应一个网格模型,部分的动画连接成一个整体 的动画,⻆色比较灵活,Quake2中使用这种动画;
-
⻣骼动画,广泛应用的动画方式,集成了以上两个方 式的优点,⻣骼按⻆色特点组成一定的层次结构,有 关节相连,可做相对运动,皮肤作为单一网格蒙在⻣ 骼之外,决定⻆色的外观;
-
单一网格模型动画由一个完整的网格模型构成,在动 画序列的关键帧里记录各个顶点的原位置及其改变量,然后插值运算实现动画效果,⻆色动画较真实。
50. Avator的作用
用户提供的模型骨架和Unity的骨架结构进行适配,是一种骨架映射关系。
方便动画的重定向
AnimationType有三种类型
Humanoid人型:可以动画重定向,游戏对象挂载animator,子类原始模型+重定向模型,设置原始模型和使用模型的AnimationType为Humanoid类型
Generic非人型
Legacy旧版
Avator Mask身体遮罩,身体某一部分是否受到动画影响
反向动力学 IK,通过手或脚来控制身体其他部分
51. 反向旋转动画的方法是什么?
将动画速度调成-1
改代码animation.speed=-1
好啦,以上就是本期的所有内容啦,希望能够帮助到大家。
整理这些内容花费了不少时间,其中还有部分点评,以及为了给读者朋友们更好的阅读体验,对文章的格式化进行处理和归纳。
如果觉得还不错的话,辛苦帮忙点个赞和在看,蟹蟹啦~❀
想了解更多游戏开发知识,可以扫描下方二维码,免费领取游戏开发4天训练营课程