Unity 脚本入门教程

您所在的位置:网站首页 unity自带的脚本编辑器叫什么软件 Unity 脚本入门教程

Unity 脚本入门教程

2024-06-30 22:43| 来源: 网络整理| 查看: 265

原文:Introduction to Unity Scripting 作者:Georgi Ivanov 译者:kmyhy

Unity 的许多功能都要通过它的富脚本语言 C# 来体现。你可以用它来处理用户输入,操作场景中的对象,碰撞检测,自动生成新的 GameObject 和在场景中发射定向光以处理游戏逻辑。听起来很可怕,但 Unity 提供了有良好文档的 API,使得这些任务的完成轻而易举——哪怕你是一个新手!

在本教程中,你将创建一个 Top down shooter 游戏,用 Unity 脚本处理敌人的生成、玩家控制、开火以及其它游戏中的重要方面。

注意:本教程假设你拥有一定的 C# 或类似编程语言经验,理解 Unity 的界面和工作方式。如果你忘记了这些内容,请阅读我们的 Unity 入门教程。

本教程针对 Unity 5.3 以上。你可以从这里下载 Unity 的最新版。

Unity 同时支持 UnityScript 和 Boo,但大部分程序员都喜欢使用 C#。C# 被数百万开发者用于开发 app、web 和游戏开发,有海量的资料和教程能够帮你学习它。

开始

下载开始项目 BlockBuster,解压缩,用 Unity 打开文件夹。

打开后是这个样子:

看一下场景视图。有一个小的竞技场,这是游戏的主战场,以及一个相机和一盏灯。如果你的布局和上图不同,请点击右上角的下拉框并选择 2 by 3。

主角都没有叫什么游戏?你的第一个任务就是创建一个代表玩家的 GameObject。

创建玩家角色

在结构视图中,点解 Create 按钮,选择 3D Object\Sphere。将球体放到 (X:0, Y:0.5, Z:0) 然后命名为 Player。

Unity 用全组件式系统来构建 GameObject。也就是说所有的 GameObject 都是由组件构成,这些组件会给游戏对象赋予行为和特性。这是几个 Unity 的内置组件:

Transforme: 每个 GameObject 都有这个组件。它保存了 GameObject 的位置、角度和比例。Box Collider:一种立方形的碰撞体,用于检测碰撞。Mesh Filter:用于显示 3D 模型的网格数据。

Player 游戏对象需要和场景中的其它对象发生碰撞反应。要实现这一点,请在结构视图中选择 Player,然后点击检视器窗口中的 Add Component 按钮。在弹出菜单中选择 Physics > Rigidbody,这就为 Player 添加了一个刚体组件,这样它就能够使用 Unity 的物理引擎了。

修改这个刚性体的属性为:Drag 设为 1,Angular Drag 为 0,勾选 Freeze Position 旁边的 Y。

这将保证玩家角色不会被上下移动,同时在转动时不添加阻尼系数。

编写玩家移动的脚本

玩家角色创建好之后,准备创建接收键盘输入以及移动玩家的脚本。

在项目窗口中,点击 Create Button\Folder。命名文件夹为 Scripts,然后在下面创建一个 Player 子文件夹。

在 Player 文件夹中,点击 Create 按钮,选择 C# Script。新脚本命名为 PlayerMovement。这个样子:

注意:创建这些文件夹有利于将文件安装各自的职能进行组织,避免混乱。你将为 Player 创建多个脚本,因此单独用一个文件夹会更好。

双击 PlayerMovement.cs 脚本。这会用你喜欢的代码编辑器打开这个脚本。Unity 内置了 MonoDevelop,它支持所有平台,在安装器运行时,Windows 用户可以安装 Visual Studio 来取代它。

本教程假设你使用 MonoDevelop,但 Visual Studo 用户也不会有任何问题。

当代码编辑器打开,你会看到:

这是 Unity 在新脚本中生成的默认的类。它继承了 MonoBehaviour 基类,这样脚本才能够在游戏中运行,同时还有一些特殊的方法对特定事件作出响应。如果你是一个 iOS 开发者,这个类就好比 UIViewCotnroller。Unity 会在运行脚本时以特定顺序调用多个方法。最常见的几个方法包括:

Start(): 这个方法在脚本第一次 update 时调用。Update(): 当游戏正在运行,同时脚本是可用的,这个方法会在每帧刷新时调用。OnDestroy(): 在这个脚本所附着的 GameObject 被销毁之前调用。OnCollisionEnter(): 当这个脚本所附着的碰撞体或刚体和其它碰撞体或刚体发生接触时调用。

完整的事件列表,请参考 Unity 的 MonoBehaviours 文档。

在 Start() 方法前,添加两行代码:

public float acceleration; public float maxSpeed;

脚本看起来是这个样子:

这是公共变量声明,这意味着这两个变量能够在检视器中看到并修改,而无需在脚本和编辑器中来回切换。

acceleration 表示玩家的速度随着时间递增。maxSpeed 则表示速度的上限。

在它们后面声明这几个变量:

private Rigidbody rigidBody; private KeyCode[] inputKeys; private Vector3[] directionsForKeys;

私有变量无法用检视器来设置,它的初始化由开发者在某个时机负责。

rigidBody 用于保存一个对刚体组件的引用,即附着在 Player GameObject 上的刚体组件。

inputKeys 是一个键盘码的数组,用于检查输入。

directionsForKeys 用于保存一个 Vector3 变量数组,这些变量表示方向数据。

将 Start() 方法修改为:

void Start () { inputKeys = new KeyCode[] { KeyCode.W, KeyCode.A, KeyCode.S, KeyCode.D }; directionsForKeys = new Vector3[] { Vector3.forward, Vector3.left, Vector3.back, Vector3.right }; rigidBody = GetComponent(); }

这段代码将按键对应到方向,比如 W 是向前。最后一行获得了一个对所附着的刚体组件的引用,将它保存到 rigidBody 变量以便使用。

要真正移动玩家的角色,还需要处理键盘输入。

将 Update() 修改为 FixedUpdate() 并加入以下代码:

// 1 void FixedUpdate () { for (int i = 0; i < inputKeys.Length; i++){ var key = inputKeys[i]; // 2 if(Input.GetKey(key)) { // 3 Vector3 movement = directionsForKeys[i] * acceleration * Time.deltaTime; } } }

有几个地方需要注意一下:

FixedUpdate() 是不依赖于帧率的,它和刚体一起使用。和以尽量快的速度运行不同,这个方法会以固定的间隔执行。这个循环检测哪个按键被按下。获取被按下的键所表示的方向,乘以加速度和上一帧耗费的秒数。最终算出一个方向向量(在 x,y 和 z 轴上的速度),你就可以用它来移动 Player 对象了。

如果你是编程新手,你可能奇怪为什么要乘以 Time.detalTime。游戏是在帧率(帧/秒)下运行的,帧率是取决于硬件和它运行压力,这样在性能好的机器上帧率快,而在性能差的机器上帧率慢,从而导致不可预知的结果。通常的办法是,当需要按每帧执行一个动作时,都乘上 Time.deltaTime。

在 FixedUpdate() 方法后添加:

void movePlayer(Vector3 movement) { if(rigidBody.velocity.magnitude * acceleration > maxSpeed) { rigidBody.AddForce(movement * -1); } else { rigidBody.AddForce(movement); } }

这个方法向刚体施加一个力,驱使它移动。乳沟当前速度超过 maxSpeed,这个力会转成反方向,让玩家减速,将速度有效地限制在最大速度下。

在 FixedUpdate() 方法中,在 if 语句右括号结束之前,添加:

movePlayer(movement);

棒极了!保存脚本,回到 Unity 编辑器。在项目窗口,将 PlayerMovement 脚本拖到结构视图的 Player 上。

将脚本添加到一个 GameObject 会导致创建一个组件实例,也就是说所有的代码会被所附着的 GameObject 所执行。

用检视器将 Acceleration 设置为 625,Max Speed 设置为 4375:

运行场景,用 WASD 键移动玩家角色:

太好了,我们只用了几行代码!:]

但是,有一个很明显的问题——玩家会飞快地跑到视线以外,让我们很难去和敌人战斗啊。

编写相机脚本

在脚本编辑器中,新建脚本名为 CameraRig,然后将它添加到 Main Camera。还需要介绍详细步骤吗?你可以参考下面的答案。

参考步骤

选择 Scripts 文件夹,点击项目浏览器中的 Create 按钮,选择 C# 脚本。取名为 CameraRig。将新脚本拖到 Main Camera 对象:

然后,在新的 CameraRig 类的 Start() 方法之上中添加如下变量:

public float moveSpeed; public GameObject target; private Transform rigTransform;

你可能想到了,moveSpeed 是相机跟随目标——任何场景内部游戏对象——进行移动的速度。

在 Start() 方法中,添加:

rigTransform = this.transform.parent;

这句引用了父对象 Camera 在场景树中的 transform 组件。每个在场景中的对象都会有一个 Transform 组件,它描述了对象的位置、角度和比例。

在同一脚本中,添加方法:

void FixedUpdate () { if(target == null){ return; } rigTransform.position = Vector3.Lerp(rigTransform.position, target.transform.position, Time.deltaTime * moveSpeed); }

CameraRig 的移动代码比 PlayerMovement 要简单。这是因为你不需要刚体,在 rigTransform 和 target 的位置之间做插值运算即可。

Vector3.Lerp() 以两个点和一个0-1 之间的小数做参数,这个小数表示两个端点之间的一个位置。左端点为 0,右端点为 1。0.5 则返回两点之间的终点。

以渐慢方式让 rigTransform 靠近 target 的位置。也就是说——相机会跟随玩家角色。

回到 Unity。在结构视图选中 Main Camera。在检视器中,设置 Move Speed 为 8 ,Target 为 Player:

运行游戏,在场景中四处移动;相机将平滑跟随 target。

创建敌人

没有对手的射击游戏玩起来固然轻松,但也太无聊了 :] 通过顶部 GameObject\3D Object\Cube 菜单创建一个方块作为敌人。将方块命名为 Enemy 并添加一个 Rigidbody 组件。

在检视器中,首先将方块的 Transform 设为 (0, 0.5,4)。在 Rigidbody 组件的 Constraints栏,勾上 Freeze Position 旁边的 Y。

太好了——现在让敌人以一种吓人的方式移动吧。在 Scripts 目录下新建脚本 Enemy。这个步骤你应该很熟悉了,如果忘记了,请参考前面的描述过的步骤。

然后,在类中声明变量:

public float moveSpeed; public int health; public int damage; public Transform targetTransform;

这些变量的作用并不难猜。moveSpeed 先前在相机中也用到过,这里是同样的作用。health 和 damage 用于决定敌人什么时候死,以及它们对玩家造成的伤害。targetTransform 引用了玩家的 transform。

对于 Player 来说,你需要一个类描述玩家的所有属性,这一切恰好是敌人想摧毁的。

在项目浏览器中,选中 Player 文件夹并新建脚本 Player,这个脚本用于对碰撞进行处理,并保存玩家的生命值。双击脚本,打开它。

添加一个公共变量用于保存玩家的生命值:

public int health = 3;

这里为 health 设置了一个默认值,但你还可以在检视器中修改这个值。

要处理碰撞,添加如下方法:

void collidedWithEnemy(Enemy enemy) { // Enemy attack code if(health


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3