Unity 脚本入门


Unity脚本入门 在Unity中脚本是必不可少的组成部分,因为它将 定义你游戏的各种行为.这个教程将介绍 JavaScript的基本使用. 课时: 2小时. 作者: Graham McAllister 译者:威阿(2009-04-06) 目录 1. 教程目的 2. 前提 3. 命名规范 4. Player输入 5. 连接变量 6. 访问组件 7. 实例 8. 调试 9. 常见脚本类型 1. 教程目的 在Unity中,脚本是用来界定用户在游戏中的行为(或规则).Unity推荐使用的编程语言是 Javascript,但是C#或Boo同样也可以. 本教程不仅介绍了脚本的基础,也介绍了脚本的重要内容(API).你可以专注于您的游戏设计并缩 短开发周期.充分理解了这些的基础教程能使你更充分的使用Unity. 2. 前提 本教程的重点是Unity脚本基础,假设你已经熟悉了Unity的界面(如果不是,你应该阅读Unity GUI教程). 为了使脚本更容易理解,最好有个支持JavaScript语法高亮的代码编辑器,也就是将关键字用不同的颜 色显示出来. SubEthaEdit就是这样的编辑器. 注: 如果需要实际操作的文字,会被加”-”前缀. 3. 命名规范 在开始前,先说一下在Unity中的一些规范. 变量 – 首写是小写字母.变量用来储存游戏状态中的任何信息. 函数 – 首写是大写字母.函数是一个代码块,只需要写一次,在需要时候可以被再次重用. 类 – 首写是大写字母.可以被认为是函数的库. 提示:当阅读范例代码或者Unity的API,要注意首写字母,这将有助于你更好的理解对象之间的关系. 4. Player输入 我们第一个项目是在一个简单的游戏 场景中走动. 设置场景 - 启动Unity. 首先,让我们创建一个用来行走的平面, 用一个扁的Cube. - 创建一个Cube,缩放x,y,z为”5,0.1,5”, 它现在看起来应该是一个大平板.在层 次视图(Hierarchy View)中重命名 为”Plane”. - 创建第二个Cube,将它放置在这个大 平板的中心位置.如果在游戏视图 (Game View)看不到它们,那么改变主 相机位置使它们可见.重命名该物体 为”Cube1”. - 你也应该建立一个点光源,并且放在大平板之上,使它们更清晰. - 保存 选择菜单File->Save As保存这个场景文件. 我们第一个脚本 我们现在开始游戏设计.我们打算让Player移动. 通过控制主相机的位置来实现,要做到这一点,我们现在要写一个脚本来读取键盘的输入.然后把脚本 和相机链接起来(更多的在下一节). - 首先创建一个空脚本.选择” Assets->Create->Javascript”并在项目面板重命名为”Move1”. - 双击Move1脚本,它将打开,并且默认包含有Update()函数,我们将我们的代码插入这个函数,任何加 入Update()函数中的代码都将在每一帧(frame)执行一次. 在Unity中为了移动一个游戏对象我们需要用transform来更改它的位置,属于Translate,这个 Translate函数有x,y和z三个参数,因为我们想通过光标键控制主相机,我们只需要下面这些代码,来决 定按键按下后参数的变化: function Update () { transform.Translate(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); } Input.GetAxis()函数返回-1或1的一个值,例如在横轴上左光标键映射为-1,有光标键映射为1. 注意参数0为y轴,因为我们不希望镜头上仰.横轴和竖轴是在输入设置(Input Settings)中预先定义好的.从 Edit->Project Settings->Input中很容易重定义按键映射. - 打开脚本Move1并输入上面的代码,注意大小写. 连接脚本 现在我们第一个脚本写完了,怎么让Unity的游戏对象具有这个脚本行为呢?我们要做的是赋予这个脚 本给游戏对象来体现脚本的行为. - 首先点击你希望应用此脚本的游戏对象,对于我们而言,这里将是主相机,你可以从层次视图和场景 视图中选择它. - 然后从菜单中选择Components->Scripts->Move1 ,将这个脚本赋予相机,你在检视面板中看到主相 机有Move1这个组件. 提示:你也可以从项目视图拖拽脚本到场景视图的游戏对象上. - 点击播放按钮运行游戏,你能通过光标键或W,S,A,D键来移动主相机.你也许注意到了,摄影机移动的 有点太快了,让我们来找一种更好的办法来控制摄像头的速度. Delta time 正如先前在Update()函数里的代码,相机的速度是按帧执行的.然而我们需要游戏对象的移动按秒执行. 为了实现这一目标,我们需要将返回的值乘以Input.GetAxis() 函数中的Time.deltaTime: var speed = 5.0; function Update () { var x = Input.GetAxis("Horizontal") * Time.deltaTime * speed; var z = Input.GetAxis("Vertical") * Time.deltaTime * speed; transform.Translate(x, 0, z); } - 将上面的代码更新到Move1脚本. 注意Update()外的这个速度变量.这是所为的暴露变量,这个变量会在检视面板中看到.它是很有用的, 实际使用中可以方便的调整它的值,这比改变代码来说方便的多. 5. 连接变量 通过Unity界面来连接变量是非常强大的. Unity的功能.它允许在Unity界面上拖拽(drag and drop)的方式来赋予脚本代码. 这是快速 又简洁的主意.这样在Unity界面中完成连接变 量,我们知道我们总是需要脚本代码中暴露的 变量,以便我们在检视面板中指派参数.为了演 示连接变量的概念,我们建立一个跟随玩家(主 相机)的聚光灯. - 添加一个聚光灯到场景视图,移动它靠近其他 游戏对象. - 创建一个JavaScript脚本并重命名为Follow. 让我们想想我们要做的,我们希望主相机的地 方有个聚光灯所照耀.事实上,Unity中有个函数 能做到这一点. transform.LookAt(). 如果你开始想”我该怎么做?”和已经想了很多代码.那么要记得经常查看Unity的函数API.,我们能同样 的猜想查看API中的” transform’”章节,为感兴趣的游戏对象的位置和旋转. 现在,我们来到连接变量章节,我们如何使用LookAt()参数呢?我们可以编写代码指定一个游戏对象,但 是我们是想通过Unity GUI来指派变量,因此我们将用一个暴露变量(Transform类型).我们的Follow.js 脚本应该如下: var target : Transform; function Update () { transform.LookAt(target); } - 赋予脚本给聚光灯,当这个脚本成功添加后,”target”变量就会暴露了. - 选中聚光灯,从层次视图拖拽主相机到监视面板中的”target”暴露变量上分配给target变量,即聚光灯 将跟随主相机.如果我们想聚光灯跟随不同的对象,我们也可以拖拽不同的对象过去(当然只要它的类 型是Transform). - 播放游戏,在场景视图中你能看到聚光灯跟随在主相机周围.你可以改变聚光灯的位置来改变效果. 6. 访问组件 作为一个游戏对象能有多个脚本(或其他组件).它不 可避免的要访问其他组件的函数或变量.Unity中通 过GetComponent() 函数来实现这个. 我们现在要添加另外的脚本来让按下跳跃键(默认空 格键)时让聚光灯射向Cube1. 让我们先思考这个问题,我们要做的是: 1. 监视跳跃键被按下. 2. 当跳跃键按下时,聚光灯将照射Cube1.我们如何 做到这一点呢?那么Follow脚本包含一个”target”变 量,其值确定哪些游戏对象被聚光灯所照射.我们需 要为这个值设定一个新的参数.我们可以写代码给这 个值为cube(看本节后的”写代码”),但我们知道暴露 了这个变量,通过GUI上指定变量的值是更好的办法: - 创建一个新的JavaScript脚本并重命名为Switch, 添加代码到Switch.js: var switchToTarget : Transform; function Update () { if (Input.GetButtonDown("Jump")) GetComponent(Follow).target = switchToTarget; } 尤其注意关注GetComponent()的值,这将返回一个参考给Follow脚本,我们就可以用它来访问”target” 变量. -添加Switch脚本到聚光灯和将在检视视图中指定Cube1给switchToTarget值. - 运行游戏,走动验证聚光灯像往常一样跟随着你,然后你按下空格键,聚光灯的焦点将转到Cube1上. 这样写代码 前面的教程中我们提到,可以通过写代码的方式指定变量(而不是通过Unity界面),让我们看看如何做. 记住,这只是用来比较,建议通过Unity界面来给变量赋值.早先按下空格时告诉聚光灯聚焦到Cube1上. 我们的解决方案是做一个暴露变量在Switch脚本,我们便可以在Unity的界面上拖拽Cube1上去.在代 码中主要有两种方法做到这一点: 1. 使用游戏对象的名称(name) 2. 使用游戏对象的标签(tag) 1. 游戏对象名称 可以从层次视图中看到游戏对象的名称.用GameObject.Find()函数来使这些名称作为参数. 因此如果我们想按下跳跃键时候切换聚光灯从主相机到Cube1,代码如下:: function Update () { if (Input.GetButtonDown("Jump")) { var newTarget = GameObject.Find("Cube").transform; GetComponent(Follow).target = newTarget; } } 注意没有暴露变量而是直接使用代码.查看API获得更多Find()的用法. 2. 游戏对象标签 游戏对象表情是字符串用于识别一个组件.在检视视图中点击Tag按钮查看内建的标签.你也可以创建 自己的标签. GameObject.FindWithTag()函数能通过具体标签寻找组件和返回一个字符串作为参数. 代码如下: function Update () { if (Input.GetButtonDown("Jump")) { var newTarget = GameObject.FindWithTag("Cube").transform; GetComponent(Follow).target = newTarget; } } 7. 实例 通常在运行时创建(create)对象(如游戏正在播放).要这样做,我们要用到Instantiate函数. 让我们讲述如何在每次按下开火按钮(或按鼠标左键或左Ctrl键)后通过实例(建立)一个新的游戏对象. 那么我们怎么做呢?我们希望用户像往常一样走动,当按下开火按钮,实例化创建一个新的对象.思考以 下几点: 1. 哪个物体做我们的实例? 2. 在哪里做实例化? 关于哪个对象到实例,最好的解决办法是暴露变量.这意味着我们随时可以通过拖拽游戏对象到变量来 改变对象为实例. 至于哪里做实例化,现在我们只要实现当按下开火按钮时在用户(主相机)当前位置创建新的游戏对象. 实例化函数有三个参数:(1)我们要建立一个对象,(2)对象的三维位置和(3)对象的旋转位置.完整的代码 如下(Create.js): var newObject : Transform; function Update () { if (Input.GetButtonDown("Fire1")) { Instantiate(newObject, transform.position, transform.rotation); } } 不要忘记, transform.position和transform.rotation是附加到脚本的transform的位置和选择的,这里假 如是主相机(Main Camera).然而,当一个对象被实例化,通常将对象设置为预设(prefab),我们现在将 Cube1游戏对象设置为预设. - 首先,让我们嫩创建一个空的预设,选择Assets->Create->Prefab.重命名这个预设为”Cube”. - 从层次视图拖拽Cube1游戏对象到项目视图的Cube预设上.注意预设图标的变化. 现在我们创建Javascript代码. - 创建一个新的脚本和命名为Create ,并插入上面的代码. - 把这个脚本赋予给主相机(Main Camera)和将Cube预设赋予主相机上的newObject 变量. - 运行游戏,并向以往一样走动.每当按下开火按钮(鼠标左键或左Ctrl)你都能看到一个新的Cube出现. 8. 调试 调试是发现和修正你的代码中人为错误的技巧,Unity中提供了Debug类,我们现在看看Debug.Log()函 数. Log Log()函数允许用户发送信息到Unity的控制台.这样做的原因可能包括: 1. 在运行时要验证某部分代码是否达成. 2. 报告变量的状态. 我们现在使用Log()函数,当用户点击开火按钮时发送一个消息到Unity控制台. - 打开创建的脚本并在” Instantiate’”代码内”if”处添加如下代码: Debug.Log("Cube created"); - 运行游戏和点击开火按钮,你能看到Unity界面下方显示” Cube created”,你可以点击这个提示详细查 看Unity控制台. Watch 另外一个有用的功能是用于调试私有变量.这使得当Debug模式被选中时检视视图中的变量,但它不 能被编辑.为了证明这一点,我们将暴露一个私有变量作为Cube实例的计数. - 再次打开创建的脚本并添加两行: (1) 添加私有变量引用cubeCount (2) 当一个cube实例创建后增加这个变量 完整代码如下(Create.js): var newObject : Transform; private var cubeCount = 0; function Update () { if (Input.GetButtonDown("Fire1")) { Instantiate(newObject, transform.position, transform.rotation); Debug.Log("Cube created"); cubeCount++; } } - 运行游戏并点击开火按钮创建一些Cube,注意每当一个新的Cube实例创建后cubeCount变量的递 增.同样这个数值是灰色的,意味着变量是只读的(不能编辑). 9. 常见脚本类型 每当一个新Javascript被创建,默认情况下将包含Update()函数.这一届将讲述其他常见的函数,简单的 从下面列表中替换Update()函数名字. FixedUpdate() 置于这个函数中的代码每隔一定间隔执行(固定的帧率).它通常被用来Rigibody中用力的时候. // Apply a upwards force to the rigid body every frame function FixedUpdate () { rigidbody.AddForce (Vector3.up); } Awake() 这里的代码将被用作初始化. Start() 这个函数将在Update()之前,但在Awake()之后执行. Start () 函数和Awake()函数的不同点在于Start() 函数仅在脚本启用时候执行(检视视图如果它的复选框被选中). OnCollisionEnter() 当游戏对象的碰撞脚本与另外的游戏对象碰撞时执行这个函数内的代码. OnMouseDown() 当鼠标在一个载有GUI元素(GUIElement)或碰撞器(Collider)的游戏对象里按下时执行该函数内的代 码. // Loads the level named "SomeLevel" as a response // to the user clicking on the object function OnMouseDown () { Application.LoadLevel ("SomeLevel"); } OnMouseOver() 当鼠标在一个载有GUI元素(GUIElement)或碰撞器(Collider)的游戏对象里的按下动作抬起后执行该 函数内的代码. // Fades the red component of the material to zero // while the mouse is over the mesh function OnMouseOver () { renderer.material.color.r -= 0.1 * Time.deltaTime; } 查看Unity API 获得这些函数的更多信息. 此教程介绍了Unity脚本的基本概念.你现在应该看看其他Unity教程或自己试试吧!
还剩6页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享pdf获得金币 ] 0 人已下载

下载pdf

pdf贡献者

pc5f

贡献于2013-10-13

下载需要 8 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf