您现在的位置是:首页 >学无止境 >Unity 新建你的第一个游戏,以及如何按WASD控制角色运动 (Unity Demo2D)网站首页学无止境
Unity 新建你的第一个游戏,以及如何按WASD控制角色运动 (Unity Demo2D)
初始化项目
当你打开 Unity Hub,初始化一个 2D 项目,进入了 Unity 编辑器,你会发现在 左侧 :
- 一个叫 SampleScene (或者其他) 的场景
- 场景下有一个 Main Camera,主相机
这就是一个新建的 2D 项目自带的内容。
新建角色物体
在 Main Camera 同级目录新建:2D Object - Sprites - Capsule,这里 Capsule 是精灵的种类,我们在后面都是可以自行更改的,Capsule 是胶囊形状的物体,在碰撞处理时会更润一点。
这里我给我的 精灵(Sprites) 命名为 PlayerObject,随后你会发现 右侧,有一大堆这个精灵的属性,比如说位置速度旋转角之类的:
- Transform 每个游戏对象都包含一个这个组件,控制其位置、移动
- Sprite Renderer 给精灵赋予渲染 2D 图片的能力
试着修改 Position、Rotation、Scale 看看效果!
游戏资源管理
试着导入资源
低头看看下面的栏里,这里是你的游戏资源,包括脚本,图片都放这里了:
- Assets 当前游戏使用的资源
- Packages 通用的资源,可能别的游戏也可以用的 ( 这里可能存在误导性,请读者自行理解
所以你只需要把图片什么的往里面拖进去就是导入资源了,非常简单。
试着管理资源
刚刚创建出来的精灵长得确实像一个胶囊,如果不是特殊情况,玩家不应该是长那样的。
在这里我在 Assets 中新建了几个文件夹,只是一个 Demo 大概了解意思就行,不喜勿喷 (但文件管理层级确实是需要上心设计的,否则到后面会变得混乱,极其不方便使用,极其影响效率)
可以看到这里我导入了一个图片,叫 character_0001:
试着使用资源
接下来我们直接让胶囊变成这个小怪物的样子:
也非常简单,你把你的资源里面的图片,拖到 Sprite Renderer - Sprite 里面就好了,没有多余的操作:
脚本是啥
如果你写过一些简单的游戏,你会写过一些脚本,比如说 碰撞检测,角色移动,在 Unity 中这些脚本作为 独立的 .cs 文件 放置在资源文件夹中,当你需要这个功能时,就可以把脚本挂在某个物体上,让他实现一些能力。
我们拿 碰撞检测 举例,在简单的游戏中,一个脚本代码文件就可以控制所有的游戏内容。每一帧检测:
- 是否有碰撞到怪物
- 碰撞到了是否结束游戏
- 碰撞到星星给本次游戏加分
- 渲染玩家,怪物,星星
- 渲染屏幕上面的分数
等等诸如此类的内容。
但在 Unity 这样的较大的游戏客户端开发中,我们将会需要把这些内容完全解耦,即:
- 每个物体都拥有一个 碰撞系统 脚本
- 游戏的结束和开始单独由 游戏流程管理器 来实现,这个管理器可以是个单独的物体,也可以 写成一个脚本,挂载在玩家对象上
- 加分系统单独写成一个 加分系统管理器,玩家拥有
<调用加分系统中的功能>
能力的脚本,当玩家的碰撞系统检测到星星时,就调用加分系统中的 加分 和 销毁星星 - 星星也有 碰撞系统,检测到 被碰撞 了就直接紫砂
如果你不这样写,那某个文件代码行数怕是要上万了。另一方面,我们也能从这种实现方式中窥见游戏性实现的可能,以便游戏的策划设计优化等等涵盖前中后期的工作。
新建脚本
也很简单,在这个地方右键然后 Create - C# Script 就可以了~
编辑脚本
我们可以使用 Visual Studio 或者 VSCode 进行 C# 脚本的编辑,多数人使用 Visual Studio,工具链更完善。
如果您对如何使用更轻量的 VSCode 感兴趣,可以参考我的另一篇笔记:如何使用 VSCode 编辑 Unity + C# 脚本
打开你刚刚创建的脚本 (如果你使用VS,文本内容也是一样的,这者没有实质上的区别):
- Start() 当脚本被初始化完毕时执行的
- Update() 每一帧都会执行的
行为逻辑
由于我们使用的是 2D 模板,此时我们的 PlayerObject 也没有挂载重力系统,碰撞体系统,那么想让 PlayerObject 移动无非是修改玩家的位置 (x, y, z)
参考一下大多数游戏的流程:按下A,玩家往左走
所以有可能初学者会认为:写一个函数来检测按下A,当玩家按下A的时候,玩家开始往左走
就目前我们仅有2个函数块 Start 和 Update,不涉及线程池等等操作的话,显然这样是不容易实现的,一个可能的正确的方式是:每一帧都检测玩家是否按下了某个按键,如果按着就移动一点点
按键检测
我们会需要一个 Unity 提供给我们的静态类 (Static Class),或者叫做工具类 (Utils),这个类是 Input,专门用来读取按键输入,这里需要您具有面向对象编程经验:
键入 Input,通过智能提示可以发现这个静态类中提供的实现:
获取按键
通过这个函数会返回某个按键是否处于按下状态 (bool)
Input.GetKey(KeyCode.A)
那么我们只需要这样就可以不停获取 A 的按键信息了
void Update() {
bool isKeyDown = Input.GetKey(KeyCode.A);
}
移动位置
这里我们需要用到 PlayerObject 对象自带的组件 transform,这样调用来实现对象的 移动:
- Time.deltaTime 是这一帧渲染所经历的时间,这样在不同游戏帧数下,对象的移动速度才会一致(参考 Terraria 的跳帧算法)
- Translate() 的三个参数分别是 x, y, z,你也可以输入一个 Vector 或者别的,详见 Translate 的函数原型
transform.Translate(1.0f * Time.deltaTime, 0, 0);
★ 最终代码 (有基础请直接跳到这)
这就是最终实现功能的代码: