还剩13页未读,继续阅读
本资源只提供10页预览,全部文档请下载后查看!喜欢就下载吧,查找使用更方便
文本内容:
脚本中文教程
一、脚本概览这是一个关于Unit y3D Parti内部脚本如何工作的简单概览内部的脚本是通过Unity.Unity附加自定义脚本对象到游戏物体组成的在脚本对象内部不同志的函数被特定的事件调用.最常用的列在下面这个函数在渲染一帧之前被调用这里是大部分游戏行Upda t e为代码被执行的地方除了物理代码这个函数Fi x edUp d ate在每个物理时间步被调用一次这是处理基于物理游戏的地方.在任何函数之外的代码在任何函数之外的代码在物体被加载的时候运行这个可以用来初始化脚本状态注意文档的这个部份假设你是用参考用编写获取如何使用J ava s crip t CC和编写脚本的信息你也能定义事件句柄它们的名称都Boo以开始例如为了查看完整的预定义On OnC o11is i on Enter事件的列表参考文档概览常用操作大多M o n o Beh a v i our数游戏物体的操作是通过游戏物体的或Trans for m Rigid body来做的在行为脚本内部它们可以分别通过和tran s fo r m rigi d访问因此如果你想绕着轴每帧旋转度你可以如下写body Y5如果你想向前移动一function Upda t et r a ns f orm.Rot a teO5O个物体你应该如下写fu n c t i o n Upda t et r ansform.Trans概览跟踪时间类包含了一个非常重要的类变1ate002Time量称为这个变量包含从上一次调用或deltaT i m eUpda t e F i根据你是在函数还是在xedU pd ateUpdate Fi xe d任何事件处理句柄都可以是一个注意你不能在ot co r outi n e或内使用但是你可以使用Update F ixedU p date yie1d S t来开始一个函数参考artCoroutine Yi e1d Ins tr uc t i o n WaitForS e conds W ai tFo rFi获xedUpdate Corou t ineand Mono Behaviour.Sta r Coroutine取更多使用的信息.概览用编写脚本除了语法使用yie1d C或者编写脚本还有一些不同最需要注意的是从C Boo
1.Mon继承所有的行为脚本必须从o Behavi o ur MonoBeh a vi our继承直接或间接在中这自动完成但是必须在J avascri p t C或脚本中显示申明如果你在内部使用一Boo UnityA ss et菜单创建脚本创建模板已经gt Create-gt CS harp/Boo Scrip t包含了必需的定义public c1ass NewB ehavi ourS c r i pt M o no Behavi o ur.o//C classNewBeh aviour Sc r i p t Mo noBehaviour.Booo o.使用或函数来初始化中放置在函2A wak e StartJav as cript数之外的代码在或中要放置在或中C BooAwak e S tart和的不同是在场景被加载时候运行而Awake St a rt Aw a ke在第一次调用或函数之前被调用所Start UpdateFixe dUpdate有函数在任何函数调用之前被调用.类名必Aw ak eStart3须与文件名相同中类名被隐式地设置为脚本的文件Javascript名不包含文件扩展名在和中必须手工做在中c Boo4Co有不同语法必有一个Coro utines C orouti n e slEnum e rato r返回类型并且使用而不是yie1d yield ret ur n...yield...u singSys t e m.C ollec t ionsusi n g UnityEng i nepublic classN ewBehavi ourScr i p t MonoBehav iour//等一帧C coro ut inelEnum e rator S o meC o rout ine//yield re〃等两秒不要turn0yieldr etur nnew Wai tFor S eco n d s25使用命名空间目前还不支持将代码放置在一个命名空Unity间中这个需要将会出在未来的版本中只有序列化的成员6变量会显示在检视面板中私有和保护成员变量只在专家模式中显示属性不被序列化或显示在检视面板中.避免使用构造7函数不要在构造函数中初始化任何变量使用或AwakeStart实现这个目的即使是在编辑模式中也自动调用构造函Unity数这通常发生在一个脚本被编译之后因为需要调用构造函数来取向一个脚本的默认值.构造函数不仅会在无法预料的时刻被调用它也会为预设或未激活的游戏物体调用单件模式使用构造函数可能会导致严重的后果带来类似随机引用n ull异常因此如果你想实现如一个单件模式不要使用构造函数而是使用其实上没有理由一定要在继续自Awake类的构造函数中写任何代码概览最重要MononBeha vio ur的类中可访问的全局函数或中的基类移动/旋转Ja v ascript C物体动画系统刚体或第二人称角色控制器概览性能优化FPS使用静态类型在使用时最重要的优化是使用静态1Javas cript类型而不是动态类型使用一种叫做类型推理的技术来Un i ty自自动转换为静态类型编码而不需要你做任何工J avasc rip t作.在上面的例子里会自动被推断为一个整型var foo5f值.因此可能使用大量的编译时间来优化而不使用耗Unity时的动态名称变量查找等这就是为什么比其他在Un ity J的实现平均快倍的原因之一唯一的问题是有时avaS cript20并非一切都可以做类型推断将会为这些变量重新使用.Un ity动态类型通过回到动态类型编写代码很简单JavaScr i pt但是这也使得代码运行速度较慢.让我们看一些例子f u notionSta rtvarfoo GetC om p onentMy S cri pt foo.D o S om eth i ng这里将是动态类型因此调用函数将使用较foo DoSometh ing长时间因为的类型是未知的它必须找出它是否支持foo函数如果支持调用它DoSome t hi n g fun c ti o nSt a rtva rfoo MyS cript GetC ompon entMyScriptf oo.D o S o met h ing这里我们强制为指定类型你将获得更好的性能使用foo2当然现在问题是你通常没有意识到你在使用动pragma st r i c t态类型解决了这个简单的在脚本顶部添加p r a g ma strictpra然后将在脚本中禁用动态类型强制使用gmastric t ouni ty静态类型如果一个类型未知将报告编译错Unit y误那么在这种情况下将在编译时产生一个错误f pragmastric tfu n cti onStar tva rfooG e tComponen tMy Sc r ipt foo缓存组件查找另一个优化是组件缓存DoSom ethi n g3不幸的是该优化需要一点编码并且不一定是值得的但是如果你的脚本是真的用了很长时间了你需要把最后一点表现出来这是一个很好的优化当你访问一个组件通过G etC ompo n或访问变量会通过游戏对象找到正确的组件这一ent Un ity次可以很容易地通过缓存保存在一个私有变量里引用该组件简单地把这个f变成unction Update transform.T ra ns1ate005p riv at ev a r myTra n sformTr a ns f o rmf unctionAwake myTran s f orm transf o rmfunction Up d atemyTr a n s f orm.Transl后者的代码将运行快得多因为没有找到变换ate005Un ity在每一帧游戏组件中的对象这同样适用于脚本组件在你使用代替变换或者其它的东西.使用内置G et ComP one n t4数组内置数组的速度非常快所以请使用它们而整列或者数组类更容易使用因为你可以很容易地添加元素他们几乎没有相同的速度内置数组有一个固定的尺寸但大多数时候你事先知道了最大的大小在可以只填写了以后关于内置数组最好的事情是他们直接嵌入在一个结构紧凑的缓冲区的数据类型没有任何额外的类型信息或其他开销因此遍历是非常容易的作为一切缓存在内存中的线性关系p rivatevar pos i tionsVec t or3function Awakep o s iti onsnew V e ctor3100for va r iOiltlOOi.如果你不需要就不要调用函数最pos itionsi Vector
3.zero5简单的和所有优化最好的是少工作量的执行.例如当一个敌人很远最完美的时间就是敌人入睡时可以接受直到玩家靠近时什么都没有做这是种缓慢的处理方式的情况f unc tion早期进行如果玩家实在是太遥远Update//if V e ct or
3.Distancet ra nsfo rm po sit io n targe t.pos ition g1100ret这不是一个好主意因为u rnp e rfo rm rea1work work..Unity必须调用更新功能而你正在执行工作的每一个帧一个比较好的解决办法是禁用行为直到玩家靠近.有种方法来做到这3一点使用和
1.OnBecameVis ib leOnBec amein visib这些回调都是绑到渲染系统的只要任何相机可以看到物1eo体将被调用当没有相机看到任何一个OnBecameVis ib1e将被调用这种方法在很多情况下非常OnBecam eIn visible有用但通常在中并不是特别有用因为只要你把相机离开他AI们敌人将不可用.function OnBecameVi sible en abled truef un cti on OnBec ame In vi sib1e enabled.使用触发器.一个简单的球形触发器会工作的非常好.false2一旦你离开这个影响球你将得到调用O nTrigg e r Enter/Exit function OnTrigger Enterc Colli d erif c.Com p ar eTagquotP1ayer q u o ten abledtru efunct i onOnT riggerExitc:C o
1.Iide rif c.Com pareTagq u o tPlayer q uo tenab1edfals e3使用协同程序调用的问题是它们每帧中都发生.很U pdate可能会只需要每秒检检查一次到玩家的距离这应该会节5省大量的处理周期.概览脚本编译高级编译所有的脚本Unity为文件将在运行时编译执行这允许脚本以惊.NET dlldll人的速度执行.这比传统的快约倍比原始ja vascr i pt20的代码慢大约在保存的时候将花费一点时间来C50o Unity编译所有脚本如果还在编译.你可以在主窗口的Un ity Unity右下角看到一个小的旋转进度图标脚本编译在个步骤中执4行所有在1q uotStandard Assetsquot q uotPr oS ta n dardAsset或的脚本被首先编译在这些文件s q u ot quot Plugi n squo t夹之内的脚本不能直接访问这些文.函数中到现在的时间量.所以对于上面的例子修改它Update使这个物体以一个恒定的速度旋转而不依赖于帧率functi移动onUp dat etr a nsf orm.Rotate05T im e.d eltaT ime0物体f un ction Update transf o rm如果你加或是减一个每帧改变T ranslat e002Time deltaTimeo的值你应该将它与相乘当你乘以Timeo d e1taTime Timeod时你实际的表达我想以米/秒移动这个物体不elt aT ime10是米/帧这不仅仅是因为你的游戏将独立于帧而运行同10时也是因为运动的单位容易理解米/秒另一个例子如果你想随着时间增加光照的范围.下面的表达式以单位/秒改变半2径.当f unotion Update ligh t range20T ime.d e1taTimeo O通过力处理刚体的时候你通常不必用因Time.d eIt aT ime为引擎已经为你考虑到了这一点概览访问其他组件组件被附加到游戏物体附加到游戏物体使它在场景中渲染Re nder er附加一个使它变为相机物体所有的脚本都是组件因Cam era为它们能被附加到游戏物体.最常用的组件可以作为简单成员变量访问可如下访问Co mponen t T rans form tr ansform Rigidb odyrigidbo d y Renderer re nde rerC ameracam erao nlyon ca meraob j ect sLight light onlyon lighto bje ctsA nimat ion anima tion Coll ide等等对于完整的预定义成员变量的列表查c oilider...o看和类Com pone ntBe haviour Mo nno Behaviour文档.如果游戏物体没有你想取的相同类型的组件上面的变量将被设置为任何附加到一个游戏物体的组nul1o件或脚本都可以通过访问GetComponen ttransf〃等同于orm.Transl ate030GetC ompon entTr an sform.注意和之间大Tran slat e010transfom T ran sform小写的区别前者是变量小写后者是类或脚本名称大写大小写不同使你能够从类和脚本名中区分变量.应用我们所学你可以使用找到任何附加在同一GetCompo n ent游戏物体上的脚本和组件请注意要使用下面的例子能够工作你需要有一个名为的脚本其中包含一OtherS c ript个函数脚本必须与下面的脚D oSomethingOtherScr i pt本附加到相同的物体上〃这个在同一游戏物体桑找到名为的脚本//并调用它上加的Oth er S cript DoS omethingfunction Update otherScript G e tCompone ntOthe rS概览访问其它游戏c ri ptot h erScr i pt D oSomet hin g物体大多数高级的代码不仅需要操作一个物体脚Unity本接口有各种方法来找到并访问其他游戏物体和组件在下面我们假定有个一名为的脚本附Othe rScriptj s加到场景的游戏物体上va rf oo5f unction DoS o methi.ngpa r am:Stringprin tp aramqu o twit hfoo:qu otfoo1通过检视面板赋值引用你可以通过检视面板赋值变量到任何物体〃变换拖动到的物体target vartarget:Transfor mfunction Upda te ta r getT ran你也可以在检视面板中公开到其他物体的引用下s lateO10面你可以拖动一个包含的游戏物体到检视面板中的槽.〃targe t设置在检视面板中赋值的变量上的调用t argetfoo D oSome〃设置物thing vartarget:0t herScri ptf unction Upd atetarg et体的变量//调用上的foo targ eto foo2t argetDoSomet hin gtargeto通过物体层次定位对于一D oSomet hingq u otHelloquot
2.个已经存在的物体可以通过游戏物体的组件来找Tran sform到子和父物体//找到脚本所附加的//游戏物体的子一Hand一旦在层次II transform Fi n dquotHandquoto Tr anslateO10o视图中找到这个变换你可以使用来获取其他Ge tC omponent脚本〃找到名为一的子〃在附加到它上面的Hand IIOtherScript中设置为fo o2t ransform Findqu o tH an d q uotoTran s1a teO0找到名为一的子〃然后应用一个力到附加在10//Hand IIhand上的刚体tra nsformFindquotH andquo tG etCompo neno找到名为tOtherSc ript.DoSome t hingquo tHe11o qu o t//一的了〃然后应用一个力到附加在上的刚体Hand IIhand tra nsfo rmFi ndquotHandqu o to ri g idbody.A ddForceO100o你可以循环所有的子//变换的所有子向上移动个单位10for varc hi Id:Tr a nsform intrans form chi参考类文档获取更多信息.1d.T ranslat e010Tran sformP.根据名称或标签定位你可以使用art23G ameObject.FindW汕和搜索T agGame Ob j ectoFindGam e Obj ects WithTa g具有特定标签的游戏物体使用根据名称GameOb jec tFindo查找物体.按照名称f unctionSta rt//v argo GameObje ctoFindqu o tSomeGuy quot go.transform.Tran slate010//按照标签var pla y erGameObj ec toFind WithT agquotPla y你可以在结果上使erquot player trans formT ransla teO10o用在找到的游戏物体上得到任何脚本或组Get Com p onent件按名称function Star t//var goGameObjec tF indquootSomeGuyquot goGetComponentOtherS cript.D oSomething//按标签var playerGam eOb jec t FindWi thTagquotP1aoye rquotpla yer.GetComponentOt h erScript.Do Somethi一些特殊的物体有快捷方式如主相机使用ngCame ra.ma in..作为参数传递一些事件消息在事件包含详细信息例如触4发器事件传递碰撞物体的组件到处理函数Collider OnTrig给我们一个到碰撞器的引用从这个碰撞器我们可ger Stay以获取附加到其上的刚体func tionOnTr ig gerStay ot h er:如果另一个碰撞Colli der//器也有一个刚体〃应用一个力到它上面if othe r.rigidb ody或者我们可以通过碰撞器获othe r.rigidbody.A ddForceO20取附加在同一个物体上的任何组件.fu nc tion OnTriggerStay如果另一个碰撞器附加了调other Co llider//OtherScript//用它上面的//大多数时候碰撞器不会附加脚Do Some thing本//所以我们需要首先检查以避免引用异常nu11i fother.GetCompo nentO therScript other.Ge tComponent0th注意通过上述例子中的变量e rScript.DoSomethin got her你可以访问碰撞物体中的任何组件.一种类型的所有脚本使用5o找到所有具有相同类或脚本名0bje ct.Find0b jectsOf Typ e称的物体或者使用.找到这个类型Ob ject.FindOb ject0fTyp e的第一个物体找到场景中附加了f un ctionS tart//的任意一个游戏物体OtherScrip tvar other:OtherS criptFindO概览向量b jectOfTypeOtherSc ript other DoSomethingo使用类同一表示全体向量向量的不同Unity V e ctor33D3D组件可以通过想和成员变量访问xy zvar a P osition:Vector你也能够使用3aPositio noX1aPosit ion.y1aPosition.z1V构造函数来同时初始化所有组件ect or3varaPos ition Vecto也定义了一些常用的变量值r3111Vector3var direction Ve与相同单个向量上的操作可以使ctor
3.u p//Vector3010用下面的方式访问someVe ctor使用多个向量的操作可以使用类的数Normal iz eVe ctor3注theD i st an ceVect or
3.Dist anceo ne VectorotherVector意你必须在函数名之前写来告诉在哪里Vect or3JavaSc ript找到这个函数这适用于所有类函数你也可以使用普通数学操作来操纵向量.查看类文combined vectorl vector2Vector3档获取完整操纵和可用属性的列表概览成员变量全局amp变量变量定义在任何函数之外的变量是一个成员变量在中这个变量可以通过检视面板来访问任何保存在成员变Unity量中的值也可以自动随工程保存.va rmemberV ariabl e
0.0上面的变量将在检视面板中显示为名为qu otMember Vari a的数值属性如果你设置变量的类型为一个组件类型blequot例如任何脚本名称等等Transfo rmRig idbo dyColli der然后你可以在检视面板中通过拖动一个游戏物体来设置它们varenemy Transformf unctionUpdateif Vector3o Distanceenem yposit iontransformposit ioo你也可以创on It10pr intquo tlsense theenemy isnea rquot建私有成员变量私有成员变量可以用来存储那些在该脚本之外不可见的状态私有成员变量不会被保存到磁盘并且在检视面板中不能编辑当它被设置为调试模式时它们在检视面板中可见这允许你就像一个实时更新的调试器一样使用私有变量pr iv atevar1ast ColliderColli der f unc tion OnCollisionE nte rco1lisionln fo:Co11i sionla stCo1Iide rc ol1全局变量你也可以使用关键字创建全isionl nfoo other static局变量这创造了一个全局变量名为s omeGlob al//Th eScri中的一个静态变量ptNam ejs static vars omeGlob al5/o你可以在脚本内部像普通变量一样访问它/printsomeGl o bal为了从另一个脚本访问它你需要使用这个脚本someG loba11的名称加上一个点和全局变量名.p r intT heScriptName somo概览实例化e G1obalT heScri ptName someGlobal10Pa rt3o实例化复制一个物体包含所有附加的脚本和整个层次.它以你期望的方式保持引用到外部物体引用的克隆层次将保持完好在克隆层次上到物体的引用映射到克隆物体实例化是难以置信的快和非常有用的因为最大化地使用它是必要的.例如这里是一个小的脚本当附加到一个带有碰撞器的刚体上时将销毁它自己并实例化一个爆炸物体var explosion:Tran s当碰撞发生时销毁我们自己〃并生成给一个爆炸预设form//functi on OnCo llisio nEnterDes troy gameObject varthe Cloned Exp1osion:TransformtheClon edE xp1osi on Instant iatee xplo sio实例化通常与预设n transformposition transform.rotati ono一起使用概览在编写游戏代码的时Coroutines ampYie1d候常常需要处理一系列事件这可能导致像下面的代码//做步骤private varstat e0function Updateif state00state做步骤更方便的是使1return ifsta te1//Istat e2return//...用语句语句是一个特殊类型的返回这个确保在yield yield下次调用时该函数继续从该语句之后执行yie Idw hi letru e//做步骤〃等待一帧//做步骤等待一帧〃..0y ield1yie Id//你也可以传递特定值给语句来延迟函数的执行yiel dUpdate直到一个特定的事件发生〃做一些事情y ie IdWai t〃等待秒//做更多事情…可以叠加和ForSecon d s505连接这个例子执行在调用之后立即继续c oroutinesDDo printquo tT hi si sp ri nted immed iatelyquotfunctionDo p rintquotDo nowquot yieldW aitForSec onds2printq uotDo2这个例子将执行并等待直到它完成才继secon ds laterquotDo续执行自己.〃链接coro utine yield St artCo routine quotDoquot printquotA1so a f ter2secondsq uotpr intquo tTh isisafter theDoco routine hasf inishedex ecu tionq uotfunctionDoprintquotDono wquot yie IdWaitForSeconds2printquo tDo2s eco nds1aterqu。
个人认证
优秀文档
获得点赞 0