计算机游戏程序设计实验指导书河北工业大学计算机科学与软件学院1实验一Unity游戏脚本一、实验目的与要求1.熟悉及掌握MonoDevelop脚本编辑器的使用方法。2.Unity脚本的生命周期。3.熟练使用脚本来操作游戏对象。二、实验原理及知识点Unity游戏脚本在整个游戏开发中可以说是关键要素,游戏对象之间任何逻辑的判断都需要通过脚本来完成。如果说游戏贴图、模型资源的好坏决定一个游戏的视觉品味,那么脚本将直接决定这个游戏的内在质量,决定这个游戏好玩与否。游戏脚本与其他游戏组件用法相同,必须绑定在游戏对象中才能执行它的生命周期。Unity一共支持3种语言来编写脚本,分别是JavaScript、C#、Boo,这3种语言不分好坏,用哪一种来编写都可以达到同样目的。从编程技巧与难度上来讲,JavaScript更容易上手一些,建议初学者使用JavaScript进行入门阶段学习,但是进阶阶段推荐使用C#语言来编写脚本,因为C#语言在编程思想上更符合Unity引擎的原理。由于与传统语言相比,Boo语言的语法更为怪异,所以开发中几乎不会用到它。1MonoDevelop脚本编辑器Unity可部署在Windows与MacOSX梁总操作系统下,所以Unity需要一个跨平台的脚本编辑器。MonoDevelop脚本编辑器并不是Unity公司所研发的。它是一个开源项目,任何人或公司都可以使用。由于该编辑器具有强大的跨平台功能,并且使用起来非常方便,所以很快被Unity公司作为核心脚本开发环境使用。2Unity脚本的生命周期Unity脚本从唤醒到销毁有着一套比较完善的生命周期,添加任何脚本2都必须遵守自身生命周期法则。下面介绍一下生命周期中有系统自身调用的几个比较重要的方法。functionAwake(){}。脚本唤醒,此方法为系统执行的第一个方法,用于脚本的初始化,在脚本的生命周期中只执行一次。functionStart(){}。此方法在Awake()方法之后、Update()方法之前执行,并且只执行一次。functionUpdate(){}。正常更新,用于更新逻辑。此方法每帧都会由系统自动调用一次。functionLateUpdate(){}。推迟更新,此方法在Update()方法执行完后调用,同样每一帧都调用。functionFixedUpdate(){}。固定更新,固定更新常用于移动模型等操作。因为固定更新每一帧调用的时间相隔都是完全一样的,所以模型的移动过程会比较均匀。functionOnGUI(){}。绘制界面。这个方法大家应该不会陌生,因为在第3章中已经做过很多例子了。它和Update()方法一样,每一帧都在调用,只是它是用来绘制界面的。functionOnDestroy(){}。当前脚本销毁时调用。3利用脚本来操作游戏对象在Unity场景中出现的所有实体都属于游戏对象,比如系统自带的立方体、球体以及由美工制作的.Fbx游戏模型等。游戏对象与脚本联系非常紧密,因为游戏对象之间的一切交互都需要使用脚本来完成。下面我们开始学习如何使用脚本来操作游戏对象。使用脚本来调用游戏对象的方式有两种,它们是:可以将脚本绑定在一个游戏对象身上,也可以在代码中动态绑定脚本和删除脚本。任何一个游戏对象都可以同时绑定多条游戏脚本,并且这些脚本互不干涉,各自完成各自的生命周期。33.1创建游戏对象创建游戏对象的方式共有一下两种。第一种为将模型预先放入Hierarchy视图中,然后在场景视图中任意拖动该模型在3D世界中的位置,运行游戏后该模型就会出现在Game视图中。第二种为在代码中根据条件动态创建与删除游戏对象,这种处理方式灵活性比较高。3.2获取游戏对象在脚本中获取游戏对象的方式一共有三种:第一种为通过对象名称获取,第二种为通过标签(tag)获取单个游戏对象,第三种为通过相同标签获取多组游戏对象。3.3添加组件与修改组件新创建的游戏对象本身并不具备任何特性,为了让它具备一些功能,就必须给其添加游戏组件。游戏组件的种类非常多,常见的游戏组件有脚本类、网格类、粒子类、物理类、声音类和渲染类等。本节中我们将学习如何在代码中添加与修改游戏组件。添加游戏组件时,可以使用AddComponent()方法。由于组件自身没有对应的删除方法,需要使用父类执行Object.Destroy()方法才能删除它,其中该方法的参数为需要删除的游戏对象或游戏组件。在删除某一游戏对象时,将连带该对象中的所有组件一并删除。3.4克隆游戏对象克隆游戏对象与创建游戏对象在效果的呈现方式是完全一样的,但是从执行效率上来讲,克隆游戏对象的效率要高。使用脚本克隆游戏对象在游戏中应用非常广泛,常用于一些完全相同并且数量庞大的游戏对象,比如游戏中发射的子弹对象,每一颗子弹对象是完全一样的,每一次发射子弹都会新克隆一个子弹对象,并且让克隆的子弹对象完成自己的生命周期。在代码中,需要使用Instantiate()方法克隆游戏对象。44用脚本来控制对象的变换在3D世界中,任何一个游戏对象在创建的时候都会附带Transform(变换)组建,并且该组建是无法删除的。Transform面板中一共包含3个属性:Position(位置)、Rotation(旋转)和Scale(缩放)。在场景中使用移动工具来拖动和旋转模型,即可直接在Transform面板中看到编辑后的值,此外也可在Transform面板的编辑框中修改对象的位置、旋转方式和缩放的数值。4.1改变游戏对象的位置在3D世界中,任何一个模型的三维坐标都保存在Vector3容器中,该容器将记录模型在x轴、y轴和z轴方向的坐标。一旦在程序中修改该模型在Vector3容器中的坐标,那么Scene视图中模型的位置将发生改变。4.2旋转游戏对象模型的旋转方式可分为2种:第一种为自身旋转,意思是模型沿着自己的x轴,y轴或z轴方向旋转;第二种为围绕旋转,意思是模型围绕着坐标系中的抹一点或摸一个游戏对象整体来做旋转。下面简要介绍一下经常会用到的一些重要方法和参数。transform.Rotate():该方法用于设置模型绕自身旋转,起参数为旋转的速度与旋转的方向。transform.RRotateAround():该方法用于设置模型围绕某一个点旋转。Time.deltaTime:用于记录上一帧所消耗的时间,这里用作模型旋转的速度系数。Vector3.right:x轴方向。Vector3.up:y轴方向。Vector3.forward:z轴方向。5当模型绕自身旋转时,可以使用objCube.transform.Rotate()方法,当模型围绕抹一点旋转时,则使用objCube.transform.RotateAround()方法。4.3平移游戏对象平移的含义是模型在原有位置的基础上继续移动,在代码中可以使用transform.Translate()方法来实现,此方法的唯一参数为平移模型的方向。4.4缩放游戏对象在Unity中,可以通过代码动态缩放游戏中的模型。主要有三种缩放方式:沿x轴缩放、沿y轴缩放、沿z轴缩放。每个轴都有自身的缩放洗漱,模型默认的缩放系数是1,就是模型原有大小,因此要在程序中实现模型的缩放,只需要动态修改模型的缩放系数即可。三、实验内容及步骤1.熟悉MonoDevelop脚本编辑器的使用方法,联系实现脚本调试。2.编程实现创建游戏对象(立方体,球体),给游戏对象命名,改变颜色,添加刚体组件。代码:usingUnityEngine;usingSystem.Collections;publicclassgameobject:MonoBehaviour{//UsethisforinitializationvoidStart(){varobjCube=GameObject.CreatePrimitive(PrimitiveType.Cube);objCube.AddComponent(typeof(Rigidbody));objCube.name=Cube;objCube.renderer.material.color=Color.blue;objCube.transform.position=newVector3(1f,0.0f,0.0f);6GameObjectobjSphere=GameObject.CreatePrimitive(PrimitiveType.Sphere);objSphere.AddComponent(typeof(Rigidbody));objSphere.name=Sphere;objSphere.renderer.material.color=Color.red;objSphere.transform.position=newVector3(-1f,0.0f,0.0f);}//UpdateiscalledonceperframevoidUpdate(){}}实验结果:此效果是在有光线的情况下,如果没有光线,物体看上去为黑色。物体具有刚体属性,受到重力作用,如果没有平面支持,物体将会一直做自由落体运动。3.分别通过名称、标签获得游戏对象,通过标签获得多个游戏对象。(1)首先创建立方体和球体两个对象7(2)创建标签,再对立方体和球体应用此标签。(3)编写脚本分别通过物体名称和物体物体标签寻找游戏对象。实验结果:4.通过脚本控制游戏对象,改变游戏对象的位置,旋转游戏对象,缩放游戏对象。代码:usingUnityEngine;usingSystem.Collections;publicclassgameobject:MonoBehaviour{8publicGameObjectobjCube;publicGameObjectobjSphere;publicGameObjectobjCylinder;//UsethisforinitializationvoidStart(){objCube=GameObject.CreatePrimitive(PrimitiveType.Cube);objCube.AddComponent(typeof(Rigidbody));objCube.name=Cube;objCube.renderer.material.color=Color.blue;objCube.transform.position=newVector3(1f,0.0f,0.0f);objSphere=GameObject.CreatePrimitive(PrimitiveType.Sphere);objSphere.AddComponent(typeof(Rigidbody));objSphere.name=Sphere;objSphere.renderer.material.color=Color.red;objSphere.transform.position=newVector3(-1f,-1.52f,2.0f);objCylinder=GameObject.CreatePrimitive(PrimitiveType.Cylinder);objCylinder.AddComponent(typeof(Rigidbody));objCylinder.name=Cylinder;objCylinder.renderer.material.color=Color.green;objCylinder.transform.position=newVector3(-3f,-1.52f,0.0f);}//UpdateiscalledonceperframevoidUpdate(){objCube.transform.Rotate(0.0f,Time.deltaTime*200,0.0f);objCube.transform.Translate(Vector3.fwd*Time.deltaTime);objSphere.transform.position=newVector3(-1f,-1.52f,2.0f*Mathf.Exp(-Tim