Unity 4.3 我们发布了第一阶段的2D工具
为此,我们用这个工具做了一个2D范例
这个2D范例叫做"铁桥塔防"
描述伦敦铁桥被外星人入侵的故事
范例完全用2D图片和物理来呈现 让你了解这些元素如何在Unity里组合
影片会说明范例里的背景、前景、角色、特效 镜头追迹、动作和脚本程序是如何制作的
开始之前,先来聊聊基本的Unity 2D工作
首先,当要制作2D项目,你应该先设定工作环境为2D
可以在建立新项目时在下拉选单设定
或是在开发中到Edit - Project Settings - Editor调整
这代表预设情况下，输入的材质会 被视为2D图片，场景视图也会预设为2D
这个新的2D模式会采用完全的 正视图视角来呈现你的2D游戏
同时也会把右上角的3D小图示都隐藏 让工作空间更大
除此之外，Unity 2D的工作流程 是和现有的3D流程整合在一起的
如果你已经会操作原本的Unity 那Unity 2D会很好上手
值得一提的是，你也可以混搭2D和3D共享
所以如果你想要有3D元素在你的2D游戏里 或2D元素在3D游戏里都没有问题
现在来看看范例如何建立一个关卡
我们一开始勾勒关卡设计雏形 然后到Photoshop里面去把每个图层做出来
然后输出这些图层 成为新的Sprite类型导入Unity
为了呈现出背景的视差，我们做了一些 背景元素在Sorting Layer里
这是一个2D工具的新功能
当所有背景指定到这一层后 我们可以在图片着色器的图层排序它们
调好位置之后也可以把图层锁定不能编辑
这样的话我们编辑前景元素的时候 就不用担心会不小心动到背景元素
可以从接口右上方的图层选单来设定
由于背景只是装饰用的，所以 并不需要在图片上放任何组件
将它们放到一个空的对象里
并放入一个叫做叫做 BackgroundParallax的脚本来处里视差
更多的细节可以详查这个已经批注的脚本
接下来制作角色活动的前景空间
我们设计了伦敦铁桥和降落在中间的飞碟
主角处于一个敌人从天而降并到处乱窜的环境
因此，每一个前景元素都需要 碰撞体(Collider)来让主角在上面行走
大多数环境用方体碰撞就可以 除了外型比较复杂的飞碟
Unity提供多边形碰撞体(Polygon Collider) 可以根据图片外型自动产生多边形碰撞体
甚至可以调整碰撞体的外型
你可以新增、移动或删除节点 调整到更适合行走的外型
为了排序前景元素我们建立了前景层 设定显示在背景之前
接下来看看主角
我们的主角也是在Photoshop里面设计的 一个四肢独立类似卡通主角雷曼的角色
另外一个2D工具的新功能
是一个以图表化的动画工具 可以在Photoshop里绘制每一节点的图
后面我们会介绍如何用这方法 制造我们的天鹅
因为身体部位分开比较好控制动画 因此我们希望独立每个身体部位
所以我们将身体部位独立切开 好让Unity在输入时容易拆离它们
这代表我们可以为图片单独制作动作
把这些部位放入建好的角色层 然后改变Z轴深度来改变前后顺序
把这些图片都放入一个有控制脚本 碰撞体、物理设定等等的对象
一旦做到这里，就可以到动画窗口给予图片动作 建立待机、跑、跳、射击和死亡的动画
使用动画窗口里新的分镜表功能 就可以简单制作动作
我们在父对象建立一个动画组件 然后针对每一个子对象建立影格
移动指标到想要的影格后调整角色部位 就会自动把变量录到影格上
可随时切换分镜表和动画曲线 使得它更容易调整设计
这些动作建立好之后我们可以 帮我们的角色设计控制状态
让我们用程序呼叫角色执行各种动作
因为不是驱动3D骨架，所以取消打勾Root Motion
也可以打勾Animate Physics如果 动画要和物理行为相互作用
为了在场景走动，主角脚上有圆形碰撞体 和一个包覆整个身体的方形碰撞体
这样他可以平顺地行走和跳下场景 跳起来的时候头部也可以判定撞到
为了控制角色动作，我们写了 一个脚本透过2D物理引擎来移动
这代表在游戏里面可以指定主角和敌人 让游戏动态更丰富的物理行为
我们用PlayerControl脚本来判断角色的输入
我们在此指定物理移动速度 同时也把输入的值送到动画控制器
判定播放哪些动画以及 顺畅的播放分镜表上图片的转变
使用动画控制建立图片动态最大的好处是
可以调整动画速度用来搭配物理速度 不需要额外再作任何判定
FixedUpdate函式会检查每一步物理运算
在这里我们第一件要做的事情是 把输入的水平值传给动画的速度参数
在我们的状态设定里 待机状态到跑动需要速度参数大于0.1
当值成立时，动画就会从待机切到跑步
要让角色移动，让它有Rigidbody2D组件 就可以为它加力道移动
同时我们也根据输入的水平值是 大于0或小于0来处理角色面朝的方向
这是因为在Unity里，按住左键会传回-1 而按住右键会传回+1
根据输入值呼叫一个简单的翻转函数 来翻转角色的X轴缩放，让角色面向反方向
为了判定角色是否着地 我们新增了一个Ground图层
并指定给全部可行走的前景物件
然后使用2D里面的Linecast函数 检查Ground图层是否和角色的脚接触
为了让制作更容易，我们建立了 一个空白的对象当作检查地面的标准点
在该对象上增加一个小图示 我们就可以控制角色到地面的距离
就游戏角度来看 角色在地面时只能做跳的动作
更多关于角色控制的信息 可以查看范例脚本里面的说明
影片稍后也会讨论角色的武器
接下来看看相机如何追踪角色
跟3D游戏一样，在2D游戏里 镜头运镜也左右着游戏体验
要呈现经典的2D游戏运镜 我们参考了2D游戏经典大作
任天堂或超任的超级玛莉欧的镜头运作
在超级玛莉欧世界里镜头会水平移动 除了封闭的空间或关卡边缘
在这两类区域里角色小幅移动 镜头不会追踪
一旦角色移出区域 镜头又会开始追踪角色
超级玛莉欧的相机 用特定高度来进行垂直判定
但我们的游戏没有往上的长度 比较像动作平台，所以不需要这类设定
因此我们的相机在垂直判定 采用了和水平一样的方法
请看看主相机里的CameraFollow脚本 了解镜头追踪更完整的写法和批注
游戏中有许多特效 但最重要的是主角杀死外星人的能力
主角会发射一个具有 反作用力动画的火箭筒
这个动画由几个部分组成
首先检查输入，当按下Fire键时 产生一个火箭，播放音效并触发火箭动画播放
让我们进一步分解这些步骤
为了可以播放其他动画(跑步)时同时播放火箭发射 我们在动画控制器建立了Shooting的动画层
将Weight属性设为1，可以 完全覆盖基本层(Base Layer)所有的动作
我们可以从任何状态中用程序 触发Shoot参数发射动画
来看看负责这工作的Gun脚本
你可以看到我们写了驱动事件 触发Shoot为True
触发后会打开，在下一格重置为关 就可以重复使用，对于射击动作最好用
除了设定动画，我们也从脚本中发射火箭
播放音效后根据角色的方向 产生火箭并给它一个X轴的正或负速度
这个Gun脚本被放在主角身上的空物件
像这样将脚本放到一个空对象上 可以轻易的定位火箭发射位置
我们将对象放到火箭筒发射口 然后以他自己的坐标当作发射点
火箭本身有2D刚体 我们给它一个速度让它移动
它也有火焰喷射动画和粒子系统做的烟雾
粒子系统也接受新的Sprite图片
所以可以将烟雾的图片切好后加到材质 并指定到粒子系统的Texture Sheet Animation
就有烟雾特效让粒子系统发射
当火箭命中敌人或环境时 火箭本身会引起爆炸并被摧毁
爆炸是我们制作的爆炸动画对象
排序位置在前景的最后面
要建立这类动画，可以从项目点选图片 然后在属性Sprite Mode选择Multiple
这功能允许我们编辑图片 手动或是自动裁切图片大小
一旦完成裁切后
只需要点击Apply Unity会自动产生图片并作为子对象
这就是火箭制作过程
稍后我们将在影片中讨论 杀死敌人的动画技法
现在先让我们回到主角 看看如何处理血条补血和扣血
血条被定义为一个浮点数(Float) 每次碰到敌人就会呼叫TakeDamage函式
为了避免触发太快造成死亡 我们用repeatDamagePeriod来间隔触发时间
为了让角色显示受伤 并容易从敌人手中逃脱
我们建立了受伤的动作 并在物理上弹飞主角
要做到这点，TakeDamage函式 会阻止角色跳跃
并从主角与敌人之间找到一个向量位置
指定一个物理力量往指定方向击退
hurtForce是一个全局变量，可以随时从接口调整 而不用从脚本里调整
除了击退主角之外，我们同时 也扣掉角色的血量并更新血条
为了呈现扣血，我们把血条的宽度缩减 用一个公式计算让绿色转变到红色
透过当下的血量和总量算出一个百分比
血条是由两个图片组成 一个显示血量，另一个显示外框
这也是在Photoshop里做的 然后输出两个单独的图片
导入图形的时候，设定图形轴心在左边 所以当它按比例减少时，就会往左缩
这两个图片放在一个空对象底下 给予一个简单脚本，让它显示在角色头上
将血条位置设定与角色相同
并加上偏移用的全局变量 好在检视接口进行调整
当主角血量为0时，设定碰撞体的isTrigger = true 主角就会往下跌到水上
同时将主角排序推到UI层上 主角会移到画面最上层
UI层是我们制作的层 是用来表示像UI的前面的对象
当脚色死亡时，我们有两个动画
一个叫Death，会失去帽子和枪 另外一个叫Falling
用Exit Time当作动画的切换条件 一旦Death播完就会切到Falling动画
最后，在播放死亡动画时 为了阻止玩家移动角色或射击
我们会禁用PlayerControl和Gun脚本
由于Die函式是全局可以从任何地方呼叫 例如玩家掉入水中
要在主角接触水面时重置游戏，我们 用一个由触发器和脚本组成的KillTrigger对象
在大多的情况下 Remover脚本移除掉入河中的敌人
并播放一个水花动画和音效
但如果是主角被触发器侦测到时
就会呼叫PlayerHealth脚本里的Die函式
并禁用CameraTracking同时将角色移出屏幕 并呼叫co-routiene函数(停止2秒)
然后重生在出生点
接下来焦点转移到角色生存
来看看它是如何生存 和我们给予它甚么生存工具
游戏中有两种帮助玩家的补给箱 一种箱子是炸弹，另一种可以补血
补给箱由箱子和降落伞两个部分组成
这两个元素放入一个空白对象 我们就可以一起触发动画
我们定位这两个图片 降落伞的轴心位于父对象的中心
这样动画可以左右摇摆 让降落伞是浮在空中的感觉
然后增加一个刚体让它有重力往下掉
箱子增加碰撞体用来探测它的着陆时机 和玩家捡起的时机
着陆之后 播放第二段动画让降落伞消失
跟游戏其他地方一样 动画器控制对象的状态
我们可以看到预设的情况下 它会播放FloatDown动画
然后当Land = True时会切换到着陆状态
在脚本里，我们使用onTriggerEnter函数 透过标记来检测是否碰到地面
我们也将补给箱从父对象中分离 并给它一个刚体
它就可以和环境互动 比如降落在一个斜坡上就会斜停在坡上
接下来看看炸弹
捡起炸弹箱的动作是箱子上的 BombPickup脚本处理的
透过角色身上的LayBombs脚本 增减主角拥有的炸弹数量
LayBombs脚本负责检查是否携带着炸弹 并负责产生并放置炸弹
炸弹设有定时装置，在爆炸之前 透过BombDetonation里的yield倒数计时
爆炸函式执行几个动作
它会重置bombLaid参数 允许产生另外一个炸弹箱
它会通知产生器补充新的炸弹箱 并炸死范围内的敌人
来看看最后一部分怎么运作的
因为炸弹对敌人来说是致命的 不管他们的生命值剩下多少
我们用Physics.OverlapCircleAll方法收集 在爆炸范围内所有标记为敌人的对象
然后为每一个敌人执行循环
设定他们的血量为0 从爆炸地点到敌人算出一个向量并施加外力
一旦循环跑完，就可以播放视觉效果
播放一段音效同时摧毁炸弹
爆炸视觉效果有两部分
主要部份是一个简单的圆形 短暂的出现后摧毁
第二部分是星星状的粒子系统 重复用相同图片呈现火箭爆炸
效率上我们保持粒子系统持续在场景中 需要时我们用程序移动到指定位置播放
这样可以让粒子系统存在内存里 使游戏比较有效率
这么做主要是因为这个范例 同时只会有一个爆炸在场景中
因为玩家只能一次丢一个炸弹
这就是为什么将粒子系统保持在场景中 并重复播放的原因，比起建立后移除有效率
但如果是火箭爆炸，因为可以重复发射 因此需要建立后移除
让我们看看主角杀死敌人 怎么计算分数
这分为两个部分，动画显示获得100分 以及增加UI的分数计算
分数动画由1和0两个数字组成
将它们放到场景中的空白对象
给予一个简单的得分动画 并用程序让它们在动画完成后消失
我们放置摧毁脚本在动画事件尾端
ScoreUI单纯是个GUI文字组件 带有管理玩家分数的脚本
Score是全局变量，代表随时可以 检查当敌人被杀死时增加100分
说到敌人，让我们仔细看看他们
在我们的游戏里，有两种类型外星敌人
一种是绿皮肤的鼻涕虫
另一种是会搭着飞船保护自己 的智能型外星怪物
这些角色会共享一种脚本
因为他们行为相似
我们可以检视它们的全局变量 并设定不同的移动速度和生命
每个敌人都有自己的移动动画
鼻涕虫有一个可以活动的尾巴 飞船内的敌人会前后摇摆移动
对鼻涕虫来说，我们汇入图形 并把尾巴切为独立图形
这样我们就可以单独缩放它 不会影响到整个图片
轴心设定到右边 我们可以漂亮的伸展收缩尾巴
上下移动眼睑
然后使用Z轴来排序 眼睛就会在眼睑底下了
就可以制作眨眼动画
第二个外星人的动画要简单的多 我们只需要前后转动它
关于这些敌人的移动技术 我们透过改变刚体的速率来移动它们
当它们遇到一个墙壁这样的障碍物时 会呼叫Physics.OverlapPoint函式来检测
检查是否有重迭到像是 墙壁和两边的塔被标记的障碍物
当函式侦测到时，就会呼叫Flip函式
函式会翻转敌人的X轴缩放 让它转到不同方向
要杀死敌人，当敌人和火箭相撞时 在撞击时会呼叫Hurt函式
这个函式我们从敌人身上扣1点血
并持续呼叫函式保持敌人持续扣血
如果血条降到0，就会呼叫死亡函式
当他们死后，就会执行一些函式
会先停用所有的图形渲染 因为2D角色大多都有动画
这是为了把动画对象换成单张死亡图片
我们在图形渲染器将图片改为deadEnemy
然后我们帮Score全局变量增加100
然后增加扭转让他们死亡时扭曲
因此我们要让这些敌人死后 掉入环境的河中
我们找到对象上所有碰撞体 并设定IsTrigger = True
这样他们就会穿过所有环境往下掉
然后播放死亡音效之后展示一个分数动画
要将已死亡的敌人从场景中移除
我们使用killTregger对象
和前面所说的一样
当任何角色接触它时
将会引起一个水花动画，并移除该对象
它们撞击水面并播放 一段附在水花动画的音效
所以当我们产生水花动画时 同时也听到音效
要完成游戏关卡 我们也用一些移动背景来装饰
为了让游戏环境更显动态
我们添加了一些飞翔的天鹅 以及沿着河岸开的公交车和出租车
首先是天鹅，它是在Photoshop里面画好后 用Multiple Sprite导入图片
Unity会自动裁切天鹅的每个图片
分为不同的图导入 并把原图当作父对象放在底下
因为这是个动画组合，可以将所有的图片 一起拖到场景中，让Unity帮我们生成动画
瞧，天鹅的动画已经准备好了
然后给天鹅一个刚体 让我们可以控制速度飞过屏幕
和公交车和出租车一样，天鹅已被存为预制对象
公交车和出租车作法只需要 在汇入图形时分开车身和车轮
并制作一个简单的摆动动画
相同指定2D刚体到车子上 就能够驱动他们在屏幕上跑
公交车、出租车和天鹅这三个物件 我们用一个重复执行的脚本来制造它们
BackgroundPropsSpawner脚本 同时也处理出生位置，出生频率并给予速度
代表我们可以用这个脚本应用在三种对象 默认出生点和属性
要了解更多的细节，可以查看脚本中的说明
最后，要了解更多的背景动态 我们使用了移动的云朵、流动的河水和烟雾
我们在空白对象下放两个背景图片 并使这些图片缓慢飞过屏幕
因为这是个无限循环 所以动画永远不会停
这就是我们游戏的制作过程
我们希望这个教学让你 对如何用Unity开发2D游戏有一定了解
未来我们也会制作更简单的教学
也期待你们对于Unity4.3的反应 迫不及待想看看你们的2D产品
谢谢观看