【Unity学习笔记】Beginning 2D Game Development
1. class:定义一个新要素;start()和update()都是函数
2. tilemap:可以在每个格子里设置不同的sprite,它们在视觉上可以彼此连到一起。
2D Object > Tilemap。Tilemap是Grid的子对象。Tilemap由Tile组成。
3. 如何创建2D地图
(1)创建图块地图(tilemap)
层级(Hierarchy)窗口>2D Object>Tilemap
创建一个新游戏对象,由Grid(网格)以及子对象Tilemap组成
(2)创建图块(tile)文件夹
项目(Project)窗口>Assets>Art(范例文件夹,即存放源图像的文件夹)
创建Tiles文件夹
(3)调整源图像设置
源图像应为sprite格式
项目窗口>Art>Sprites>Environment
选择相应源图像,打开检查器,在Pixel Per Unit中将值调整为与源图像大小相同的值,并点击“应用”。
(4)分割
还是在检查器中,打开Sprite Editor,在顶部Type下拉菜单中选择Grid by Cell Count,根据需求选择Column & Row的值,例如(3*3)。
然后点击分割(Slice)和应用。
(5)将源图像转换为图块
将项目窗口中分割好的源图像整体拖拽入调色板(Palette)窗口,另存到Tiles文件夹。
(6)修改图层顺序
层级窗口>Tilemap>Tilemap Renderer>Additional Settings>Order in Layer
数字越小(可为负,默认为0),图层越靠下。
(7)关于遮挡物的图层顺序
根据y来决定图层顺序,y较小(位置较低)的物体应该在y较大(位置较高)的物体之后绘制(在上层)。
Edit>Project Settings>Graphics>Camera Settings>Transparency Sort Mode>Custom Axis>增加下列坐标:x=0,y=1,z=0
玩家>Sprite Renderer>Sprite Sort Point>Pivot
Pivot:轴心点,可以自主定义。该点为物体坐标。
改变轴心点位置:
Project window>Assets>Art>Sprites>Environment>MetalCube>Pivot>Bottom
或者,Sprite Editor>Pivot>Custom Pivot>x=0.5, y=0
4. 关于2D物体的物理
(1)物理系统的更新频率与游戏不同。Update是在游戏每次计算出新图像时更新,但每秒的新图像数量可能有很大差异。为了让物理计算频率稳定,需要使用FixedUpdate,但这有可能错过输入值,因此需要增加两个浮点变量来储存Update函数内当前的水平数值和垂直数值。
(2)为了确保物体的正确遮挡,碰撞器的尺寸需要调整为只覆盖下半部分。
5. 生命值函数
currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth);
Mathf.Clamp:返回在最小值与最大值之间的结果。
6. 碰撞检测函数
7. 在if函数中提取其他脚本中的值:Property
目的:不将变量改为公开,以免其他脚本中的误操作改变原变量的值。
Property定义:
public int health { get { return currentHealth; }}
property的应用类似于变量而非函数
get只读,set只写。
8. 伤害物
伤害不能是持续的(默认为每帧),否则血会瞬间掉没(每秒30帧),所以每伤害一次后要给玩家一定免疫时间,这里需要做个倒计时器(本例中为2秒),倒计时结束后再次计算伤害,直至生命值掉为零。
另一个新知识点是,Unity为了节省运行空间,只有在运动时才会计算刚体,不运动时刚体是休眠的。而本例中玩家停留在伤害物中的时候也会掉血,所以需要在玩家刚体中把相应属性改为“持续唤醒”。
9. 拉伸物体时使其自动根据尺寸平铺
Sprite Renderer>Draw Mode>Tiled>Tiled Mode>Adaptive
Project>Mesh Type>Full Rect
Box Collider 2D>Auto Tiling
10. OnTriggerEnter和OnCollisionEnter的区别
前者无碰撞(可穿过),后者有碰撞(不可穿过)。
11. 动画与动画控制器
(1)动画
Prefab>Add Component>Animator
Window>Animation>Animation
导入需要的动作(取名)>右上菜单>Samples>设置每秒帧数
(2)动画控制器
图层:对3D动画很有用,它让我们可以在角色的不同部分使用动画。
参数:脚本用其向控制器传达信息
动画状态机:所有动画状态及其之间的过渡关系。
混合树(Blend Tree):根据参数混合多个动画。
在动画器中,单击右键>Create State>From New Blend Tree,双击Blend Tree,点击Blend Tree节点,Blend Type>2D Simple Directional
参数>创建两个浮点参数Move X和Move Y>Blend Tree的参数分别选中Move X和Move Y。
Motion>Add Motion Field(4次),拖入相应动画片段
Left : Pos X = -0.5 Pos Y = 0
Right: Pos X = 0.5 Pos Y = 0
Up: Pos X = 0 Pos Y = 0.5
Down: Pos X = 0 Pos Y = -0.5
脚本:
12. Awake与Start
Awake在物体创建后立即唤起,而Start只在游戏开始后唤起一次。
13. 图层:解决子弹与玩家碰撞的问题
将玩家放在一个图层,将子弹放在另一个图层,并告诉物理系统玩家和子弹不会碰撞。
最多可有32个图层。
14. 自动控制摄像机
Window>Package Manager>Cinemachine
Cinemachine可以控制多个摄像机的移动和切换,比如同一段对话中的正反打镜头。Cinemachine通过虚拟摄像机(Virtual Cameras)实现这些功能,我们可以给每个虚拟摄像机选择不同设置,然后告诉真实摄像机(Main Camera)现在哪个虚拟摄像机是活跃的,并复制其设置。
Zoom-in:Orthographic Size数值调大
Orthographic size:摄像头视野高度的一半
摄像头跟随主角:将Hierarchy中的对象拖拽入摄像头的Follow
防止游戏视野超出地图边界:Virtual Camera Inspector>Add Extension>CinemachineConfiner,建立空物体>Add Component>Polygon Collider 2D,设好碰撞器边界,然后将该物体拖入虚拟摄像头的Bounding Shape 2D。增加一个Confiner图层,将该物体设为该图层,然后在Project Setting中取消Confiner与所有图层之间的碰撞。
15. 粒子系统
粒子效果可以通过用图片替换粒子来实现。使用图片时,同样要经过分割。
Sprite Mode>Multiple
需调整的变量:Texture Sheet Animation>Start Frame(Random Between Two Constants)&Frame over time(删除帧)、Shape>Radius(0)&angle(5)、Start Lifetime、Start Size、Start Speed、Color over Lifetime(调透明度)、Size Over Lifetime(拉曲线)
Simulation Space(Local=>World)
public ParticleSystem smokeEffect;(没有用GameObject是因为拖拽物体到窗口中时,会自动提取出该类型的组件,在脚本中不用再GetComponent,也防止拖拽不含该类型组件的GameObject而出现bug)。
对于粒子系统,使用Stop可以让已产生的粒子自然消失,只是不再产生新粒子。而Destroy是删除粒子系统,因此所有粒子将同时消失。
解决粒子遮挡问题:在使用粒子系统的物体上增加组建Sorting Group,然后在物体的Sprite Render>Additional Settings>Order in Layer中将图层顺序选为0
循环系统:去掉Looping前面的勾,设置Duration,并将Stop Action设为Destroy
爆炸效果:Rate over Time(每秒产生的粒子数),Rate over Distance(只有在物体移动时才产生粒子),Emission>Bursts>"+"。例如,打击效果:去掉Looping前面的勾并将Stop Action设为Destroy>Rate over Time设为0,设为在0.0秒产生20个粒子。
16. UI系统
Canvas的三种模式:Screen Space-Overlay(默认模式,始终在游戏最上层描绘UI)、Screen Space-Camera(在与摄像机匹配的平面上描绘UI,可以被游戏物体覆盖)、World Space(可以放在游戏中任何地方)
用遮罩(mask)制作血条
静态(static):变量和函数都可以是静态,设为公共静态后,可以直接从其他脚本中引用,而不用先获取游戏对象。
单例(Singleton):静态的特例,只能存在一个该类物体。不能有其他物体的参数存到该静态中。
17. 音效
在Unity中,负责“听”声音的“耳朵”一般是绑在主摄像机上的,让摄像机走到哪里,就听取它周围的声音。游戏中的背景乐、打击声、加血声使用的都是2D音效,如果不手动调节,它们的音量是不会变化的。不过,机器人的脚步声使用了3D音效。当狐狸子走近机器人时,脚步声会变大,远离机器人时,脚步声会变小(而且是环绕立体声效果,戴耳机听比较明显)。如果狐狸子走出3D音效的范围(是个立体圆球)外,脚步声就会消失。
这里出现一个问题:在2D游戏中,主摄像机和游戏画面并不在一个水平面上,这就导致绑在主摄像机上的“耳朵”可能因为在音效球体范围外而听不到声音。这时可以在主摄像机下添加一个子对象,把“耳朵”绑在这个子对象上,并将子对象的位置设为和游戏画面在一个水平面,问题就解决了。