You are on page 1of 57

不用填写

Unity FUNDAMENTAL DAY02


内容

09:00 ~ 09:15 作业讲解和回顾

09:15 ~ 10:00 自定义组件 _ 脚本


上午
10:10 ~ 11:00
脚本生命周期
11:10 ~ 12:00
14:00 ~ 15:10
15:20 ~ 16:30 访问游戏对象
下午
16:40 ~ 17:50

17:50 ~ 18:00 总结和答疑


自定义组件 _ 脚

脚本介绍

脚本语言

创建脚本

脚本编译工具
自定义组件 _ 脚
Unity 脚本 脚本绑定到游戏对象

Unity 脚本
脚本介绍

• 在前面内容中,我们介绍了场景、游戏对象、组件这三
者之前的关系。组件,实际描述的就是“功能”,使用
系统内置的组件(如: Transform 、 Mesh 、)虽然可
知 以满足为指定游戏对象添加功能的操作,但远远不够。


实际上我们最简单的游戏也需要处理响应用户的作操作、
解 游戏场景中的事件触发、游戏对象的创建和销毁等,内
置组件已不能实现。而脚本的出现,就帮助我们解决了
这个问题。
• 脚本,其实就是组件,只不过是一种特殊的自定义组件,
又叫自定义脚本。
脚本介绍(续 1 )

• 什么是脚本?
在 Unity 中,脚本可以理解为附加在游戏对象上的用
于于定义游戏对象行为的指令代码,脚本与组件的用法
知 相同,必须绑定在游戏上才能开始它的生命周期。



脚本介绍(续 2 )

• Unity 中所有脚本都是继承自 MonoBehaviour 类,它


定义了基本的脚本行为(生命周期方法),这些方法完
整的描述了游戏对象被加载到被销毁的整个过程。
知 • 除此之外, MonoBehaviour 还定义了对各种特定事件

讲 (例如模型碰撞、鼠标移动等)的响应方法,这些方法

均以 On 作为开头。
脚本语言

• Unity 的脚本语言是基于 Mono 的 .NET 平台上运行,


可以使用 .NET 库。 Unity 5.0 取消对 Boo 语言的支持
将只支持两种语言: JavaScript 和 C# ,并且加大对
知 C# 语言的支持力度,用户可以使用其中任何一种或同时


使用两种语言来进行脚本的开发,并且脚本之间可以相
解 互访问和进行函数调用,这也方便了使用不同的编辑语
言的开发者进行协同开发。
• 这两种脚本语言的运行效率是一样的,它们都会被编译
成 Unity 内置中间代码,因此运行速度也很快。
脚本语言(续 1 )

• JavaScript 脚本语言和 C# 脚本语言区别?


JavaScript 相对来说语法比较简单,入门容易, Unity
官方示例中也大量使用了 JavaScript 作为脚本语言。而
知 C# 对于有 C/C++ 基础的开发者来说比较容易, C# 本

讲 身有很强大的语言特性,总体而言比 JavaScript 更适合

进行深入开发。另外,目前市场上大多数的 Unity 第三
方插件都是使用 C# 开发的,许多商业项目基本也都是使
用 C# 开发。
• 综上所述, C# 和 JavaScript 使用人群都很多,资料
也较为丰富,开发都可根据自身情况来选择适合的语言
进行开发。
创建脚本

• 创建脚本
注:以下将通过创建 Hello World 来开始 Unity 编程之
旅。



• 在 Unity 中有两种创建脚本的方法,如下:

I. 依次选择菜单栏中的 Assets->Create->C# Script 命
令, 也可以根据需要选择 JavaScript ,如下图所
示:
创建脚本(续 1 )

II. Project 视图灰色区域右击,在弹出的快捷菜单中选择


Create->C# Script (或 JavaScript )来创建脚本,如





创建脚本(续 2 )

III.Project 视图灰色区域右击,在弹出的快捷菜单中选择
Create->C# Script (或 JavaScript )来创建脚本,如





创建脚本(续 3 )

• 创建成功后,就会在 Project 视图灰色区域部分出现刚刚


创建的名为 Hello World.cs 的脚本文件




• 注:选中 Hierarchy 面板中的游戏对象后,缓慢的按两


下鼠标左键,这时游戏对象的名字处于可编辑状态,直
接输入新名字,即可实现对脚本文件重命名的操作。
脚本编译工具

• 在 Project 视图区域双击创建的脚本文件
HelloWorld.cs ,默认情况下 Unity 会自动遍历
Mono 脚本编辑器来编辑脚本,如下图所示:




脚本编译工具(续 1 )

• 当然, Unity 也支持使用其它的编辑器来编辑脚本,例


如: Visual Studio 。 Unity 编辑器中, Edit -
>Preferences ,在弹出的对话框中单击左侧 Extenal
知 Tool 命令,然后在 External Script Editor 下拉列表中选


择 VS 作为 Unity 默认的编辑器,如下图:

脚本编译工具(续 2 )

• 如果在上面点开的下拉列表中没有 Visual Studio( 前提


是电脑上已经安装过 VS ) ,那么应选择 Browse ,然
后浏览找到 VS 的安装目录,在安装目录下
知 选 "devenv.exe" 的文件即可。如下图:


• 说明: VS 安装目录默认在:
脚本编译工具(续 5 )

• 修改之后,再次打开 Hello World.cs ,会在 VS 中显示


出 Hello World.cs 中的代码,如下:


识 注: class 后面跟的类
讲 • 名一定要和创建脚本

时脚本的名字保持一
致,否则为游戏对象
设置此脚本时,设置
不了。
脚本绑定到游戏对象

• 脚本创建完成,如何将脚本绑定到游戏对象上呢?
Unity 提供了多种方式将绑定绑定到指定的对象上的方
式:

识  将脚本文件直接拖动到 Hierarchy 面板的游戏对象上;

解  单击操作的游戏对象,此时 Inspector 面板中显示该对
象的一系列组件,将脚本文件直接拖动到 Inspector 面
板的靠下部分( Add Compont 按钮下面任何位置都
可);
 单击选择操作的游戏对象,然后选择 Inspector 区域
的 "Add Component" 按钮,最底部有一个 Add
Scripts ,这样可在创建脚本时便自动将脚本绑定到操作
脚本绑定到游戏对象(续 1 )

• 注意:
绑定脚本时要注意,脚本文件的名字一定要和脚本打开
class 后面的类名保持一致,否则会导致脚本不能绑定到
知 游戏对象上,并给出错误提示,如下:


脚本文件:
类名为: TestScript
Test.cs
脚本生命周期

脚本生命周期 脚本生命周期 脚本生命周期


脚本生命周期
脚本生命周期

• Unity 中有些特定的方法,这些特定的方法在一定条件下
会被自动调用,称为必然事件 ( Certain Events ) 。
• 在 Unity 中创建的每个脚本文件,默认都包含两个方法:
知 Start() 和 Update() ,这俩方法是最常用的两个事件,所

讲 以新建脚本时会自动创建,除此之外还有其它必然事件。

• 这些必然事件描述了一个脚本从最初的创建到最后被销
毁的完整流程,所以这些必然事件也被称为 Unity 脚本
的生命周期方法。
脚本生命周期(续 1 )

• Unity 生命周期中涉及到的常用方法:
 Awake ():
 OnEnable (): 初始化模块
知  Start ():

讲  FixedUpdate ():

 Update (): 更新模块
 LateUpdate ():
 OnGUI ():
 OnDisable ():
 OnDestory (): 销毁模块
脚本生命周期(续 2 )

• 第一阶段:初始化模块。与初始化相关的生命周期方法:

Awake()
知 OnEnable()


Start()

脚本生命周期(续 3 )

• 初始化模块: Awake()
以下针对 Awake() 方法四个方面介绍(方法完整定义、
方法何时调用、方法作用、被调用次数)
知  Awake() 的完整形式: private void Awake() {......}

讲  Awake() 是整个生命周期中最先执行的方法,当脚本实

例被加载时会自动调用这个方法。
 该方法主要用于在游戏开始之前初始化对象或游戏状态,
如:使用 "GameObject.FindWithTag()" 查询游戏对象。
 Awake() 方法在整个生命周期内只执行一次;
脚本生命周期(续 4 )

• 比如,在 Awake() 方法中通过标签名查找指定游戏对象:





脚本生命周期(续 5 )

• 初始化模块: OnEnable()
以下针对 OnEnable() 四个方面介绍(方法完整定义形式、
方法何时调用、方法作用、被调用次数)
知  OnEnable() 完整形式: private void OnEnable()

讲 {......}

 执行完 Awake() 方法后,如果当前脚本可用或可激活,
按正常执行顺序则会执行 OnEnable() 方法。
 通常在这个地方将当前脚本禁用 :this.enable=false ,若
执行此操作则会直接跳到 OnDisable() 方法执行一次,
其它生命周期方法都不会再执行。
 OnEnable() 方法在整个生命周期内执行的次数不确定。
脚本生命周期(续 6 )

• 比如,下面代码简单的介绍了 OnEnable() 方法的使用:





脚本生命周期(续 7 )

• 初始化模块: Start()
以下针对 Start() 四个方面介绍(方法完整定义形式、
方法何时调用、方法作用、被调用次数)
知  Start() 的完整形式: private void Start() {......}

讲  执行完 OnEnable() 方法之后,在第一次执行 Update()

方法之前, Start() 会进行一次判断:若之前没有执行过
该方法,则会执行;若之前已执行过,则不会再执行。
 该方法主要用于对变量等进行初始化或赋值的相关操作。
可将一些需要依赖 Awake 的变量放在 Start() 里面初始
化。
 Start() 方法在整个生命周期中只执行一次
脚本生命周期(续 8 )

• 比如说:游戏对象 A 的初始化代码需要依赖对象 B 已被
初始化的情况下,此时 B 的初始化应该在 Awake 中完成,
而 A 应该在 Start 中完成。




脚本生命周期(续 9 )

• 比如,下面代码实现在 Start() 方法中为变量赋值的操作:





脚本生命周期(续 10 )

• 第二阶段:更新模块,与生命周期对应的三个方法:

FixedUpdate() 、 Update() 、 LateUpdate()


知  这三个方法是何时被调用的呢?

讲 游戏画面更新时,这三个方法会被调用,并且会被循环

被调用。需要特别强调的是: FixedUpdate() 方法经常
会比 Update() 方法更频繁的被调用。
脚本生命周期(续 11 )

• 更新模块
 Update() 和 FixedUpdate() 在更新时有什么区别吗?
1. 不同点一:调用时间上
知 Update() 方法会在每次渲染新的一帧时被自动调用,而

讲 FixedUpdate() 会在每个固定时间点被调用。也就是说:

Update() 方法的更新频率与硬件设备性能和被渲染的物
体有关,有时快有时慢,帧率会发生变化。当 Update()
被调用时,每帧的时间间隔也自然会发生变化。简单来
讲,硬件设施的好坏会影响 Update() 的更新速率,但
是 FixedUpdate() 则不受帧率变化的影响,它是以固定
时间被调用,从而实现更新操作。
脚本生命周期(续 12 )

2. 不同点二:负责更新的内容上
一般, FixedUpdate() 适合做物理状态的更新,如:
Unity 中的 Rigidbody 是一个操作重力的刚体组件,
知 如果为某游戏对象添加了这个 Rigidbody 组件时,那


么与该组件相关的代码处理要放在 FixedUpdate() 中
解 完成;而 Update() 方法,比较适合完成一般的逻辑更
新或界面数据的更新操作。
脚本生命周期(续 13 )

• 更新模块: LateUpdate()
以下针对 LateUpdate() 四个方面介绍(方法完整定义
形式、方法何时调用、方法作用、被调用次数)
知  LateUpdate() 形式: private void LateUpdate()

讲 {......}

 该方法会在 Update() 之后执行,也就是说,执行完本次
更并且在开始执行下一次更新之前,都会先调用一下
LateUpdate() 方法,该方法也是以帧为单位执行。
脚本生命周期(续 14 )

 哪些工作可交给 LateUpate() 完成呢?


和相机相关的更新放在这里。如:当物体在 Update()
里移动时,跟随物体的相机可以在 LateUpdate() 里实
知 现。比较适合用于命令脚本的执行。对 LateUpdate()


方法的具体使用,官网上给出的案例是摄像机的跟随,
解 都是在所有 Update() 操作完才跟进摄像机,不然就有
可能出现摄像机已经推进了,但是视角里还未有角色的
空帧出现。
通过物体移动观察更新区别

• 在场景中添加一个立方体,实现立方体沿 Z 轴移动(向
前移动),并打印距离上一帧执行所用的时间。通过该
例子观察立方体移动时, Update() 和 FixedUpdate()
课 两个执行时每一帧耗用时间的问题。



通过物体移动观察更新区别(续
1)
• 创建一个场景文件: Demo1Scene( 由 Plane,Cube) 组
成:





通过物体移动观察更新区别(续
2)
• Hierarchy 面 板 中 的 内 容 , 如 图 1 。 场 景 中 地 板
( Plane )的 Inspector 主要内容,如图 2 。场景中立
方体( Cube )的 Inspector 主要内容如图 3 :



习 图2

图3
图1
通过物体移动观察更新区别(续
3)
• 创建一个脚本文件: Demo1Script.cs ,下面的结果是伤
使用 FixedUpdate() 实现及控制台打印内容:





通过物体移动观察更新区别(续
4)
• 创建一个脚本文件: Demo1Script.cs ,下面的结果是伤
使用 Update() 实现及控制台打印内容:





脚本生命周期(续 15 )

• 渲染模块: OnGUI()
 OnGUI() 方法的完整形式是什么?什么时候被调用呢?
主要负责完成的工作的又是什么呢?
知  OnGUI() 的完整形式: private void OnGUI() {......}

讲  执行完 Start() 方法后,会接着执行 OnGUI() 方法,并且

会循环调用该方法来绘制图形界面。
 在处理和渲染与 GUI 有关的事件时调用,由于后面会使
用 NGUI ,所以对 OnGUI() 了解就可以。
• 比如:你画一个 button 或 label 时常常用到它。这意味
着 OnGUI() 也是每帧执行一次。
脚本生命周期(续 16 )

• 下面代码介绍了 OnGUI() 方法的使用:





脚本生命周期(续 17 )

• 销毁模块: OnDisable()
 OnDisable() 方法的完整定义形式是什么?什么时候调
用此方法?方法主要作用是什么?会被调用多少次呢?
知  OnDisable() 完整形式: private void OnDisable()

讲 {......}

 当前对象不可用或脚本处于非激活状态时会调用该方法;
如何才能体现 OnApplicationQuit 调用时会调用 , 还会
再设置 enable = false 或 active = false 调用。
 这个方法会在一个对象销毁前一帧调用,会在所有帧更
新一个对象存在的最后一帧之后执行,对象也许会响应
Object.Destroy 或一个场景关闭时被销毁。
脚本生命周期(续 18 )

• 销毁模块: OnDestory()
 OnDestory() 方法的完整定义形式是什么?什么时候调
用此方法?方法主要作用是什么?会被调用多少次呢?
知  OnDestory() 完整形式: private void OnDestory()

讲 {.....}

 当对象或脚本被销毁时会调用本方法。体现在代码中:
1. 在 OnApplicationQuit() 时会调用 2. 通过
Destory( 列表 ) 销毁游戏对象时也会调用。这个函数在
会在一个对象销毁前一帧调用,会在所有帧更新一个对
象存在的最后一帧之后执行,对象也许会响应
Object.Destroy 或一个场景关闭时被销毁。
脚本生命周期(续 19 )
• 以下是官方网站提供的脚本完整生命周期执行流程图:





脚本生命周期(续 20 )

• 创建工程,并在工程下创建一个场景, ScriptLife
• 1 )在场景下添加游戏对象, 3D Object->Cube ;然后
添加了一个脚本, LiftScript1.cs 。如图 1
知 • 2 )在 LiftScript1.cs 中,添加了完整的 8 个生命周期方

讲 法,每个方法打印了一句话,如图 2 ;

• 3 )然后,将此脚本绑定到 Cube 游戏对象上。最后,运
行程序,如图 3
脚本生命周期(续 21 )





图1

图2
访问游戏对象

访问游戏对象 访问游戏对象 访问游戏对象


访问游戏对象
访问游戏对象

• 在 Unity 场景中出现的所有物体都属于游戏对象,
( GameObject ) ,游戏对象和脚本是紧密相联的,游戏
对象间的交互通常也是通过脚本来实现的。在 Unity 中,
知 开发者可通过以下几种方式来访问游戏对象。



访问游戏对象(续 1 )
• 当场景前工程下面创建一个场景, FindGameObect1 ;
在该场景下放一个游戏对象, 3D Object->Cube ,
然后创建一个脚本文件, FindByTagScript.cs ,在脚本
知 文件中查找场景中的 Cube 游戏对象,代码如下:



访问游戏对象(续 2 )

II. 通过标签来查找: GameObject.FindWithTag( 标签名


) 如果场景中存在指定标签的游戏对象,那么返回该对
象的引用,否则返回 null ;如果多个游戏对象使用同一

标签,那么返回第一个游戏对象的引用(这里的第一个,
识 指的是最后一个添加的游戏对象)。如果场景中有多个

解 相同标签的游戏对象,可以通过
FindGameobjectWithTag() 方法获取游戏对象数组。
访问游戏对象(续 3 )
• 在当前工程下面创建一个场
景, indGameObjectsScene 在该场景下放三个游戏对
象, Player1,Player2,Player3 (3D Object->Cube 对

象),这三个游戏对象的 Tag 都设置为同一个 Tag ,名
识 为: Players ,然后创建一个脚本文


件,名为: FindGameObjectsScript.cs ,在脚本文件
中通过标签名查找场景中的 Cube 游戏对象。
访问游戏对象(续 5 )
 第一:为场景中的多个 cub 游戏对象设置同一个 Tag
首先选中场景中的某个游戏对象,然后在右侧 Inspector
中选择 Tag 这一项,点击向下列表,选择 Add
知 Tag ,在弹出的选项中点击 + 号,弹出下面图片,输入

讲 Tag 名字即可。然后同样的方式为另外两个 Cub 设置刚

刚创建的 Tag 名字。
访问游戏对象(续 6 )
 第二:打开 FindGameObjectsScript.cs 脚本文件,代
码如下:

知 运行结果



总结和答疑

You might also like