1 00:00:00,000 --> 00:00:04,295 Unity 4.3 我们发布了第一阶段的2D工具 2 00:00:04,295 --> 00:00:08,295 为此,我们用这个工具做了一个2D范例 3 00:00:08,295 --> 00:00:11,527 这个2D范例叫做"铁桥塔防" 4 00:00:11,527 --> 00:00:15,556 描述伦敦铁桥被外星人入侵的故事 5 00:00:15,556 --> 00:00:23,472 范例完全用2D图片和物理来呈现 让你了解这些元素如何在Unity里组合 6 00:00:23,472 --> 00:00:31,639 影片会说明范例里的背景、前景、角色、特效 镜头追迹、动作和脚本程序是如何制作的 7 00:00:31,639 --> 00:00:36,139 开始之前,先来聊聊基本的Unity 2D工作 8 00:00:36,860 --> 00:00:43,040 首先,当要制作2D项目,你应该先设定工作环境为2D 9 00:00:43,040 --> 00:00:47,040 可以在建立新项目时在下拉选单设定 10 00:00:47,040 --> 00:00:53,172 或是在开发中到Edit - Project Settings - Editor调整 11 00:00:53,172 --> 00:00:59,630 这代表预设情况下,输入的材质会 被视为2D图片,场景视图也会预设为2D 12 00:00:59,630 --> 00:01:04,420 这个新的2D模式会采用完全的 正视图视角来呈现你的2D游戏 13 00:01:04,420 --> 00:01:10,197 同时也会把右上角的3D小图示都隐藏 让工作空间更大 14 00:01:10,197 --> 00:01:17,040 除此之外,Unity 2D的工作流程 是和现有的3D流程整合在一起的 15 00:01:17,040 --> 00:01:22,929 如果你已经会操作原本的Unity 那Unity 2D会很好上手 16 00:01:22,929 --> 00:01:27,219 值得一提的是,你也可以混搭2D和3D共享 17 00:01:27,219 --> 00:01:32,870 所以如果你想要有3D元素在你的2D游戏里 或2D元素在3D游戏里都没有问题 18 00:01:33,366 --> 00:01:38,312 现在来看看范例如何建立一个关卡 19 00:01:38,812 --> 00:01:44,812 我们一开始勾勒关卡设计雏形 然后到Photoshop里面去把每个图层做出来 20 00:01:45,312 --> 00:01:51,312 然后输出这些图层 成为新的Sprite类型导入Unity 21 00:01:58,373 --> 00:02:06,515 为了呈现出背景的视差,我们做了一些 背景元素在Sorting Layer里 22 00:02:06,515 --> 00:02:09,658 这是一个2D工具的新功能 23 00:02:10,158 --> 00:02:17,379 当所有背景指定到这一层后 我们可以在图片着色器的图层排序它们 24 00:02:17,379 --> 00:02:21,379 调好位置之后也可以把图层锁定不能编辑 25 00:02:21,379 --> 00:02:27,751 这样的话我们编辑前景元素的时候 就不用担心会不小心动到背景元素 26 00:02:27,751 --> 00:02:31,751 可以从接口右上方的图层选单来设定 27 00:02:32,817 --> 00:02:39,531 由于背景只是装饰用的,所以 并不需要在图片上放任何组件 28 00:02:39,531 --> 00:02:41,531 将它们放到一个空的对象里 29 00:02:41,531 --> 00:02:46,201 并放入一个叫做叫做 BackgroundParallax的脚本来处里视差 30 00:02:46,201 --> 00:02:50,643 更多的细节可以详查这个已经批注的脚本 31 00:02:54,914 --> 00:02:59,400 接下来制作角色活动的前景空间 32 00:02:59,790 --> 00:03:03,466 我们设计了伦敦铁桥和降落在中间的飞碟 33 00:03:03,466 --> 00:03:09,216 主角处于一个敌人从天而降并到处乱窜的环境 34 00:03:09,216 --> 00:03:13,632 因此,每一个前景元素都需要 碰撞体(Collider)来让主角在上面行走 35 00:03:13,632 --> 00:03:21,239 大多数环境用方体碰撞就可以 除了外型比较复杂的飞碟 36 00:03:22,505 --> 00:03:28,724 Unity提供多边形碰撞体(Polygon Collider) 可以根据图片外型自动产生多边形碰撞体 37 00:03:28,724 --> 00:03:32,053 甚至可以调整碰撞体的外型 38 00:03:32,053 --> 00:03:38,164 你可以新增、移动或删除节点 调整到更适合行走的外型 39 00:03:38,664 --> 00:03:45,599 为了排序前景元素我们建立了前景层 设定显示在背景之前 40 00:03:48,875 --> 00:03:50,875 接下来看看主角 41 00:03:53,709 --> 00:04:03,598 我们的主角也是在Photoshop里面设计的 一个四肢独立类似卡通主角雷曼的角色 42 00:04:03,598 --> 00:04:05,598 另外一个2D工具的新功能 43 00:04:05,598 --> 00:04:09,643 是一个以图表化的动画工具 可以在Photoshop里绘制每一节点的图 44 00:04:09,643 --> 00:04:14,365 后面我们会介绍如何用这方法 制造我们的天鹅 45 00:04:15,072 --> 00:04:20,196 因为身体部位分开比较好控制动画 因此我们希望独立每个身体部位 46 00:04:20,196 --> 00:04:27,959 所以我们将身体部位独立切开 好让Unity在输入时容易拆离它们 47 00:04:28,763 --> 00:04:33,096 这代表我们可以为图片单独制作动作 48 00:04:33,096 --> 00:04:40,921 把这些部位放入建好的角色层 然后改变Z轴深度来改变前后顺序 49 00:04:48,811 --> 00:04:56,591 把这些图片都放入一个有控制脚本 碰撞体、物理设定等等的对象 50 00:04:56,591 --> 00:05:07,095 一旦做到这里,就可以到动画窗口给予图片动作 建立待机、跑、跳、射击和死亡的动画 51 00:05:07,095 --> 00:05:11,795 使用动画窗口里新的分镜表功能 就可以简单制作动作 52 00:05:13,414 --> 00:05:19,403 我们在父对象建立一个动画组件 然后针对每一个子对象建立影格 53 00:05:19,403 --> 00:05:25,403 移动指标到想要的影格后调整角色部位 就会自动把变量录到影格上 54 00:05:27,313 --> 00:05:35,064 可随时切换分镜表和动画曲线 使得它更容易调整设计 55 00:05:36,730 --> 00:05:41,370 这些动作建立好之后我们可以 帮我们的角色设计控制状态 56 00:05:41,370 --> 00:05:45,277 让我们用程序呼叫角色执行各种动作 57 00:05:45,277 --> 00:05:52,123 因为不是驱动3D骨架,所以取消打勾Root Motion 58 00:05:52,123 --> 00:05:57,287 也可以打勾Animate Physics如果 动画要和物理行为相互作用 59 00:05:57,287 --> 00:06:04,564 为了在场景走动,主角脚上有圆形碰撞体 和一个包覆整个身体的方形碰撞体 60 00:06:04,564 --> 00:06:09,454 这样他可以平顺地行走和跳下场景 跳起来的时候头部也可以判定撞到 61 00:06:09,802 --> 00:06:16,038 为了控制角色动作,我们写了 一个脚本透过2D物理引擎来移动 62 00:06:16,038 --> 00:06:21,427 这代表在游戏里面可以指定主角和敌人 让游戏动态更丰富的物理行为 63 00:06:21,427 --> 00:06:25,814 我们用PlayerControl脚本来判断角色的输入 64 00:06:25,814 --> 00:06:32,000 我们在此指定物理移动速度 同时也把输入的值送到动画控制器 65 00:06:32,000 --> 00:06:40,475 判定播放哪些动画以及 顺畅的播放分镜表上图片的转变 66 00:06:40,475 --> 00:06:44,475 使用动画控制建立图片动态最大的好处是 67 00:06:44,475 --> 00:06:51,278 可以调整动画速度用来搭配物理速度 不需要额外再作任何判定 68 00:07:23,129 --> 00:07:26,358 FixedUpdate函式会检查每一步物理运算 69 00:07:26,358 --> 00:07:32,994 在这里我们第一件要做的事情是 把输入的水平值传给动画的速度参数 70 00:07:33,950 --> 00:07:41,718 在我们的状态设定里 待机状态到跑动需要速度参数大于0.1 71 00:07:41,718 --> 00:07:46,025 当值成立时,动画就会从待机切到跑步 72 00:07:51,857 --> 00:07:58,822 要让角色移动,让它有Rigidbody2D组件 就可以为它加力道移动 73 00:07:59,626 --> 00:08:07,710 同时我们也根据输入的水平值是 大于0或小于0来处理角色面朝的方向 74 00:08:07,710 --> 00:08:14,573 这是因为在Unity里,按住左键会传回-1 而按住右键会传回+1 75 00:08:15,073 --> 00:08:24,566 根据输入值呼叫一个简单的翻转函数 来翻转角色的X轴缩放,让角色面向反方向 76 00:08:26,848 --> 00:08:31,000 为了判定角色是否着地 我们新增了一个Ground图层 77 00:08:31,000 --> 00:08:34,982 并指定给全部可行走的前景物件 78 00:08:43,397 --> 00:08:50,234 然后使用2D里面的Linecast函数 检查Ground图层是否和角色的脚接触 79 00:08:50,234 --> 00:08:56,777 为了让制作更容易,我们建立了 一个空白的对象当作检查地面的标准点 80 00:08:56,777 --> 00:09:03,083 在该对象上增加一个小图示 我们就可以控制角色到地面的距离 81 00:09:03,083 --> 00:09:07,958 就游戏角度来看 角色在地面时只能做跳的动作 82 00:09:08,456 --> 00:09:12,648 更多关于角色控制的信息 可以查看范例脚本里面的说明 83 00:09:12,648 --> 00:09:15,879 影片稍后也会讨论角色的武器 84 00:09:15,879 --> 00:09:19,879 接下来看看相机如何追踪角色 85 00:09:21,291 --> 00:09:27,824 跟3D游戏一样,在2D游戏里 镜头运镜也左右着游戏体验 86 00:09:27,824 --> 00:09:33,625 要呈现经典的2D游戏运镜 我们参考了2D游戏经典大作 87 00:09:33,625 --> 00:09:38,651 任天堂或超任的超级玛莉欧的镜头运作 88 00:09:38,651 --> 00:09:45,119 在超级玛莉欧世界里镜头会水平移动 除了封闭的空间或关卡边缘 89 00:09:45,119 --> 00:09:49,342 在这两类区域里角色小幅移动 镜头不会追踪 90 00:09:49,342 --> 00:09:54,047 一旦角色移出区域 镜头又会开始追踪角色 91 00:09:54,047 --> 00:09:58,205 超级玛莉欧的相机 用特定高度来进行垂直判定 92 00:09:58,205 --> 00:10:06,848 但我们的游戏没有往上的长度 比较像动作平台,所以不需要这类设定 93 00:10:07,210 --> 00:10:12,787 因此我们的相机在垂直判定 采用了和水平一样的方法 94 00:10:18,779 --> 00:10:25,138 请看看主相机里的CameraFollow脚本 了解镜头追踪更完整的写法和批注 95 00:10:26,135 --> 00:10:32,732 游戏中有许多特效 但最重要的是主角杀死外星人的能力 96 00:10:32,732 --> 00:10:36,338 主角会发射一个具有 反作用力动画的火箭筒 97 00:10:36,338 --> 00:10:38,898 这个动画由几个部分组成 98 00:10:38,898 --> 00:10:47,969 首先检查输入,当按下Fire键时 产生一个火箭,播放音效并触发火箭动画播放 99 00:10:47,969 --> 00:10:49,969 让我们进一步分解这些步骤 100 00:10:49,969 --> 00:10:57,677 为了可以播放其他动画(跑步)时同时播放火箭发射 我们在动画控制器建立了Shooting的动画层 101 00:10:57,677 --> 00:11:06,980 将Weight属性设为1,可以 完全覆盖基本层(Base Layer)所有的动作 102 00:11:20,499 --> 00:11:27,351 我们可以从任何状态中用程序 触发Shoot参数发射动画 103 00:11:27,351 --> 00:11:30,543 来看看负责这工作的Gun脚本 104 00:11:32,700 --> 00:11:37,402 你可以看到我们写了驱动事件 触发Shoot为True 105 00:11:37,402 --> 00:11:45,511 触发后会打开,在下一格重置为关 就可以重复使用,对于射击动作最好用 106 00:11:46,011 --> 00:11:50,673 除了设定动画,我们也从脚本中发射火箭 107 00:11:50,673 --> 00:12:00,555 播放音效后根据角色的方向 产生火箭并给它一个X轴的正或负速度 108 00:12:01,276 --> 00:12:05,294 这个Gun脚本被放在主角身上的空物件 109 00:12:05,294 --> 00:12:11,663 像这样将脚本放到一个空对象上 可以轻易的定位火箭发射位置 110 00:12:11,663 --> 00:12:20,010 我们将对象放到火箭筒发射口 然后以他自己的坐标当作发射点 111 00:12:40,248 --> 00:12:46,804 火箭本身有2D刚体 我们给它一个速度让它移动 112 00:12:46,804 --> 00:12:51,096 它也有火焰喷射动画和粒子系统做的烟雾 113 00:12:52,826 --> 00:12:56,482 粒子系统也接受新的Sprite图片 114 00:12:56,482 --> 00:13:04,149 所以可以将烟雾的图片切好后加到材质 并指定到粒子系统的Texture Sheet Animation 115 00:13:04,149 --> 00:13:08,232 就有烟雾特效让粒子系统发射 116 00:13:16,122 --> 00:13:22,935 当火箭命中敌人或环境时 火箭本身会引起爆炸并被摧毁 117 00:13:22,935 --> 00:13:27,731 爆炸是我们制作的爆炸动画对象 118 00:13:27,731 --> 00:13:33,699 排序位置在前景的最后面 119 00:13:36,174 --> 00:13:44,576 要建立这类动画,可以从项目点选图片 然后在属性Sprite Mode选择Multiple 120 00:13:44,576 --> 00:13:49,757 这功能允许我们编辑图片 手动或是自动裁切图片大小 121 00:13:49,757 --> 00:13:52,406 一旦完成裁切后 122 00:13:52,406 --> 00:13:58,765 只需要点击Apply Unity会自动产生图片并作为子对象 123 00:13:59,707 --> 00:14:01,693 这就是火箭制作过程 124 00:14:01,693 --> 00:14:06,533 稍后我们将在影片中讨论 杀死敌人的动画技法 125 00:14:07,102 --> 00:14:12,194 现在先让我们回到主角 看看如何处理血条补血和扣血 126 00:14:12,194 --> 00:14:18,548 血条被定义为一个浮点数(Float) 每次碰到敌人就会呼叫TakeDamage函式 127 00:14:18,548 --> 00:14:25,347 为了避免触发太快造成死亡 我们用repeatDamagePeriod来间隔触发时间 128 00:14:26,524 --> 00:14:31,136 为了让角色显示受伤 并容易从敌人手中逃脱 129 00:14:31,136 --> 00:14:34,847 我们建立了受伤的动作 并在物理上弹飞主角 130 00:14:34,847 --> 00:14:39,540 要做到这点,TakeDamage函式 会阻止角色跳跃 131 00:14:39,540 --> 00:14:42,125 并从主角与敌人之间找到一个向量位置 132 00:14:42,125 --> 00:14:46,125 指定一个物理力量往指定方向击退 133 00:14:46,125 --> 00:14:55,323 hurtForce是一个全局变量,可以随时从接口调整 而不用从脚本里调整 134 00:14:55,323 --> 00:15:02,209 除了击退主角之外,我们同时 也扣掉角色的血量并更新血条 135 00:15:02,209 --> 00:15:09,825 为了呈现扣血,我们把血条的宽度缩减 用一个公式计算让绿色转变到红色 136 00:15:09,825 --> 00:15:14,640 透过当下的血量和总量算出一个百分比 137 00:15:14,640 --> 00:15:21,744 血条是由两个图片组成 一个显示血量,另一个显示外框 138 00:15:21,744 --> 00:15:25,954 这也是在Photoshop里做的 然后输出两个单独的图片 139 00:15:25,954 --> 00:15:34,053 导入图形的时候,设定图形轴心在左边 所以当它按比例减少时,就会往左缩 140 00:15:48,573 --> 00:15:54,573 这两个图片放在一个空对象底下 给予一个简单脚本,让它显示在角色头上 141 00:15:54,573 --> 00:15:58,621 将血条位置设定与角色相同 142 00:15:58,621 --> 00:16:02,621 并加上偏移用的全局变量 好在检视接口进行调整 143 00:16:16,215 --> 00:16:22,629 当主角血量为0时,设定碰撞体的isTrigger = true 主角就会往下跌到水上 144 00:16:22,629 --> 00:16:28,194 同时将主角排序推到UI层上 主角会移到画面最上层 145 00:16:28,194 --> 00:16:31,594 UI层是我们制作的层 是用来表示像UI的前面的对象 146 00:16:31,594 --> 00:16:34,223 当脚色死亡时,我们有两个动画 147 00:16:34,223 --> 00:16:38,631 一个叫Death,会失去帽子和枪 另外一个叫Falling 148 00:16:38,631 --> 00:16:47,239 用Exit Time当作动画的切换条件 一旦Death播完就会切到Falling动画 149 00:16:50,778 --> 00:16:55,000 最后,在播放死亡动画时 为了阻止玩家移动角色或射击 150 00:16:55,000 --> 00:16:58,340 我们会禁用PlayerControl和Gun脚本 151 00:16:58,340 --> 00:17:05,040 由于Die函式是全局可以从任何地方呼叫 例如玩家掉入水中 152 00:17:05,040 --> 00:17:12,463 要在主角接触水面时重置游戏,我们 用一个由触发器和脚本组成的KillTrigger对象 153 00:17:12,463 --> 00:17:17,512 在大多的情况下 Remover脚本移除掉入河中的敌人 154 00:17:17,512 --> 00:17:21,442 并播放一个水花动画和音效 155 00:17:21,442 --> 00:17:24,001 但如果是主角被触发器侦测到时 156 00:17:24,001 --> 00:17:27,092 就会呼叫PlayerHealth脚本里的Die函式 157 00:17:27,092 --> 00:17:34,527 并禁用CameraTracking同时将角色移出屏幕 并呼叫co-routiene函数(停止2秒) 158 00:17:34,527 --> 00:17:36,527 然后重生在出生点 159 00:17:37,079 --> 00:17:39,079 接下来焦点转移到角色生存 160 00:17:39,079 --> 00:17:42,481 来看看它是如何生存 和我们给予它甚么生存工具 161 00:17:42,481 --> 00:17:49,911 游戏中有两种帮助玩家的补给箱 一种箱子是炸弹,另一种可以补血 162 00:17:50,411 --> 00:17:55,695 补给箱由箱子和降落伞两个部分组成 163 00:17:58,046 --> 00:18:03,768 这两个元素放入一个空白对象 我们就可以一起触发动画 164 00:18:03,768 --> 00:18:08,476 我们定位这两个图片 降落伞的轴心位于父对象的中心 165 00:18:09,045 --> 00:18:15,307 这样动画可以左右摇摆 让降落伞是浮在空中的感觉 166 00:18:15,307 --> 00:18:19,307 然后增加一个刚体让它有重力往下掉 167 00:18:19,307 --> 00:18:24,962 箱子增加碰撞体用来探测它的着陆时机 和玩家捡起的时机 168 00:18:24,962 --> 00:18:30,513 着陆之后 播放第二段动画让降落伞消失 169 00:18:30,513 --> 00:18:34,916 跟游戏其他地方一样 动画器控制对象的状态 170 00:18:34,916 --> 00:18:38,916 我们可以看到预设的情况下 它会播放FloatDown动画 171 00:18:38,916 --> 00:18:43,472 然后当Land = True时会切换到着陆状态 172 00:18:43,972 --> 00:18:49,732 在脚本里,我们使用onTriggerEnter函数 透过标记来检测是否碰到地面 173 00:18:49,732 --> 00:18:55,098 我们也将补给箱从父对象中分离 并给它一个刚体 174 00:18:55,098 --> 00:19:00,624 它就可以和环境互动 比如降落在一个斜坡上就会斜停在坡上 175 00:19:00,624 --> 00:19:03,672 接下来看看炸弹 176 00:19:03,672 --> 00:19:08,475 捡起炸弹箱的动作是箱子上的 BombPickup脚本处理的 177 00:19:08,475 --> 00:19:16,739 透过角色身上的LayBombs脚本 增减主角拥有的炸弹数量 178 00:19:17,557 --> 00:19:25,557 LayBombs脚本负责检查是否携带着炸弹 并负责产生并放置炸弹 179 00:19:27,424 --> 00:19:36,147 炸弹设有定时装置,在爆炸之前 透过BombDetonation里的yield倒数计时 180 00:19:36,799 --> 00:19:39,545 爆炸函式执行几个动作 181 00:19:39,545 --> 00:19:43,797 它会重置bombLaid参数 允许产生另外一个炸弹箱 182 00:19:43,797 --> 00:19:49,797 它会通知产生器补充新的炸弹箱 并炸死范围内的敌人 183 00:19:50,518 --> 00:19:53,058 来看看最后一部分怎么运作的 184 00:19:53,058 --> 00:19:57,180 因为炸弹对敌人来说是致命的 不管他们的生命值剩下多少 185 00:19:57,180 --> 00:20:03,470 我们用Physics.OverlapCircleAll方法收集 在爆炸范围内所有标记为敌人的对象 186 00:20:03,470 --> 00:20:06,612 然后为每一个敌人执行循环 187 00:20:06,612 --> 00:20:15,542 设定他们的血量为0 从爆炸地点到敌人算出一个向量并施加外力 188 00:20:16,304 --> 00:20:21,381 一旦循环跑完,就可以播放视觉效果 189 00:20:21,381 --> 00:20:25,907 播放一段音效同时摧毁炸弹 190 00:20:26,875 --> 00:20:29,252 爆炸视觉效果有两部分 191 00:20:29,252 --> 00:20:33,583 主要部份是一个简单的圆形 短暂的出现后摧毁 192 00:20:33,583 --> 00:20:39,583 第二部分是星星状的粒子系统 重复用相同图片呈现火箭爆炸 193 00:20:42,265 --> 00:20:51,735 效率上我们保持粒子系统持续在场景中 需要时我们用程序移动到指定位置播放 194 00:20:52,511 --> 00:20:56,511 这样可以让粒子系统存在内存里 使游戏比较有效率 195 00:20:57,011 --> 00:21:04,668 这么做主要是因为这个范例 同时只会有一个爆炸在场景中 196 00:21:04,668 --> 00:21:07,794 因为玩家只能一次丢一个炸弹 197 00:21:07,794 --> 00:21:14,936 这就是为什么将粒子系统保持在场景中 并重复播放的原因,比起建立后移除有效率 198 00:21:15,714 --> 00:21:21,618 但如果是火箭爆炸,因为可以重复发射 因此需要建立后移除 199 00:21:22,118 --> 00:21:26,118 让我们看看主角杀死敌人 怎么计算分数 200 00:21:26,618 --> 00:21:35,528 这分为两个部分,动画显示获得100分 以及增加UI的分数计算 201 00:21:35,528 --> 00:21:40,193 分数动画由1和0两个数字组成 202 00:21:40,193 --> 00:21:42,872 将它们放到场景中的空白对象 203 00:21:42,872 --> 00:21:49,186 给予一个简单的得分动画 并用程序让它们在动画完成后消失 204 00:21:49,186 --> 00:21:55,186 我们放置摧毁脚本在动画事件尾端 205 00:22:06,142 --> 00:22:13,703 ScoreUI单纯是个GUI文字组件 带有管理玩家分数的脚本 206 00:22:13,703 --> 00:22:20,980 Score是全局变量,代表随时可以 检查当敌人被杀死时增加100分 207 00:22:20,980 --> 00:22:24,980 说到敌人,让我们仔细看看他们 208 00:22:25,480 --> 00:22:28,260 在我们的游戏里,有两种类型外星敌人 209 00:22:28,260 --> 00:22:30,854 一种是绿皮肤的鼻涕虫 210 00:22:30,854 --> 00:22:34,563 另一种是会搭着飞船保护自己 的智能型外星怪物 211 00:22:34,563 --> 00:22:36,563 这些角色会共享一种脚本 212 00:22:36,563 --> 00:22:38,563 因为他们行为相似 213 00:22:38,563 --> 00:22:45,765 我们可以检视它们的全局变量 并设定不同的移动速度和生命 214 00:22:46,638 --> 00:22:49,093 每个敌人都有自己的移动动画 215 00:22:49,093 --> 00:22:54,444 鼻涕虫有一个可以活动的尾巴 飞船内的敌人会前后摇摆移动 216 00:22:55,994 --> 00:23:01,994 对鼻涕虫来说,我们汇入图形 并把尾巴切为独立图形 217 00:23:01,994 --> 00:23:07,475 这样我们就可以单独缩放它 不会影响到整个图片 218 00:23:07,475 --> 00:23:14,124 轴心设定到右边 我们可以漂亮的伸展收缩尾巴 219 00:23:16,475 --> 00:23:19,918 上下移动眼睑 220 00:23:19,918 --> 00:23:24,859 然后使用Z轴来排序 眼睛就会在眼睑底下了 221 00:23:24,859 --> 00:23:26,859 就可以制作眨眼动画 222 00:23:28,865 --> 00:23:34,046 第二个外星人的动画要简单的多 我们只需要前后转动它 223 00:23:35,798 --> 00:23:41,229 关于这些敌人的移动技术 我们透过改变刚体的速率来移动它们 224 00:23:41,229 --> 00:23:47,826 当它们遇到一个墙壁这样的障碍物时 会呼叫Physics.OverlapPoint函式来检测 225 00:23:47,826 --> 00:23:55,850 检查是否有重迭到像是 墙壁和两边的塔被标记的障碍物 226 00:23:55,850 --> 00:23:59,161 当函式侦测到时,就会呼叫Flip函式 227 00:23:59,161 --> 00:24:04,070 函式会翻转敌人的X轴缩放 让它转到不同方向 228 00:24:04,070 --> 00:24:11,036 要杀死敌人,当敌人和火箭相撞时 在撞击时会呼叫Hurt函式 229 00:24:14,962 --> 00:24:19,213 这个函式我们从敌人身上扣1点血 230 00:24:19,213 --> 00:24:23,213 并持续呼叫函式保持敌人持续扣血 231 00:24:23,213 --> 00:24:27,124 如果血条降到0,就会呼叫死亡函式 232 00:24:31,229 --> 00:24:33,916 当他们死后,就会执行一些函式 233 00:24:33,916 --> 00:24:39,916 会先停用所有的图形渲染 因为2D角色大多都有动画 234 00:24:40,941 --> 00:24:46,941 这是为了把动画对象换成单张死亡图片 235 00:24:47,745 --> 00:24:54,165 我们在图形渲染器将图片改为deadEnemy 236 00:24:54,165 --> 00:24:58,165 然后我们帮Score全局变量增加100 237 00:24:58,165 --> 00:25:03,534 然后增加扭转让他们死亡时扭曲 238 00:25:04,448 --> 00:25:08,881 因此我们要让这些敌人死后 掉入环境的河中 239 00:25:08,881 --> 00:25:13,589 我们找到对象上所有碰撞体 并设定IsTrigger = True 240 00:25:13,589 --> 00:25:17,417 这样他们就会穿过所有环境往下掉 241 00:25:17,417 --> 00:25:25,470 然后播放死亡音效之后展示一个分数动画 242 00:25:27,876 --> 00:25:29,876 要将已死亡的敌人从场景中移除 243 00:25:29,876 --> 00:25:31,876 我们使用killTregger对象 244 00:25:31,876 --> 00:25:34,762 和前面所说的一样 245 00:25:34,762 --> 00:25:36,762 当任何角色接触它时 246 00:25:36,762 --> 00:25:39,950 将会引起一个水花动画,并移除该对象 247 00:25:39,950 --> 00:25:45,950 它们撞击水面并播放 一段附在水花动画的音效 248 00:25:45,950 --> 00:25:50,634 所以当我们产生水花动画时 同时也听到音效 249 00:25:55,153 --> 00:25:59,153 要完成游戏关卡 我们也用一些移动背景来装饰 250 00:25:59,153 --> 00:26:02,302 为了让游戏环境更显动态 251 00:26:02,302 --> 00:26:07,125 我们添加了一些飞翔的天鹅 以及沿着河岸开的公交车和出租车 252 00:26:07,125 --> 00:26:16,051 首先是天鹅,它是在Photoshop里面画好后 用Multiple Sprite导入图片 253 00:26:16,051 --> 00:26:20,800 Unity会自动裁切天鹅的每个图片 254 00:26:20,800 --> 00:26:24,579 分为不同的图导入 并把原图当作父对象放在底下 255 00:26:24,579 --> 00:26:32,346 因为这是个动画组合,可以将所有的图片 一起拖到场景中,让Unity帮我们生成动画 256 00:26:32,346 --> 00:26:37,759 瞧,天鹅的动画已经准备好了 257 00:26:37,759 --> 00:26:43,369 然后给天鹅一个刚体 让我们可以控制速度飞过屏幕 258 00:26:43,369 --> 00:26:47,334 和公交车和出租车一样,天鹅已被存为预制对象 259 00:26:49,257 --> 00:26:55,257 公交车和出租车作法只需要 在汇入图形时分开车身和车轮 260 00:26:55,257 --> 00:26:58,392 并制作一个简单的摆动动画 261 00:26:58,392 --> 00:27:04,376 相同指定2D刚体到车子上 就能够驱动他们在屏幕上跑 262 00:27:07,279 --> 00:27:14,271 公交车、出租车和天鹅这三个物件 我们用一个重复执行的脚本来制造它们 263 00:27:14,271 --> 00:27:21,838 BackgroundPropsSpawner脚本 同时也处理出生位置,出生频率并给予速度 264 00:27:21,838 --> 00:27:30,521 代表我们可以用这个脚本应用在三种对象 默认出生点和属性 265 00:27:30,521 --> 00:27:33,854 要了解更多的细节,可以查看脚本中的说明 266 00:27:33,854 --> 00:27:40,409 最后,要了解更多的背景动态 我们使用了移动的云朵、流动的河水和烟雾 267 00:27:41,323 --> 00:27:50,004 我们在空白对象下放两个背景图片 并使这些图片缓慢飞过屏幕 268 00:27:50,004 --> 00:27:54,652 因为这是个无限循环 所以动画永远不会停 269 00:27:59,185 --> 00:28:01,031 这就是我们游戏的制作过程 270 00:28:01,031 --> 00:28:05,516 我们希望这个教学让你 对如何用Unity开发2D游戏有一定了解 271 00:28:05,516 --> 00:28:08,971 未来我们也会制作更简单的教学 272 00:28:08,971 --> 00:28:14,959 也期待你们对于Unity4.3的反应 迫不及待想看看你们的2D产品 273 00:28:14,959 --> 00:28:16,487 谢谢观看