下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領
文檔簡介
Unity3D腳本中文教程Part1一、腳本概覽這是一個關于Unity內(nèi)部腳本如何工作的簡單概覽。Unity內(nèi)部的腳本是通過附加自定義腳本對象到游戲物體組成的。在腳本對象內(nèi)部不同志的函數(shù)被特定的事件調(diào)用。最常用的列在下面Update這個函數(shù)在渲染一幀之前被調(diào)用這里是大部分游戲行為代碼被執(zhí)行的地方除了物理代碼。FixedUpdate這個函數(shù)在每個物理時間步被調(diào)用一次這是處理基于物理游戲的地方。在任何函數(shù)之外的代碼在任何函數(shù)之外的代碼在物體被加載的時候運行這個可以用來初始化腳本狀態(tài)。注意文檔的這個部份假設你是用Javascript參考用C編寫獲取如何使用C和Boo編寫腳本的信息。你也能定義事件句柄它們的名稱都以On開始例如OnCollisionEnter為了查看完整的預定義事件的列表參考MonoBehaviour文檔。概覽常用操作大多數(shù)游戲物體的操作是通過游戲物體的Transform或Rigidbody來做的在行為腳本內(nèi)部它們可以分別通過transform和rigidbody訪問因此如果你想繞著Y軸每幀旋轉(zhuǎn)5度你可以如下寫functionUpdatetransform.Rotate050如果你想向前移動一個物體你應該如下寫functionUpdatetransform.Translate002概覽跟蹤時間Time類包含了一個非常重要的類變量稱為deltaTime這個變量包含從上一次調(diào)用Update或FixedUpdate根據(jù)你是在Update函數(shù)還是在FixedUpdate函數(shù)中到現(xiàn)在的時間量。所以對于上面的例子修改它使這個物體以一個恒定的速度旋轉(zhuǎn)而不依賴于幀率functionUpdatetransform.Rotate05Time.deltaTime0移動物體functionUpdatetransform.Translate002Time.deltaTime如果你加或是減一個每幀改變的值你應該將它與Time.deltaTime相乘。當你乘以Time.deltaTime時你實際的表達我想以10米/秒移動這個物體不是10米/幀。這不僅僅是因為你的游戲?qū)ⅹ毩⒂趲\行同時也是因為運動的單位容易理解。米/秒另一個例子如果你想隨著時間增加光照的范圍。下面的表達式以2單位/秒改變半徑。functionUpdatelight.range2.0Time.deltaTime當通過力處理剛體的時候你通常不必用Time.deltaTime因為引擎已經(jīng)為你考慮到了這一點。概覽訪問其他組件組件被附加到游戲物體附加Renderer到游戲物體使它在場景中渲染附加一個Camera使它變?yōu)橄鄼C物體所有的腳本都是組件因為它們能被附加到游戲物體。最常用的組件可以作為簡單成員變量訪問Component可如下訪問TransformtransformRigidbodyrigidbodyRendererrendererCameracameraonlyoncameraobjectsLightlightonlyonlightobjectsAnimationanimationCollidercollider…等等。對于完整的預定義成員變量的列表。查看ComponentBehaviour和MonnoBehaviour類文檔。如果游戲物體沒有你想取的相同類型的組件上面的變量將被設置為null。任何附加到一個游戲物體的組件或腳本都可以通過GetComponent訪問。transform.Translate030//等同于GetComponentTransform.Translate010注意transfom和Transform之間大小寫的區(qū)別前者是變量小寫后者是類或腳本名稱大寫。大小寫不同使你能夠從類和腳本名中區(qū)分變量。應用我們所學你可以使用GetComponent找到任何附加在同一游戲物體上的腳本和組件請注意要使用下面的例子能夠工作你需要有一個名為OtherScript的腳本其中包含一個DoSomething函數(shù)。OtherScript腳本必須與下面的腳本附加到相同的物體上。//這個在同一游戲物體桑找到名為OtherScript的腳本//并調(diào)用它上加的DoSomethingfunctionUpdateotherScriptGetComponentOtherScriptotherScript.DoSomething概覽訪問其它游戲物體大多數(shù)高級的代碼不僅需要操作一個物體Unity腳本接口有各種方法來找到并訪問其他游戲物體和組件。在下面我們假定有個一名為OtherScriptjs的腳本附加到場景的游戲物體上。varfoo5functionDoSomethingparam:Stringprintparamquotwithfoo:quotfoo1.通過檢視面板賦值引用你可以通過檢視面板賦值變量到任何物體//變換拖動到target的物體vartarget:TransformfunctionUpdatetarget.Translate010你也可以在檢視面板中公開到其他物體的引用下面你可以拖動一個包含的游戲物體到檢視面板中的target槽。//設置在檢視面板中賦值的target變量上的foo調(diào)用DoSomethingvartarget:OtherScriptfunctionUpdate//設置target物體的foo變量target.foo2//調(diào)用target上的DoSomethingtarget.DoSomethingquotHelloquot2.通過物體層次定位對于一個已經(jīng)存在的物體可以通過游戲物體的Transform組件來找到子和父物體//找到腳本所附加的//游戲物體的子―Hand∥transform.FindquotHandquot.Translate010一旦在層次視圖中找到這個變換你可以使用GetComponent來獲取其他腳本//找到名為―Hand∥的子//在附加到它上面的OtherScript中設置foo為2transform.FindquotHandquot.Translate010//找到名為―Hand∥的子//然后應用一個力到附加在hand上的剛體transform.FindquotHandquot.GetComponentOtherScript.DoSomethingquotHelloquot//找到名為―Hand∥的了//然后應用一個力到附加在hand上的剛體transform.FindquotHandquot.rigidbody.AddForce0100你可以循環(huán)所有的子//變換的所有子向上移動10個單位forvarchild:Transformintransformchild.Translate010參考Transform類文檔獲取更多信息。Part23.根據(jù)名稱或標簽定位.你可以使用GameObject.FindWithTag和GameObject.FindGameObjectsWithTag搜索具有特定標簽的游戲物體使用GameObject.Find根據(jù)名稱查找物體。functionStart//按照名稱vargoGameObject.FindquotSomeGuyquotgo.transform.Translate010//按照標簽varplayerGameObject.FindWithTagquotPlayerquotplayer.transform.Translate010你可以在結(jié)果上使用GetComponent在找到的游戲物體上得到任何腳本或組件。functionStart//按名稱vargoGameObject.FindquotSomeGuyquotgo.GetComponentOtherScript.DoSomething//按標簽varplayerGameObject.FindWithTagquotPlayerquotplayer.GetComponentOtherScript.DoSomething一些特殊的物體有快捷方式如主相機使用Camera.main。4.作為參數(shù)傳遞一些事件消息在事件包含詳細信息。例如觸發(fā)器事件傳遞碰撞物體的Collider組件到處理函數(shù)。OnTriggerStay給我們一個到碰撞器的引用。從這個碰撞器我們可以獲取附加到其上的剛體。functionOnTriggerStayother:Collider//如果另一個碰撞器也有一個剛體//應用一個力到它上面ifother.rigidbodyother.rigidbody.AddForce020或者我們可以通過碰撞器獲取附加在同一個物體上的任何組件。functionOnTriggerStayother:Collider//如果另一個碰撞器附加了OtherScript//調(diào)用它上面的DoSomething//大多數(shù)時候碰撞器不會附加腳本//所以我們需要首先檢查以避免null引用異常ifother.GetComponentOtherScriptother.GetComponentOtherScript.DoSomething注意通過上述例子中的other變量你可以訪問碰撞物體中的任何組件。5.一種類型的所有腳本使用Object.FindObjectsOfType找到所有具有相同類或腳本名稱的物體或者使用Object.FindObjectOfType.找到這個類型的第一個物體。functionStart//找到場景中附加了OtherScript的任意一個游戲物體varother:OtherScriptFindObjectOfTypeOtherScriptother.DoSomething概覽向量Unity使用Vector3類同一表示全體3D向量3D向量的不同組件可以通過想xy和z成員變量訪問。varaPosition:Vector3aPosition.x1aPosition.y1aPosition.z1你也能夠使用Vector3構(gòu)造函數(shù)來同時初始化所有組件。varaPositionVector3111Vector3也定義了一些常用的變量值。vardirectionVector3.up//與Vector3010相同單個向量上的操作可以使用下面的方式訪問someVector.Normalize使用多個向量的操作可以使用Vector3類的數(shù)theDistanceVector3.DistanceoneVectorotherVector注意你必須在函數(shù)名之前寫Vector3來告訴JavaScript在哪里找到這個函數(shù)這適用于所有類函數(shù)你也可以使用普通數(shù)學操作來操縱向量。combinedvector1vector2查看Vector3類文檔獲取完整操縱和可用屬性的列表。概覽成員變量amp全局變量變量定義在任何函數(shù)之外的變量是一個成員變量。在Unity中這個變量可以通過檢視面板來訪問任何保存在成員變量中的值也可以自動隨工程保存。varmemberVariable0.0上面的變量將在檢視面板中顯示為名為quotMemberVariablequot的數(shù)值屬性。如果你設置變量的類型為一個組件類型例如TransformRigidbodyCollider任何腳本名稱等等然后你可以在檢視面板中通過拖動一個游戲物體來設置它們。varenemy:TransformfunctionUpdateifVector3.Distanceenemy.positiontransform.positionlt10printquotIsensetheenemyisnearquot你也可以創(chuàng)建私有成員變量。私有成員變量可以用來存儲那些在該腳本之外不可見的狀態(tài)。私有成員變量不會被保存到磁盤并且在檢視面板中不能編輯。當它被設置為調(diào)試模式時它們在檢視面板中可見。這允許你就像一個實時更新的調(diào)試器一樣使用私有變量。privatevarlastCollider:ColliderfunctionOnCollisionEntercollisionInfo:CollisionlastCollidercollisionInfo.other全局變量你也可以使用static關鍵字創(chuàng)建全局變量這創(chuàng)造了一個全局變量名為someGlobal//TheScriptName.js中的一個靜態(tài)變量staticvarsomeGlobal5//你可以在腳本內(nèi)部像普通變量一樣訪問它printsomeGlobalsomeGlobal1為了從另一個腳本訪問它你需要使用這個腳本的名稱加上一個點和全局變量名。printTheScriptName.someGlobalTheScriptName.someGlobal10Part3概覽實例化實例化復制一個物體。包含所有附加的腳本和整個層次。它以你期望的方式保持引用。到外部物體引用的克隆層次將保持完好在克隆層次上到物體的引用映射到克隆物體。實例化是難以置信的快和非常有用的。因為最大化地使用它是必要的。例如這里是一個小的腳本當附加到一個帶有碰撞器的剛體上時將銷毀它自己并實例化一個爆炸物體。varexplosion:Transform//當碰撞發(fā)生時銷毀我們自己//并生成給一個爆炸預設functionOnCollisionEnterDestroygameObjectvartheClonedExplosion:TransformtheClonedExplosionInstantiateexplosiontransform.positiontransform.rotation實例化通常與預設一起使用概覽CoroutinesampYield在編寫游戲代碼的時候常常需要處理一系列事件。這可能導致像下面的代碼。privatevarstate0functionUpdateifstate0//做步驟0state1returnifstate1//做步驟1state2return//…更方便的是使用yield語句。yield語句是一個特殊類型的返回這個確保在下次調(diào)用時該函數(shù)繼續(xù)從該yield語句之后執(zhí)行。whiletrue//做步驟0yield//等待一幀//做步驟1yield//等待一幀//...你也可以傳遞特定值給yield語句來延遲Update函數(shù)的執(zhí)行直到一個特定的事件發(fā)生。//做一些事情yieldWaitForSeconds5.0//等待5秒//做更多事情…可以疊加和連接coroutines。這個例子執(zhí)行Do在調(diào)用之后立即繼續(xù)。DoprintquotThisisprintedimmediatelyquotfunctionDoprintquotDonowquotyieldWaitForSeconds2printquotDo2secondslaterquot這個例子將執(zhí)行Do并等待直到它完成才繼續(xù)執(zhí)行自己。//鏈接coroutineyieldStartCoroutinequotDoquotprintquotAlsoafter2secondsquotprintquotThisisaftertheDocoroutinehasfinishedexecutionquotfunctionDoprintquotDonowquotyieldWaitForSeconds2printquotDo2secondslaterquot任何事件處理句柄都可以是一個coroutine注意你不能在Update或FixedUpdate內(nèi)使用yield但是你可以使用StartCoroutine來開始一個函數(shù)。參考YieldInstructionWaitForSecondsWaitForFixedUpdateCoroutineandMonoBehaviour.StartCoroutine獲取更多使用yield的信息。概覽用C編寫腳本除了語法使用C或者Boo編寫腳本還有一些不同。最需要注意的是1.從MonoBehaviour繼承所有的行為腳本必須從MonoBehaviour繼承直接或間接。在Javascript中這自動完成但是必須在C或Boo腳本中顯示申明。如果你在Unity內(nèi)部使用Asset-gtCreate-gtCSharp/BooScript菜單創(chuàng)建腳本創(chuàng)建模板已經(jīng)包含了必需的定義。publicclassNewBehaviourScript:MonoBehaviour...//CclassNewBehaviourScriptMonoBehaviour:...Boo2.使用Awake或Start函數(shù)來初始化Javascript中放置在函數(shù)之外的代碼在C或Boo中要放置在Awake或Start中。Awake和Start的不同是Awake在場景被加載時候運行而Start在第一次調(diào)用Update或FixedUpdate函數(shù)之前被調(diào)用所有Awake函數(shù)在任何Start函數(shù)調(diào)用之前被調(diào)用。3.類名必須與文件名相同Javascript中類名被隱式地設置為腳本的文件名不包含文件擴展名。在c和Boo中必須手工做。4.在C中Coroutines有不同語法。Coroutines必有一個IEnumerator返回類型并且yield使用yieldreturn…而不是yield…usingSystem.CollectionsusingUnityEnginepublicclassNewBehaviourScript:MonoBehaviour//CcoroutineIEnumeratorSomeCoroutine//等一幀yieldreturn0//等兩秒yieldreturnnewWaitForSeconds25不要使用命名空間目前Unity還不支持將代碼放置在一個命名空間中這個需要將會出在未來的版本中。6.只有序列化的成員變量會顯示在檢視面板中私有和保護成員變量只在專家模式中顯示屬性不被序列化或顯示在檢視面板中。7避免使用構(gòu)造函數(shù)不要在構(gòu)造函數(shù)中初始化任何變量使用Awake或Start實現(xiàn)這個目的。即使是在編輯模式中Unity也自動調(diào)用構(gòu)造函數(shù)這通常發(fā)生在一個腳本被編譯之后因為需要調(diào)用構(gòu)造函數(shù)來取向一個腳本的默認值。構(gòu)造函數(shù)不僅會在無法預料的時刻被調(diào)用它也會為預設或未激活的游戲物體調(diào)用。單件模式使用構(gòu)造函數(shù)可能會導致嚴重的后果帶來類似隨機null引用異常。因此如果你想實現(xiàn)如一個單件模式不要使用構(gòu)造函數(shù)而是使用Awake。其實上沒有理由一定要在繼續(xù)自MononBehaviour類的構(gòu)造函數(shù)中寫任何代碼。概覽最重要的類Javascript中可訪問的全局函數(shù)或C中的基類移動/旋轉(zhuǎn)物體動畫系統(tǒng)剛體FPS或第二人稱角色控制器概覽性能優(yōu)化1使用靜態(tài)類型在使用Javascript時最重要的優(yōu)化是使用靜態(tài)類型而不是動態(tài)類型Unity使用一種叫做類型推理的技術(shù)來自自動轉(zhuǎn)換Javascript為靜態(tài)類型編碼而不需要你做任何工作。varfoo5在上面的例子里foo會自動被推斷為一個整型值。因此Unity可能使用大量的編譯時間來優(yōu)化。而不使用耗時的動態(tài)名稱變量查找等。這就是為什么Unity比其他在JavaScript的實現(xiàn)平均快20倍的原因之一。唯一的問題是有時并非一切都可以做類型推斷。Unity將會為這些變量重新使用動態(tài)類型。通過回到動態(tài)類型編寫JavaScript代碼很簡單。但是這也使得代碼運行速度較慢。讓我們看一些例子functionStartvarfooGetComponentMyScriptfoo.DoSomething這里foo將是動態(tài)類型因此調(diào)用DoSomething函數(shù)將使用較長時間因為foo的類型是未知的它必須找出它是否支持DoSomething函數(shù)如果支持調(diào)用它。functionStartvarfoo:MyScriptGetComponentMyScriptfoo.DoSomething這里我們強制foo為指定類型你將獲得更好的性能。2使用pragmastrict當然現(xiàn)在問題是你通常沒有意識到你在使用動態(tài)類型。pragmastrict解決了這個簡單的在腳本頂部添加pragmastrict。然后unity將在腳本中禁用動態(tài)類型強制使用靜態(tài)類型如果一個類型未知。Unity將報告編譯錯誤。那么在這種情況下foo將在編譯時產(chǎn)生一個錯誤pragmastrictfunctionStartvarfooGetComponentMyScriptfoo.DoSomething3.緩存組件查找另一個優(yōu)化是組件緩存。不幸的是該優(yōu)化需要一點編碼并且不一定是值得的但是如果你的腳本是真的用了很長時間了你需要把最后一點表現(xiàn)出來這是一個很好的優(yōu)化。當你訪問一個組件通過GetComponent或訪問變量Unity會通過游戲?qū)ο笳业秸_的組件。這一次可以很容易地通過緩存保存在一個私有變量里引用該組件。簡單地把這個functionUpdatetransform.Translate005變成privatevarmyTransform:TransformfunctionAwakemyTransformtransformfunctionUpdatemyTransform.Translate005后者的代碼將運行快得多因為Unity沒有找到變換在每一幀游戲組件中的對象。這同樣適用于腳本組件在你使用GetComponent代替變換或者其它的東西。4.使用內(nèi)置數(shù)組內(nèi)置數(shù)組的速度非??焖哉埵褂盟鼈?。而整列或者數(shù)組類更容易使用因為你可以很容易地添加元素他們幾乎沒有相同的速度。內(nèi)置數(shù)組有一個固定的尺寸但大多數(shù)時候你事先知道了最大的大小在可以只填寫了以后。關于內(nèi)置數(shù)組最好的事情是他們直接嵌入在一個結(jié)構(gòu)緊湊的緩沖區(qū)的數(shù)據(jù)類型沒有任何額外的類型信息或其他開銷。因此遍歷是非常容易的作為一切緩存在內(nèi)存中的線性關系。privatevarpositions:Vector3functionAwakepositionsnewVector3100forvari0ilt100ipositionsiVector3.zero5.如果你不需要就不要調(diào)用函數(shù)最簡單的和所有優(yōu)化最好
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年林芝貨運從業(yè)資格考試題目
- 2025年貨運從業(yè)資格證考試題庫答案
- 2025年廣州貨運從業(yè)資格證題庫年
- 2025頂管施工勞務分包合同模板
- 溶氣水釋放器行業(yè)深度研究報告
- 2025幕墻施工合同
- 上海外國語大學《圖形紋樣設計》2023-2024學年第一學期期末試卷
- mpa開題報告范文
- 實訓周報告范文
- 2025合同和解協(xié)議書
- 宮頸機能不全和宮頸縫扎術(shù)課件
- 醫(yī)療設備的清潔和消毒制度
- 湖南省基本概況
- 通信原理智慧樹知到期末考試答案章節(jié)答案2024年濰坊學院
- 承包商安全資質(zhì)審核管理規(guī)定模板
- 24春國家開放大學《建筑測量》形考任務實驗1-6參考答案
- 維保措施及方案設計流程
- 橋架及電纜敷設施工方案及流程
- 人工智能革命AI對全球勞動力市場的影響
- 第三單元名著閱讀《經(jīng)典常談》-2023-2024學年八年級語文下冊同步教學課件
- 人體解剖學與組織胚胎學說課講解
評論
0/150
提交評論