2.2
答:Awake —> OnEnable —> Start —> FixedUpdate —>Update —> LateUpdate—> OnGUl —> OnDisable —> OnDestroy
主要执行顺序
编辑器->初始化->物理系统->输入事件->游戏逻辑->场景渲染->GUI渲染->物体激活或禁用->销毁物体->应用结束
主要函数介绍
Reset
是在用户点击检视面板的Reset按钮或者首次添加该组件时被调用。此函数只在编辑模式下被调用。Reset最常用于在检视面板中给定一个最常用的默认值。Awake
用于在游戏开始之前初始化变量或游戏状态。在脚本整个生命周期内它仅被调用一次,当脚本设置为不可用时,运行时Awake方法仍然会执行一次。Awake在所有对象被初始化之后调用,所以你可以安全的与其他对象对话或用诸如 GameObject.FindWithTag 这样的函数搜索它们。每个游戏物体上的Awke以随机的顺序被调用。因此,你应该用Awake来设置脚本间的引用,并用Start来传递信息 ,Awake总是在Start之前被调用。它不能用来执行协同程序。OnEnable
当对象变为可用或激活状态时被调用事件监听。Start
在behaviour的生命周期中只被调用一次。它和Awake的不同是Start只在脚本实例被启用时调用。你可以按需调整延迟初始化代码。Awake总是在Start之前执行。这允许你协调初始化顺序。FixedUpdate
当MonoBehaviour启用时,其在每一帧被调用。处理Rigidbody时,需要用FixedUpdate代替Update。例如:给刚体加一个作用力时,你必须应用作用力在FixedUpdate里的固定帧,而不是Update中的帧。(两者帧长不同)。Update
是实现各种游戏行为最常用的函数。LateUpdate
每帧调用一次(在 在所有Update函数调用后被调用) 用于更新游戏场景和状态,和摄像机相关的更新。 官网上例子是摄像机的跟随,都是所有的Update操作完才进行摄像机的跟进,不然就有可能出现摄像机已经推进了,但是视角里还未有角色的空帧出现。OnGUI
渲染和处理GUI事件时调用。这意味着你的OnGUI程序将会在每一帧被调用。要得到更多的GUI事件的信息查阅Event手册。如果Monobehaviour的enabled属性设为false,OnGUI()将不会被调用。OnDisable
不能用于协同程序。当对象变为不可用或非激活状态时此函数被调用。OnDestroy
当对象被销毁时调用。OnApplicationQuit
当用户停止运行模式时在编辑器中调用。当web被关闭时在网络播放器中被调用。
答:碰撞器是触发器的载体,而触发器只是碰撞器身上的一个属性。
当Is Trigger=false时,碰撞器根据物理引擎引发碰撞,产生碰撞的效果,可以调用OnCollisionEnter/Stay/Exit函数;
当Is Trigger=true时,碰撞器被物理引擎所忽略,没有碰撞效果,可以调用OnTriggerEnter/Stay/Exit函数。
如果既要检测到物体的接触又不想让碰撞检测影响物体移动或要检测一个物件是否经过空间中的某个区域这时就可以用到触发器。
答:两个物体都必须带有碰撞器Collider,其中一个物体还必须带有Rigidbody刚体。
Unity的脚本语言基于Mono的.Net平台上运行,可以使用.NET库,这也为XML、数据库、正则表达式等问题提供了很好的解决方案。
Unity里的脚本都会经过编译,他们的运行速度也很快。这三种语言实际上的功能和运行速度是一样的,区别主要体现在语言特性上。
Unity支持的语言:C#,JavaScrip(不在使用)
mono是.net的一个开源跨平台工具,就类似java虚拟机,java本身不是跨平台语言,但运行在虚拟机上就能够实现了跨平台。
.net只能在windows下运行,mono可以实现跨平台编译运行,可以运行于Linux,Unix,Mac OS等。
答:Awake–>OnEnable->Start
OnEnable在同一周期中可以反复地发生!
LateUpdate,是在所有的Update结束后才调用,比较适合用于命令脚本的执行。
官网上例子是摄像机的跟随,都是所有的Update操作完才进行摄像机的跟进,不然就有可能出现摄像机已经推进了,但是视角里还未有角色的空帧出现。
FixedUpdate,每固定帧绘制时执行一次,和Update不同的是FixedUpdate是渲染帧执行,如果你的渲染效率低下的时候FixedUpdate调用次数就会跟着下降。
FixedUpdate比较适用于物理引擎的计算,因为是跟每帧渲染有关。 Update就比较适合做控制。
四种。
答:四元数⽤于表示旋转,对旋转⻆度进⾏计算时⽤到四元数
相对欧拉⻆的优点:
1)能进⾏增量旋转
2)避免万向锁
3)给定⽅位的表达⽅式有两种,互为负(欧拉⻆有⽆数种表达⽅式)
Rigidbody具有完全真实物理的特性,而CharacterController可以说是受限的的Rigidbody,具有一定的物理效果但不是完全真实的。
localPosition :自身坐标系,相对于父级的位置
Position :世界坐标系中的位置
在游戏运行时实例化,prefab相当于一个模板,对你已经有的素材、脚本、参数做一个默认的配置,主要用于经常会用到的物体做成一个集合方便反复使用,以便于以后的修改,同时prefab打包的内容简化了导出的操作,便于团队的交流。
进程
线程
协程
在Unity中只有主线程才能访问Unity3D的对象、方法、组件。当主线程在执行一个对资源消耗很大的操作时,在这一帧我们的程序就会出现帧率下降,画面卡顿的现象!
那这个时候我们就可以利用协程来做这件事,因为协程是伴随着主线程运行的,主线程依旧可以丝滑轻松的工作,把脏活累活交给协程处理就好了!简单来说:协程是辅助主线程的操作,避免游戏卡顿。
从程序的角度讲,协程的核心就是
迭代器
。
想要定义一个协程方法有两个因素,第一:方法的返回值为 IEnumerator 。第二,方法中有 yield关键字。
当代码满足以上两个条件时,此方法的执行就具有了迭代器的特质,其核心就是 MoveNext方法。
方法内的内容将会被分成两部分:yield 之前的代码和 yield 之后的代码。yield之前的代码会在第一次执行MoveNext时执行, yield之后的代码会在第二次执行MoveNext方法时执行。
而在Unity中,MoveNext的执行时机是以帧为单位的,无论你是设置了延迟时间,还是通过按钮调用MoveNext,亦或是根本没有设置执行条件,Unity都会在每一帧的生命周期中判断当前帧是否满足当前协程所定义的条件,一旦满足,当前帧就会抽出CPU时间执行你所定义的协程迭代器的MoveNext。
注意,只要方法中有yield语句,那么方法的返回值就必须是 IEnumerator ,不然无法通过编译。
线程和协同程序的主要不同在于:在多处理器情况下,从概念上来讲多线程程序同时运行多个线程;而协同程序是通过协作来完成,在任一指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只在必要时才会被挂起。
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() 方法。
原因:因为游戏物体隐藏了,一切与游戏物体相关的脚本生命周期都会停止,协程自然也会停止 ;
如果游戏对象没有隐藏,只是将脚本隐藏,游戏对象照样可以通过反射获取协程迭代器对象继续协程的执行。
答:OnCollisionEnter、 OnCollisionStay、 OnCollisionExit
自身旋转:transform.Rotate()
绕某点旋转:transform.RotateAround
PlayerPrefs类是一个本地持久化保存与读取数据的类
PlayerPrefs类支持3中数据类型的保存和读取,浮点型,整形,和字符串型。
分别对应的函数为:
受Camera覆盖各场景物件均同时实时绘制,主Camera视场里有多个Camera的渲染合集。可以用depth(深度),Layer(层)+ Culling Mask,enable = false/true来控制,或者调整Viewport Rect可以调整不同摄像机的显示内容。
使用Destroy()方法;
主要有关节动画、骨骼动画、单一网格模型动画(关键帧动画)。
关节动画:把角色分成若干独立部分,一个部分对应一个网格模型,部分的动画连接成一个整体的动画,角色比较灵活,Quake2中使用这种动画;
骨骼动画,广泛应用的动画方式,集成了以上两个方式的优点,骨骼按角色特点组成一定的层次结构,有关节相连,可做相对运动,皮肤作为单一网格蒙在骨骼之外,决定角色的外观;
单一网格模型动画由一个完整的网格模型构成,在动画序列的关键帧里记录各个顶点的原位置及其改变量,然后插值运算实现动画效果,角色动画较真实。
一般是组件上绑定的对象被删除了,导致组件找不到该对象了而出现数据丢失现象。或者对象在Editor外部被删除和移动位置。
Alpha Blend 实现透明效果,不过只能针对某块区域进行alpha操作,透明度可设。
diffuse = Kd x colorLight x max(N*L,0);Kd 漫反射系数、colorLight 光的颜色、N 单位法线向量、L 由点指向光源的单位向量、其中N与L点乘,如果结果小于等于0,则漫反射为0。
LOD(Level of detail)多层次细节,是最常用的游戏优化技术。
它按照模型的位置和重要程度决定物体渲染的资源分配,降低非重要物体的面数和细节度,从而获得高效率的渲染运算。
缺点:增加了内存
LOD简单示例:【100个 Unity踩坑小知识点】| Unity 的 LOD技术(多细节层次)
本影和半影:
顶点着色器 是一段执行在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几个过程。
MipMapping:在三维计算机图形的贴图渲染中有常用的技术,为加快渲染进度和减少图像锯齿,贴图被处理成由一系列被预先计算和优化过的图片组成的文件,这样的贴图被称为MipMap。
语法不同处:
用法不同处:
对象池就存放需要被反复调用资源的一个空间。
比如游戏中要常被大量复制的对象,子弹,敌人,以及任何重复出现的对象。
特点:用内存换取cpu的优化
支持:如果同时你要处理很多事情或者与Unity的对象互动小可以用thread,否则使用coroutine。
Unity3d没有多线程的概念,不过unity也给我们提供了StartCoroutine(协同程序)和LoadLevelAsync(异步加载关卡)后台加载场景的方法。
注意:仅能从主线程中访问Unity3D的组件,对象和Unity3D系统调用。C#中有lock这个关键字,以确保只有一个线程可以在特定时间内访问特定的对象
DontDestroyOnLoad(transform.gameObject);
Transform 父类是 Component
用于表示线性变换:旋转、缩放、投影、平移、仿射
注意矩阵的蠕变:误差的积累
穿透(碰撞检测失败)(例如CS射击游戏,可以使用开枪时发射射线,射线碰撞到则掉血击中)
使用动态字体时,Unity将不会预先生成一个与所有字体的字符纹理, 静态字体体积会很大。
多屏幕分辨率下的UI布局一般考虑两个问题:
为了解决这两个问题,在Unity UGUI体系中有两个组件可以来解决问题,分别是布局元素的Rect Transform和Canvas的Canvas Scaler组件。
CanvasScaler中UI Scale Mode有三种模式,Constant Pixel Size、Scale With Screen Size、Constant Physical Size,其中第二个就是根据屏幕分辨率来进行缩放适配。在这个模式下,有两个参数,一个是我们在开发过程中的标准分辨率,一个是屏幕的匹配模式,通过这里面的设置,就可以完成多分辨率下的适配问题。
当物体是否可见切换之时。可以用于只需要在物体可见时才进行的计算。
如果动态物体共用着相同的材质,那么Unity会自动对这些物体进行批处理。
动态批处理操作是自动完成的,并不需要你进行额外的操作。
区别:动态批处理一切都是自动的,不需要做任何操作,而且物体是可以移动的,但是限制很多。静态批处理:自由度很高,限制很少,缺点可能会占用更多的内存,而且经过静态批处理后的所有物体都不可以再移动了。
LightMap:就是指在三维软件里实现打好光,然后渲染把场景各表面的光照输出到贴图上,最后又通过引擎贴到场景上,这样就使物体有了光照的感觉。
Unity3D支持C#、javascript等,cocos2d-x 支持c++、Html5、Lua等。
cocos2d 开源 并且免费
Unity3D支持iOS、Android、Flash、Windows、Mac、Wii等平台的游戏开发,cocos2d-x支持iOS、Android、WP等。
剪裁平面 。从相机到开始渲染和停止渲染之间的 距离。
简而言之,GPU的图形(处理)流水线完成如下的工作:(并不一定是按照如下顺序)。
顶点处理:这阶段GPU读取描述3D图形外观的顶点数据并根据顶点数据确定3D图形的形状及位置关系,建立起3D图形的骨架。在支持DX8和DX9规格的GPU中,这些工作由硬件实现的Vertex Shader(定点着色器)完成。
光栅化计算:显示器实际显示的图像是由像素组成的,我们需要将上面生成的图形上的点和线通过一定的算法转换到相应的像素点。把一个矢量图形转换为一系列像素点的过程就称为光栅化。例如,一条数学表示的斜线段,最终被转化成阶梯状的连续像素点。
纹理帖图:顶点单元生成的多边形只构成了3D物体的轮廓,而纹理映射(texture mapping)工作完成对多变形表面的帖图,通俗的说,就是将多边形的表面贴上相应的图片,从而生成“真实”的图形。TMU(Texture mapping unit)即是用来完成此项工作。
像素处理:这阶段(在对每个像素进行光栅化处理期间)GPU完成对像素的计算和处理,从而确定每个像素的最终属性。在支持DX8和DX9规格的GPU中,这些工作由硬件实现的Pixel Shader(像素着色器)完成。
最终输出:由ROP(光栅化引擎)最终完成像素的输出,1帧渲染完毕后,被送到显存帧缓冲区。
总结:GPU的工作通俗的来说就是完成3D图形的生成,将图形映射到相应的像素点上,对每个像素进行计算确定最终颜色并完成输出。
是指在显示器上为了显示出图像而经过的一系列必要操作。 渲染管道中的很多步骤,都要将几何物体从一个坐标系中变换到另一个坐标系中去。
主要步骤有: 本地坐标->视图坐标->背面裁剪->光照->裁剪->投影->视图变换->光栅化。
Alpha Test,中文就是透明度测试。
简而言之就是V&F shader中最后fragment函数输出的该点颜色值(即上一讲frag的输出half4)的alpha值与固定值进行比较。Alpha Test语句通常于Pass{}中的起始位置。Alpha Test产生的效果也很极端,要么完全透明,即看不到,要么完全不透明。
仅深度,该模式用于对象不被裁剪。
Hinge Joint,可以模拟两个物体间用一根链条连接在一起的情况,能保持两个物体在一个固定距离内部相互移动而不产生作用力,但是达到固定距离后就会产生拉力。
设置游戏对象为Static将会剔除(或禁用)网格对象当这些部分被静态物体挡住而不可见时。因此,在你的场景中的所有不会动的物体都应该标记为Static。
把A组物体的渲染对列大于B物体的渲染队列
Sprite作为UI精灵使用,Texture作用模型贴图使用。
答:没有区别,因为不管几张贴图只渲染一次。
Unity中,每次引擎准备数据并通知GPU的过程称为一次Draw Call。DrawCall越高对显卡的消耗就越大。
降低DrawCall的方法:
可以有cookies – 带有 alpha通道的立方图(Cubemap )纹理。点光源是最耗费资源的。
在Game视图右上角点击Stats。降低Draw Call 的技术是Draw Call Batching
对于AddComponent添加的脚本,其Awake,Start,OnEnable是在Add的当前帧被调用的
其中Awake,OnEnable与AddComponent处于同一调用链上
Start会在当前帧稍晚一些的时候被调用,Update则是根据Add调用时机决定何时调用:如果Add是在当前帧的Update前调用,那么新脚本的Update也会在当前帧被调用,否则会被延迟到下一帧调用。
用layermask ,通过位运算的方式去设置
在代码中使用时如何开启某个Layers?
LayerMask mask = 1 << 你需要开启的Layers层。
LayerMask mask = 0 << 你需要关闭的Layers层。
举几个例子:
LayerMask mask = 1 << 2; 表示开启Layer2。
LayerMask mask = 0 << 5;表示关闭Layer5。
LayerMask mask = 1<<2|1<<8;表示开启Layer2和Layer8。
LayerMask mask = 0<<3|0<<7;表示关闭Layer3和Layer7。
顶点着⾊器是⼀段执⾏在GPU上的程序,⽤来取代 fixed pipeline中的transformation和lighting,Vertex Shader主要操作顶点。‘’
像素着色器实际上就是对每一个像素进行光栅化的处理期间,在GPU上运算的一段程序。
不同与顶点着色器,像素着色器不会以软件的形式来模拟像素着色器。
像素着色器实质上是取代了固定功能流水线中多重纹理的环节,而且赋予了我们访问单个像素以及访问每一个像素纹理坐标的能力
缩放模式:
Property: | Function: |
---|---|
UI Scale Mode | Canvas中UI元素的缩放模式 |
Constant Pixel Size | 使UI保持自己的尺寸,与屏幕尺寸无关。 |
Scale With Screen Size | 屏幕尺寸越大,UI越大 |
Constant Physical Size | 使UI元素保持相同的物理大小,与屏幕尺寸无关。 |
Constant Pixel Size、Constant Physical Size实际上他们本质是一样的,只不过 Constant Pixel Size 通过逻辑像素大小调节来维持缩放,而 Constant Physical Size 通过物理大小调节来维持缩放。 |
FSM是一种数据结构,它由以下几个部分组成:
为什么要用FSM?
因为它编程快速简单,易于调试,性能高,与人类思维相似从而便于梳理,灵活且容易修改
FSM的描述性定义:
一个有限状态机是一个设备,或是一个模型,具有有限数量的状态。它可以在任何给定时间根据输入进行操作,使得系统从一个状态转换到另一个状态,或者是使一个输出或者一种行为的发生,一个有限状态机在任何瞬间只能处于一种状态。
State 状态基类,定义了基本的Enter,Update,Exit三种状态行为,通常在这三种状态行为的方法里会写一些逻辑。每个State都会有StateID(状态id,可以是枚举等),FSMControl(控制该状态的状态控制器的引用),Check方法(用来进行状态判断,并返回StateID,通过FSMControl驱动)
FSMControl,包含了一下FSMMachine,封装层。
FSMMachine,驱动它的State列表,Update方法调用当前State的Check方法来获得StateID,当currentState的Check方法返回的StateID和当前StateID不同,则切换状态。
这是一个简单的FSM状态机系统,根据需要自己写个Control继承FSMControl来驱动状态。因为Check是State的职责,所以每一个不同对象的行为如Human的Idle和Dog的Idel区分肯定也不同。因此需要分别去写HumanIdleState和DogIdleState。如果还有Cat,Fish,可想而知代码量会有多么庞大。
因此我将FSMControl抽象为一个公共基类,把State的Check具体实现作为FSMControl的Virtual方法。这样在IdleState里的Check方法就不用写具体的状态切换判断逻辑,而是调用它FSMControl子类(自己写的继承自FSMControl的Control类)的重写方法
这样每次添加的新对象只要有Idle这个状态,就可以用一个公用的StateIdle,状态切换的逻辑差异放在Control层
有限状态机系统:是指在不同阶段会呈现出不同的运行状态的系统,这些状态是有限的、不重叠的。这样的系统在某一时刻一定会处于其所有状态中的一个状态,此时它接收一部分允许的输入,产生一部分可能的响应,并且迁移到一部分可能的状态。
行为树:一个流行的AI技术,涵盖了层次状态机,事件调度,事件计划,行为等一系列技术。实现AI的过程更加得有技巧,框架设计者较为全面考虑了我们可能会遇到的种种情况,把每种情况都抽象成了一个类型的节点,而我们要做的就是按照规范去写节点,然后把节点连接成一颗行为树。更加得具有面向对象的味道,行为模块间的藕合度相对较低。
概念:
优点:
缺点:
Text是像素渲染放大之后就会模糊,使用Text父物体的放大缩小会影响子物体Text的清晰度, TMPText不会,它是网格渲染TMPText会把字体生成一个类似于贴图的东西然后读取贴图的坐标来获取对应的文字,更换文字的消耗会比Text大。
TMPText更适用于不会变动的文字,特别是在量大的情况下,性能比Text高一些,需要经常变动的问题用Text好点,TMPText在字体库很大的情况下查找更换会比较慢。
思路:
红点系统基于MVC的思想,将分为三层:数据层,驱动层,显示层。
更多详细内容可以看下面文章:
Unity之红点树系统多层级高效能
Unity手游实战:从0开始SLG——独立功能扩展(三)用树实现客户端红点系统
Animation和Animator 虽然都是控制动画的播放,但是它们的用法和相关语法都是大有不同的。Animation控制一个动画的播放,而Animator是多个动画之间相互切换,并且Animator有一个动画控制器,俗称动画状态机。
Animator利用它做动画的切换是很方便的,但是它有一个缺点就是占用内存比Animation大。
根据骨骼,动态整体实现表层Mesh,相对普通mesh由不同面片堆砌,根据骨骼结构,对顶点的变换计算出不同的蒙皮,最终进行模型的渲染
答:修改sharedMaterial将改变所有物体使用这个材质的外观,并且也改变储存在工程里的材质设置。 不推荐修改由sharedMaterial返回的材质。如果你想修改渲染器的材质,使用material替代。
ScriptableObject是一个数据容器,它可以用来保存大量数据。
更多详细内容可以看下面文章:Unity零基础到进阶 | Unity中Scriptable Object介绍学习
//获取的目录路径最后不包含 /
//获得的文件路径开头包含 /
Application.dataPath; //Asset文件夹的绝对路径
//只读
Application.streamingAssetsPath; //StreamingAssets文件夹的绝对路径(要先判断是否存在这个文件夹路径)
Application.persistentData ; //可读写
//资源数据库 (AssetDatabase) 是允许您访问工程中的资源的 API
AssetDatabase.GetAllAssetPaths; //获取所有的资源文件(不包含meta文件)
AssetDatabase.GetAssetPath(object) //获取object对象的相对路径
AssetDatabase.Refresh(); //刷新
AssetDatabase.GetDependencies(string); //获取依赖项文件
Directory.Delete(p, true); //删除P路径目录
Directory.Exists(p); //是否存在P路径目录
Directory.CreateDirectory(p); //创建P路径目录
AssetDatabase //类库,对Asset文件夹下的文件进行操作,获取相对路径,获取所有文件,获取相对依赖项
Directory //类库,相关文件夹路径目录进行操作,是否存在,创建目录,删除等操作
因人而异,可以去简单了解一下要说的插件,没用过也可以,至少你知道这个插件了!
插件名 | 作用 |
---|---|
shader graph | 制作shader光影效果 |
cinemachine+timeline+postprocessingstack | 制作过场动画 |
nodecanvas | 制作怪物ai |
easytouch | 手游触摸控制 |
DoTween | 动画插件 |
Fungus | 对话插件 |
3D WebView | 浏览器插件 |
Vectrosity | 划线插件 |
AVPro Video | 视频播放插件 |
Feel | 受击插件 |
Device Simulator | 移动设备模拟器 |
StateMachine | 状态机插件 |
资料白嫖,技术互助
博客主页:https://xiaoy.blog.csdn.net
本文由 呆呆敲代码的小Y 原创
学习专栏推荐:Unity系统学习专栏
游戏制作专栏推荐:游戏制作
Unity实战100例专栏推荐:Unity 实战100例 教程
欢迎点赞 收藏 ⭐留言 如有错误敬请指正!
未来很长,值得我们全力奔赴更美好的生活✨
------------------❤️分割线❤️-------------------------
学习路线指引(点击解锁) | 知识定位 | 人群定位 |
---|---|---|
Unity系统学习专栏 | 入门级 | 本专栏从Unity入门开始学习,快速达到Unity的入门水平 |
Unity实战类项目 | 进阶级 | 计划制作Unity的 100个实战案例!助你进入Unity世界,争取做最全的Unity原创博客大全。 |
❤️ 游戏制作专栏 ❤️ | 难度偏高 | 分享学习一些Unity成品的游戏Demo和其他语言的小游戏! |
游戏爱好者万人社区 | 互助/吹水 | 数万人游戏爱好者社区,聊天互助,白嫖奖品 |
Unity100个实用技能 | Unity查漏补缺 | 针对一些Unity中经常用到的一些小知识和技能进行学习介绍,核心目的就是让我们能够快速学习Unity的知识以达到查漏补缺 |