Unity 4.3 2D 教程:新手上路
?
如果你嘗試用更早版本的Unity來制作2D游戲,那當然沒問題,但你也知道必須先解決一些問題。
可能你通過給quad應用紋理,使用腳本調整紋理參數來實現一些動畫。由于它們在3D環境,如果添加物理效果,你需要保證它們在同樣的深度才能互相作用,同時還要確保它們沒有意外的繞x或y軸旋轉。再者,你可能添加Unity的Asset Store中各種各樣的元件,例如2D Toolkit或者Orthello 2D Framework,它們都擁有一些很棒的特性,但還是需要你來控制。
現在Unity 4.3本地包提供了一個新的維度,你可以工作在2維環境,同時原先的一切仍然可用。
這是探索Unity2D系類教程的第一篇,通過這一系列教程,你將學會制作一個名叫Zombie Conga的游戲,這是一個2D卷軸游戲,其中有一個逍遙自在只想跳舞的僵尸,一個想在來世變成僵尸的貓,和一個想阻止它們的老處女。
學習怎樣在Unity 4.3中使用新的內置2D toolset制作一個2D游戲!
這個Unity 4.3 3D的教程重點放在Unity的新類型——Sprite,所有關于它你需要知道的知識,你都將學到,而且,之后你會學到如何使用Unity的 Animators 控制動畫,你也會了解到Unity的新2D物理支持。
還有很長的路要走,你應該起航了。
Note:這個教程假定你至少有一些Unity的經驗,你應該知道Unity的基本操作界面,GameObjects 和 Components,而且你也應該知道一些操作,比方說:
“通過從 Project browser 拖一個貓到 Hierarchy 來添加到你的場景”
如果你覺得它聽起想胡扯,或者你想讓你拖動這只貓的時候有一個更好的心態,你可能要先閱讀一下Unity的基本簡介,比如這個。
最后,注意這個教程是面向OS X的,如果你在Windows下工作,不用擔心,因為Unity中大多數操作都是相同的,可能會有一點點不同(比方使用Windows Explorer來代替Finder),但我相信你能搞定,或者你干脆你和我一樣用OS X也行。
推開大門
Unity在4.3版引入了本地2D工具包(免費和專業版都有),所以確保你安裝的是最新版本,你能在Unity的官網下載到。
你也需要一些素材來制作2D游戲,幸運的是,Mike Berg制作了一些很酷的圖片為Zombie Conga,下載Mike的作品,解壓它到某個方便的地方。
Note:你可以使用這個教程提供的素材,音樂和音效在你想做的游戲中,但是必須注明來源在你的游戲中:“Artwork/sounds: from iOS Game by Tutorials book, available at http://www.raywenderlich.com”
創建你的游戲
打開Unity通過選擇 File\New Project…. 點擊出現的 Project Wizard 對話框中的 Create new Project 選項卡中的 Set… 創建一個新的工程。
命名為ZombieConga,選擇一個文件來創建它,點擊 Save。
最后,選擇名稱為 Set up defaults for: 組合框中的2D,就像下面這樣,然后點擊 Create Project。
上面提到的組合框是第一個與2D有關的特性,它允許改變你項目的默認素材資源輸入設置,但是到目前為止,我們還沒有它正常工作。好在你可以在工程中輕松改變這個設置。
為了確保這個設置正確,同時讓你知道在哪里修改這個設置,選擇 Edit\Project Settings\Editor 來在 Inspector 打開 Editor Setting。在 Default Behavior Mode 段,把 Mode 的值選擇為2D,就像這樣。
這個 Default Behavior Mode 定義了你項目的默認素材資源輸入設置,當設置為3D時,Unity假設你想將圖像文件導入為 Texture (例如PNG文件),當設置為2D時,Unity假定你想將圖像文件導入為? Sprite,貫穿這套教程,你將了解到關于 Sprite 資源和輸入設置的更多細節。
2D場景視圖
你將面對的下一個2D特性是 2D 開關按鈕在 Scene 視圖的控制條上。
點擊 2D開關按鈕 來切換到2D模式,就想這樣:
這個按鈕控制 Scene 視圖 camera 在透視投影和正交投影中切換,它們之間有什么不同?
當使用透視投影時,物體對 camera 呈現近大遠小,就像在真實世界用眼睛觀察中一樣。然而,當使用正交投影時,物體距離 camera 的并距離不影響它的大小。因此在2D模式,一個物體從距離 camera 遠處移動到近處,它的大小不會因為位置而。
接下來的圖片展示出兩種 Sence 視圖的不同,它們都是從相同的位置觀察相同的立方體,上面這幅是使用2D模式,下面的不是。
這個截圖也顯示出2D模式隱藏了讓你改變 camera 透視投影和正交投影的 Scene Gizmo。使用2D模式,上方是y軸正方向,右方是x軸正方向。
Important:開關的設置不影響你游戲最終運行的結果,只是在 Scene 改變 camera 的呈現方式,但它仍然在我們框選物體時非常有用。當你制作2D游戲的時候你可能在兩種模式中來回切換,甚至有時制作3D游戲也需要,但是這個教程的插圖全部都是截取自2D模式。
Question:跟著截圖一步步做感覺還好嗎?你完全可以自己安排Unity的界面布局使你操作更輕松,試試吧。
Sprites,使這一切變得容易
看看下面的動畫就能發現,用Unity的新特性添加 sprite 到場景中的過程極其容易。
步驟 1:拖動 cat.png 從你的文件夾窗口到 Scene 視圖,就想這個演示一樣。
步驟 2:使用你所省下的時間給Unity的開發人員發一份感謝信。
啊!那很棘手!如果你失敗了,不要難過,只要重新閱讀這段教程,再試一次。
Note:想知道為什么動畫下方有兩只貓?不要著急,待我慢慢道來。
依賴Uniyt的默認輸入設置使這個操作變得十分簡單,你不用時常的更正你的圖片設置。無論如何,這說明Unity的新特性使在2D環境工作驚人的輕松!在接下來的教程將覆蓋所有你在Unity2D模式工作的需要知道的知識。
Sprite 資源
在 Hierarchy 選擇 cat,同時目光轉向 Inspector,你的 Inspector 中非常有可能坐標和下面這張截圖不同,但是不用在意它。你要注意的是,Unity為了在 Scene 顯示這只貓,為這個 GameObject 添加了一個 Sprite Render 組件。
同時不易察覺到的是,Unity也創建了一個幾何圖形為這個對象,在Unity免費版中,每個 Sprite 獲得一個簡單的矩形,但Unity專業版為每個 Sprite 創建一個簡易的 mesh 來適應圖片不清晰的像素邊界。注意在Unity專業版中僵尸身上藍色的 mesh。
通過創建一個這樣的 mesh 而不是應用你的 Sprites 作為紋理在一個 quad 上,Unity可以改進 Scene 的渲染效率,意味著他將產生更少的像素,并且當使用Unity專業版的 Sprite Packer 時,它能把這些紋理打包的更緊密。你將在教程的尾部了解它。
Note:別被這突然出現的僵尸嚇著了,我用僵尸當例子只是因為他的 mesh 比貓的更有趣。
你將學習關于 Sprite Render 的屬性貫穿這個教程,但現在,看這個 Sprite 屬性。這里顯示了分配給Sprite Render 的 Sprite 資源的名字,一次只能分配一個,但在后面你會學到如何通過更新這個屬性來實現動畫。
在下面這個圖片中,正如你所見的那樣,這個 cat GameObject 有一個 Sprite 屬性,同時有一個名叫 cat 的資源分配給了這個渲染器。
保持 Prioject 可視,然后點擊 Inspector 中的 Sprite 屬性內部,來定位和高亮這個 Sprite 資源在 Project browser,就像這樣:
Note:這個高亮框在幾秒后漸漸消失,所以如果你沒注意到,就再點一下,當然,我們的的工程中只有這一只貓,你不太可能沒看到。
就像剛才的截圖中的一樣,Unity在 Project browser 中高亮的項目名叫 cat,而且它還有一個子對象也叫 cat。我們有兩只貓?沒錯,可能有點迷惑。我來解釋下:
- 父 cat 是一個紋理資源,它與你的源素材文件一致(cat.png),用來創建 Sprite 從這個素材,你可以看到它的縮略圖。
- 子 cat 是一個當導入 cat.png 時由Unity創建的 Sprite 資源,在我們的例子中,它只有一個,因為Unity僅僅從這個文件創建了一個 Sprite,但是在后面幾章,你將了解到如何從一個圖像文件創建多個 Sprite。
Note:我們清楚Unity渲染的是 Sprite 對象,Sprite 類實際上僅僅包含一個需要被訪問的 Texture2D 對象的信息,就是我們儲存的真正圖像數據。如果你想在運行時刻生成 Sprite,你可以動態創建你自己的 Texture2D 對象,但關于這些的討論將在未來的教程中。
你可以通過從電腦中拖拽素材到你的 Scene 視圖(或者Hierarchy,如果你喜歡)來添加 Sprite。但是通常,將素材添加進工程總是在添加進 Scene之前。
把你下載的剩下的圖片添加到你的工程中:background.png, enemy.png, zombie.png。
通過拖動 Project browser 中的 enemy 到 Hierarchy 來添加一個敵人到你的 Scene 中。
就想貓一樣,Project browser 中有兩個名叫 enemy,但不要緊,隨便拖哪個都行,因為拖動 Sprite asset(子對象)時,總會使用這個 Sprite,而拖動 Texture asset(父對象)時,會使用第一個子對象,在我們現在的情況,其實都一樣。
在 Hierarchy 中選擇 enemy,設置它的 Transform 組件中的 Position 為(2,0,0),如圖。
在你的場景變亂之前,在 Hierarchy 中選擇 cat,設置它的 Postition 為 (0,2,0),如圖。
你的場景現在看起來可能是這樣的。
最后拖動 background 從 project browser 到 Hierarchy,同時設置它的 Position 為(0,0,0),如圖。
我們等會調整底圖的質量,所以先不要在意它現在看起來不是很清晰(悄悄告訴你,添加 background.png 是Unity默認設置不正確的地方之一),你的 Scene 視圖現在看起來是這樣的:
不要被因為你沒在 Sence 視圖中看到貓和老處女而報警。他們只不過被埋在了沙灘下,你很快就會把他們挖出來。在你挖出他們之前,我們要開始分尸!不對,是僵尸的 Sprite,就在那!
切割 Sprite Sheets
你已經導入了 zombie.png 到你的項目,但是這個文件和別的文件不同,它不是只有一只僵尸,它有好幾個僵尸,如圖。
這樣的文件常常被叫做 Sprite Sheet,你會想讓Unity為每個圖中的獨立個體創建一個單獨的 Sprite。
在 Project browser 中展開 zombie,如圖。Unity只創建了一個子對象——一個 Sprite 包含了全部的圖像,這不是我們想要的結果。
好在,Unity提供了解決的辦法,你可以用來對付這種 Sprite Sheet,在 Project browser 中選擇頂層的 zombie 打開 Import Setting 在Inspector。
設置 Sprite Mode 為 Multiple(如圖),點擊 Apply。
選擇這個選項會顯示一個 Sprite Editor 按鈕,同時 Pivot 屬性消失。
因為每個獨立的 Sprite 將在其他地方定義他們各自的 pivot point(軸心點)。
注意 Project browser 這個 zombie 紋理已經沒有了子對象(如下圖),它的右邊也沒有了小箭頭。
在這種狀態下,zombie 紋理是不可用的,如果你嘗試把它拖動到 Hierarchy,會有一個消息告訴它沒有 Sprite。這是因為你需要告訴Unity,你將如何分割這個 sprite sheet。
保持 Project browser 里的 zombie 選中,點擊 Inspector 里的 Sprite Editor 來打開下面的窗口。
這個 Sprite Editor 視圖可以讓你把這個圖片分割為互相獨立的 sprite。點擊窗口左上角的 Slice 按鈕,開始分割 sprite,就如下圖。
Unity可以自動找到你圖片中的 sprite,但你仍可以調整它的結果。現在我們使用默認設置,點擊 Slice。如圖。
Unity使用透明的邊框圈定出圖片中可能存在的每個 sprite,它發現了四個 spites。
經過我的測試,當每個個體直接有明確的空白的時候,Unity的自動分割效果最好。注意Untiy在下面這個圖片中只找到了微笑的表情,但之后的圖片中找到了三個 sprite。
Unity沒有找到所有的 sprite,因為它不能使用沒有交集的邊界框出每個元素
Unity找到了所有的 sprite,因為它能框出每個元素
上面的圖片說明,你應該恰當的安排你的 sprite sheets,它也說明,為什么Mike要這樣畫這張圖。
點擊隨便一個Unity圈出的 sprite 來編輯它的詳細屬性,包括它的名字,坐標,邊界,和軸心點。當選擇了第二個 sprite 時,會出現下面這張圖的樣子。
你可以在這個窗口里修改這些設置,比如直接在圖片上調整邊界,設置軸心點。
通常,在你修改完成后,你要點擊 Sprite Editor 視圖右上角的 Apply 或 Revert 來保存和恢復它。
雖然Unity自動做的很好,但我們不并不想用它自動的配置。這個 zonbie.png 中的每個元素范圍都是等大的矩形,在Unity中有方法可以處理這種情況。
點擊 Sprite Editor 視圖左上角的 Slice 按鈕再次打開分割設置,但是這次,把 Type 設置為 Grid,這時它會變成下圖這樣。
左上角彈出的小視圖中,Pixel size 屬性可以讓你指定網格的大小,X是每個格子的寬度,Y是高度。Unity 將使用這些數值來等距分割你提供的圖片。把X設置為157,Y設置為102。如圖。
點擊 Slice,Unity找到了四個 sprite。
你仍然可以選擇其中的一個就像剛才那樣設置它們的詳細屬性,但目前,這不重要。
點擊 Sprite Editor 右上角的 Apply 按鈕,應用你的操作。注意 Project browser 視圖內 zombie 發什么了什么變化。它現在擁有了四個子對象,分別名叫 zombie_0,zombie_1 等,就像下圖這樣。
雖然 zombie 紋理被分割成為了多個 sprite,但把他們添加進場景的方法沒什么不同,你仍然可以把他們直接拖到 Hierarchy 來創建你的 GameObject。這里告訴你一個新的方法。
通過選擇 GameObject\CreateEmpty 創建一個新的敵人 GameObject。重命名為 zombie,設置 Position 為 (-2,0,0),如圖。
在 Hierarchy 中保持 zombie 選中。點擊 Inspector 中的 Add Component,在出現的菜單中選擇 Rendering,然后選擇 Sprite Render 來添加一個 Sprite Render 組件,如圖。
點擊 Sprite Render 的 sprite 屬性旁的那個小圓圈圖標,打開 Select Sprite 對話框。那個圖標是這樣的:
這個出現的對話框有兩個選項卡,分別是 Assets 和 Scene,分別包括所有你項目中和現在場景中的所有 sprite。
切換到 Assets 分頁,選擇 zombie_0 分配給這個屬性來讓 Sprite Render 組件渲染,如圖。
在場景視圖,你就能看到一個僵尸悠閑的站在沙灘上,此刻,沙灘下的某處埋著老處女和她的貓。哈哈。
所有需要的元素都已經導入場景。是時候來解決一些問題了。
配置你的 Game 視圖
Zombie Conga 的所有素材是為了制作iPhone游戲,意味著它在特殊的分辨率下看起來才會更好。為了適應iPhone的環境,把 Game 視圖的分辨率大小設置為 1136x640。
修改 Game 視圖的寬高比或者分辨率都是使用 Game 視圖的控制條的那個下拉菜單,就是圖中高亮的地方。
點開這個菜單,里面是幾個默認提供的設置,如果里面已經有了 1136x640,選擇它就行了。如果沒有,點擊菜單底部的 + 按鈕,如圖。
創建一個新的分辨率設置,將 Type 設置為 Fixed Resolution,設置寬度和高度分別為1136和640。如圖。
點擊 OK,在菜單中選擇這個新的設置。
你的 Game 視圖現在看起來應該是這樣:
Note:可能你的視圖看起來和這個截圖不是完全一樣,因為Unity重新按照你設置的寬高比調整了視圖的大小,但你仍可以在視圖中看到相同的內容。
顯然,它不是很正確,你在這里已經看到了三個不同問題,你將一一更正它。
首先開始修正第一個問題。
修正你的 Camera 的屬性
在2D游戲中,你通常想使用正交投影而不是透視投影。你在之前的章節已經知道了這兩個 Scene 視圖的屬性,但你可能沒意識到,Unity可能會默認設置你的攝像機為透視投影。
在 Hierarchy 中選擇 Main Camera,然后,在 Camera 的組件中,確保 Projection 已經設置到了 Orthographic。
通過設置它的 Transform 組件的 Position 為(0,0,-10),來將攝像機面朝場景中心垂直放置。你的 Inspector 面板現在應該看起來是這樣:
同時你的 Game 視圖現在看起來應該是這樣:
現在看看,這和使用透視投影的設置看起來沒什么太大的不同。如果 sprite 不會隨著它距離攝像機的距離而改變大小,那要如何放大這個底圖讓它鋪滿整個屏幕呢?你可以試試縮放你的 GameObject,但這里有一個更好的解決辦法——改變攝像機的 Size 到適當的值。
攝像機的 Size 定義了它視野的基本尺寸。這個數字的大小是從視圖中心到頂邊的距離。換句話說,就是視圖高度的一半。而寬度是在運行時由寬高比計算出來的。如圖。
在這個例子中,你想底圖完美填滿整個屏幕從上到下,同時允許水平滾動。底圖的高度是640像素,所以一半就是320像素。這不就是我們要的數值嗎?
還沒完。
在 Project browser 中選擇父 background 來在 Inspector 查看它的 Import Settings。
看這個 Sprite 渲染器的 Pixels to Units 屬性。它現在使用的是默認的100,如圖。
在Unity中,單位不是很重要,相當于屏幕的像素。反而你更經常使用相對大小。可能假設一個單位長度是一米。對于 Sprites,Unity使用 Pixel to Units 來定義除去比例后的大小。
例如,想象導入了一個500像素寬的 Sprite,下面這個表展示了為 Pixels to Units 使用不同的值時候,你的 GameObject 在x軸上渲染出的寬度。
background.png 的高度是640像素,并且它的 Pixel to Unity 屬性的值是100,所以 background 對象在 Hierarchy 將為6.4個單位長度高,然而,這個正交攝像機的 Size 屬性是它視野范圍高度的一半,所以應該把它設置為 background 對象高度的一半,即為 3.2個單位長度。
在 Hierarchy 中選擇 Main Camera,設置 Camera 組件中的 Size 屬性為 3.2,如下圖。
現在,你的背景圖片完美的適應了整個視野,如下圖。
這時,你會發現一些圖像質量上的問題。下面這兩張圖指出了一些地方,對比它們應當顯示的樣子,看看我們的圖片。
我們現在的海灘
期望得到的海灘
上面的圖片顯示的問題是由于底圖紋理的壓縮設置,你可以通過修改這個文件的 Import Setting 來修正它。
修正你的 Import Setting
選擇 Project browser 中的父 background 對象,再次打開它的 Import Setting,但這次,看到 Inspector 底部的 Preview 面板了嗎?
Preview 面板顯示了導入的紋理,連同紋理的大小,顏色,信息,和內存使用量。你可以看下面這個截圖,這個 background 紋理現在的大小是 1024x320 像素,但 background.png 的大小是 2048*640 像素!這說明Unity把原始如圖縮小了一半,為了把他放在 1024*1024 的紋理中。
為了修正你的紋理,看到那個 Import Settings 下方的選擇夾里的 Max Size 和 Fortmat 屬性了嗎?如圖。
Max Size 定義了紋理的最大大小,是一個正方形,它的默認大小是1024像素,同時,Format 指定了色彩深度,它的默認值是 Compressed。
你可以為每種平臺設置不同的值,(例如:IOS,Web,Android),但對于我們這個應用,只用考慮 Default 選項卡就行了。
在 Default 選項卡中,修改 Max Size 為 2048,之后點擊 Apply。你的設置看起來應該是這樣。
立刻,你會注意到 Scene 和 Game 視圖都更棒了,因為 background 壓縮減少了。下面這張圖顯示了 Game 視圖的樣子。
注意在 Inspector 面板的 Preview 區域顯示了這個 background 紋理現在是 0.6MB,之前它是 160KB。
增加紋理的大小使它的內存使用量BMW之前的四倍(大致估計)。
對于有些紋理,你可能想調整它的 Format 值來提高它的色彩質量,但那將進一步增加它的大小。例如,如果你把 background 的 Format 改為 16bit,你會發現紋理的大小增長到了 2.5MB,當改為 Truecolor 時它為 3.8MB。
然而,如果你看下面這兩個版本的 background,你會發現壓縮過的圖片和真彩色的圖片幾乎一樣好。
壓縮過的紋理
真彩色紋理
因為壓縮過的圖片看起來足夠好,而且占用內存少,所以允許 Format 的值為 Compressed。當你自己制作游戲的時候,盡量對這些設置嘗試不同的組合,選擇一個占用內存最少,還能達到你預期效果的設置。
那么,攝像機部署就位,底圖看起來清晰。現在是時候從沙灘挖出那個老處女和她的小貓咪了!
控制渲染順序
你仍然不能看到老處女和貓是因為場景把他們畫在底圖之后,你可以調整游戲對象的Z軸坐標讓它更接近攝像機從而顯示在前面。事實上,這種方法可以完美的解決這個問題。但對于渲染順序的問題,現在Unity里有一個很棒的特性,你應該試試:Sorting Layers。
在 Hierarchy 選擇 cat,可以看到的 Sprite Render 的 Sorting Layer 屬性被設置為 Default。如圖。
點擊 Sorting Layer 的下拉框,你會看到你的項目中定義了一個排序層,我們現在選擇的正是其中的 Default。
你也會看到一個名叫 Add Sorting Layer… 的選項,點擊它。
這會帶你來到 Tags&Layer 編輯器,你可以從Unity的很多地方來到這個地方。只展開 Sorting Layer 的分組,如圖:
點擊 Sorting Layer 分組中的 + 來創建一個新的名叫 Cats 的排序層。同樣的方法,再創建兩個層分別叫做 Enemies 和 Zombie。你的編輯器現在會看起來像這樣:
這些層定義了渲染的順序,名叫 Defalut 的 Layer0 在最底層,名叫 Cat 的 Layer 1,在它之上,以此類推。
目前,所有你添加的游戲對象都是使用的 Default 的排序層。對于 background 對象這沒問題,因為我們就是想它在所有元素后面,但你需要改變其他對象的排序層屬性。
在 Hierarchy 中選擇 cat,設置它的 Sorting Layer 為 Cats,你立刻會注意到那只貓在 Scene 和 Game 視圖都可以看到了。
當貓的排序層被改為 Cat …
…立即就能看到貓了
在 Hierarchy 中選擇 enemy,設置它的 Sorting Layer 為 Enemies。這樣,老處女和她的貓一起在沙灘上散步,誰知道呢,或許他們在度假?
最后在 Hierarchy 中選擇 zombie,設置它的 Sorting Layer 為 Zombie 確保你的游戲對象在頂部,你的 Game 視圖現在會看起來像這樣:
Note:Sprite Renderer 也有一個 Order in Layer,你可以使用它來為游戲對象指定排序順序。
但你不會用到它,因為 Zombie Conga 沒有任何 Z軸的戰斗的問題,看起來Unity是按照被添加進 Scene 中的順序來渲染對象的,所以最新添加的對象總是在最頂層,對象不會在這幀在另一個對象的前面而下一幀又到它后面,這個特性對我們的游戲很有用。
給 Sprite 使用腳本
你已經把這些 sprite 放在沙灘上了,但他們什么都不能做。通過這章,你將編寫兩個小腳本:一個是僵尸擁有的動畫,另一個可以讓玩家控制僵尸移動。你將在這一系列剩下的教程中逐漸完善這個游戲。
Note:你將編寫C#(讀作see-sharp)腳本的代碼,如果你更喜歡 JaveScript,你可以很輕松的轉換過去。如果你需要什么幫助,可以在評論區自由發言。(我從沒用過Unity支持的Boo腳本語言,這都看你喜好)
讓 Sprite 動起來!
首先你要添加一個簡單的僵尸動畫腳本。選擇 Hierarchy 中的 zombie,點擊 Inspector 中的 Add Component,在彈出的菜單中選擇 New Script,將這個腳本命名為 ZombieAnimator,Language 選擇為 CSharp,點擊 Create And Add。操作步驟如圖。
Note:你在這系列教材的第二部分會使用Unity的 Animator 來代替這個基本的動畫腳本。但是這個例子可以讓你了解到如何在腳本中訪問 SpriteRenderer。
使用 MonoDevelop 打開 ZomebieAnimator.cs。這是Untiy自帶的代碼編輯器。打開腳本有好幾種方法,但無論何時,最簡單的是雙擊 ZombieAnimator,或者保持 zombie 選中,在 Inspector 或 Project browser,如圖。
Inspector 中的腳本動畫腳本
Project browser 中的腳本動畫腳本
在 Zombie Conga 中你的僵尸只是簡單愚蠢的走路,就像你想象中的好僵尸。為了實現這個簡單的動畫,你需要一個 Sprite 數組,和一個循環播放它的速度。為了儲存這些信息,給 ZombieAnimator 添加下面這兩個共有變量。
public Sprite[] sprites; public float framesPerSecond;Note:在C#中,你可以把這些代碼放置在類定義的花括號之內,并且在函數定義的外部的任何地方,技術上沒有問題。但通常良好的做法是放置類定義中第一個函數之前。
Public 變量會暴露在Unity的編輯器中,你可以使用Unity的操作界面直接修改它的值而不用修改代碼,甚至運行的時候也是。你等下會知道這是多么容易。
你將通過設置不同的 Sprite 給你的 GameObject 的 SpriteRenderer 組件制作一個動畫。為了代替在每次 Update里獲取 Component,你將在腳本第一次運行的時候緩存它。
添加這樣一個私有變量給你的 ZombieAnimator 腳本:
private SpriteRenderer spriteRenderer;私有變量不會暴露在Unity的編輯器中,在這個例子中,你要初始化這個變量,添加下面的代碼到你的 Start 函數。
spriteRenderer = renderer as SpriteRenderer;你的腳本繼承自 MonoBehaviour,它會讓你能夠訪問一個名叫 renderer 的變量。對于顯示的 GamObject,renderer 就是 SpriteRenderer 組件。因此在給變量賦值之前你需要把 renderer 類型轉換到 SpriteRenderer。
Note:為了更佳的游戲性能,這些優化是非常有必要的。緩存一些頻繁使用的對象是最常用到的優化方法。常見的例子是 GameObject 的 Transform,場景的 Main Camera,或者別的什么,其他的使用 GameObject.Find 來訪問。保持一切簡單明了,這是教程中你唯一緩存對象的地方。這種情況下,這樣做是有意義的。
為了完成這個腳本,添加這幾行代碼到 Updata:
int index = (int)(Time.timeSinceLevelLoad * framesPerSecond); index = index % sprites.Length; spriteRenderer.sprite = sprites[ index ];它使用自從本關開始到目前為止的秒數(更多信息請查閱 Time 的類文檔)乘上每秒渲染的幀數,如果這些幀儲存在一個無限長的數組中,那你會得到現在需要顯示的幀的索引。
但沒那么美好,因為你知道數組不可能是無限的,你需要在到達末尾的時候回到數組的開始,執行求余操作,得到兩個整數相除的余數。
換句話說,你得到的所有數值都在0到比數組長度小1的范圍內,那會是一個 Sprite 數組的有效索引(當然假設數組的長度不為0)。
你在 MonoDevelop 中寫完后,保存腳本(File\Save)回到Unity中。
Note:Unity會自動編譯你的腳本,如果在 Console 中有什么錯誤,先改正它再繼續。
在 Hierarchy 中選擇 zombie,留心它的 Zombie Animator(Script) 組件,那個區域展示了你的兩個共有變量。謝謝,Unity!
現在,Sprite 數組(Unity使用在詞之間添加了空格的變量名)沒有項目。你的 Sprite 資源名叫 zombie_0 到 zombie_3。這些是打算按順序設置的圖片,所以需要它們放到 Sprite 數組里來制作一個永遠循環的動畫。
為了定義這個循環的動畫,你需要添加下面這六個元素到 Sprite 數組:zombie_0,zombie_1,zombie_2,zombie_3,zombie_2,zombie_1。有幾種不同的方式來實現,看你喜歡哪個。
保持 Hierarchy 中的 zombie 選中,點擊 Inspector 右上角的 lock 按鈕,鎖定這個視圖。如圖。
即便你選擇了其他的對象,都會保持顯示現在的 Inspector 信息。在這種情況下,這是個十分有用的功能。
在 Project browser 中展開你的 zombie 紋理,左鍵點擊 zombie_0 來選中它,然后 shift+左鍵點擊 zombie_3,就能選擇四個僵尸 Sprite。
現在拖動你選中的對象到 Inspector,懸浮在 Zombie Animator(Script) 組件的 Sprites 那一行,當你鼠標移動到正確位置的時候,你會看到你的光標下方出現了一個綠色的添加圖標。如圖。
釋放鼠標,Unity會自動添加這些對象到你的數組里。
Note:拖放的時候無論 Sprites 是否展開都不要緊,上面的截圖僅僅演示了展開狀態,因為Unity會自動在拖放時展開你鼠標懸浮位置的項目。如果這個時候截屏的話,就會像我這樣。
你的 Zombie Animator(Script) 組件現在看起來是這樣。
現在只選擇 Project browser 中的 zombie_2,用相同的方法添加到數組里,Unity會自動修改 Sprite 數組的大小來放入你新加入的元素。
再一次添加 zombie_1,你的數組現在就有6個順序正確的元素了,就像這樣:
在你結束這些操作的時候,記得再次點擊 Inspector 視圖右上角的按鈕來解鎖 Inspector 視圖。
如果你忘記怎么做了,之后你可能會為Unity為什么不自動跟隨你選擇的對象切換 Inspector 的信息而摔杯子。
最后,把 Frames Per Second 設置為 10,如圖這樣:
把游戲跑起來,現在對著這個拖著腳走的僵尸驚訝去吧。
Note:在游戲運行的時候,你可以調節 Frames Per Second 屬性來找到一個你喜歡的速度,但是Unity會在你停止游戲的時候恢復這些數值。因此,你需要記住你喜歡的數值,然后在游戲停止的狀態下修改它。
現在,你已經使這個僵尸動了起來(或者說這是復活術?)。它看起來正要去一個聚會,下一章將帶你創建一個簡單的腳本,你可以為他指出正確的方向。
控制這只僵尸
在 Hierarchy 選擇 zombie,為它添加一個新的名叫 ZombieController 的C#腳本。就像剛才你添加 ZombieAnimator腳本一樣。
你是喜歡緩緩移動的僵尸還是奔跑的?都沒問題,如果想在游戲運行中調節僵尸的移動速度,就需要定義一個共有變量在這個腳本中。
在 MonoDevelop 中打開 ZombieController.cs,添加這個變量。
public float moveSpeed;moveSpeed 會儲存僵尸每秒移動的長度,不是像素,是Unity中的單位。因為你的 Sprite 大小是1單位/100像素,你可能想把這個數值設置的相當低。
正如你在動畫中所見的,你將制作一個僵尸在 Zombie Conga 游戲中直線移動。始終走向鼠標最新點擊的位置。(或者是當玩家按住鼠標鍵時候鼠標最新的位置)
僵尸走向你鼠標點擊的方向,然后走過。“這里,僵尸!不,是這里!”
僵尸跟隨鼠標就像它被拖著。
“哪只小僵尸想吃一口美味的光標?你!沒錯,就是你!”
你可能不會在每一幀都有一個鼠標的輸入事件,所以你需要在目的地改變的時候保存僵尸前進的方向。為了實現這個,你要計算一個單位向量(一個長度為1的向量)從僵尸指向輸入的坐標。
添加下面的變量到 ZombieController:
private Vector3 moveDirection;你正在制作的2D游戲,但要知道Unity仍然工作在三維坐標系系統中。比如 Transorm 儲存的 Vector3 的類型。因為你知道僵尸永遠不會在z軸上運動,所以你可以在這里使用 Vector2。但你的僵尸運動方向是 Vector3 類型的,你不得不在這兩個類型之間不斷轉換。這全看個人喜好。
添加下面的代碼到 Update,為了在所有受到輸入事件的時候更新 moveDirection。
// 1 Vector3 currentPosition = transform.position; // 2 if( Input.GetButton("Fire1") ) {// 3Vector3 moveToward = Camera.main.ScreenToWorldPoint( Input.mousePosition );// 4moveDirection = moveToward - currentPosition;moveDirection.z = 0; moveDirection.Normalize(); }這些代碼主要實現了這幾個功能:
Note:你使用 Input 通用類的方法去獲取信息。工程默認中定義了很多輸入方式,叫做 axes,比如 Horizontal,Vertical,和 Jump.Horizontal 用來監視搖桿的x坐標。同樣包括鍵盤上左右光標鍵的狀態,如果你想知道游戲受到的水平移動信息,只要簡單的訪問 Horizontal 軸就可以,不用關心它的輸入源(鍵盤/手柄/搖桿)。
默認定義的 Fire1 是虛擬按鈕之一,它監視了鼠標或搖桿上的0號按鈕以及鍵盤上的左crtl鍵。當指定鍵被按下的時候 Input.Getbutton 返回 true。所以你寫的代碼在每一幀中在按鈕按下的時候更新 moveDirection(不只是最初按下,包括按住),是的,這也說明只要你控制好鼠標,你可以通過按下左ctrl鍵改變僵尸的方向。
如果你想查看或者定制你工程的輸入設置,你可以點擊 Edit\Project Setting\Input,在 Inspector 中打開 InputManager 的設置。
現在在 Update 中添加這些代碼讓僵尸走起來吧!
Vector3 target = moveDirection * moveSpeed + currentPosition; transform.position = Vector3.Lerp( currentPosition, target, Time.deltaTime );第一行計算出了使用設定速度離開現在位置的目的位置。目標位置就是從現在的位置開始運動一秒后的位置。
第二行使用了 Vector3.Lerp 來定義僵尸的在現在位置到目標位置之間的新位置。Lerp 是一個在兩個三維坐標之間插值的簡單方法。Lerp 中的第三個參數是一個0到1的值,是全程的百分比,意思是當這個值為0的時候,會返回 currentPosition,當它為1的時候,會返回 target,而當它為0.5時候會返回中點坐標。
在這個例子中,我們使用 Time.deltaTime 作為第三個參數,因為這是一秒的一小部分,肯定遠遠小于1。它會給你一些路徑上的點,因為 Time.deltaTime 接近1,這樣做所以僵尸會永遠平穩的走下去。
保持腳本,返回Unity。
運行游戲,隨便點擊一個地方讓僵尸走去。如果僵尸沒動,是因為 ZombieController 腳本的 moveSpeed 還沒設置,所以僵尸的移動速度是0!
游戲運行的時候,在 Hierarchy 中選中 zombie 在 Inspector 面板中找到 Zonmie Controller(Script) 組件,把 Move Speed 設置為2,點擊沙灘,你的僵尸就上路了!
在 Inspector 面板調整到你喜歡的速度,根據你調整的速度,你也要調整一下 Zombie Animator(Script) 腳本組件中的 Frames Per Second,不然僵尸的動作會和速度不匹配。
當你嘗試出你希望的值的時候,記住他們。停止游戲,再次重新在 Inspector 中修改好,這樣下次運行就會如你所愿了。
當你快樂的牽著它到處游蕩的時候,你可能會發現僵尸身上的幾個問題。
你將在這系列的未來篇目修正它走出屏幕的問題,所以現在不要管它。如果它走出了屏幕,簡單的再點一下沙灘,把它牽回來就行了。僵尸很聽話的。
在 MonoDevelop 中回到 ZombieController.cs。
這個腳本在移動僵尸的時候使用了 moveDirection,但你只在輸入事件里改變了它的值。為了控制僵尸的方向,你需要在游戲開始的時候初始化 moveDirection 指向它的右邊。
添加下面這一行到 Start:
moveDirection = Vector3.right;這會指向x軸的正方向,換句話說,會指向屏幕右端。
保存 ZombieController.cs,再次運行你的游戲,現在僵尸直接就開始走了,它的也面朝它走的方向,所以它沒絆倒。
返回 ZombieController.cs,添加一個公有變量,以便你可以控制僵尸的轉向的速度。
public float turnSpeed;你會使用 trunSpeed 來控制僵尸轉到新的方向的速度。
Unity內部使用 quaternion 來代表旋轉,如果你對它數學上的定義感興趣,可以看看這。在你理清了你的思維后,放輕松,制作2D游戲你不需要知道多少關于 quaternion 的知識。
因為 Quaternion.Euler 方法可以讓你從歐拉角創建一個 Quaternion 對象。大多數人都習慣使用的就是歐拉角,包括獨立的旋轉的x,y,z軸,但它不適合在3D環境下使用,因為它會產生一些問題,比如萬向節死鎖。歐拉角只適用于你只想沿著z軸旋轉的2D游戲,
Note:想學習有關 Quaternion 的知識,可以去OpenGL ES Transformations with Gestures教程。
添加下面的代碼到 Updata:
float targetAngle = Mathf.Atan2(moveDirection.y, moveDirection.x) * Mathf.Rad2Deg; transform.rotation = Quaternion.Slerp( transform.rotation, Quaternion.Euler( 0, 0, targetAngle ), turnSpeed * Time.deltaTime );首先使用 Mathf.Atan2 來確定x軸與 moveDirection 之間的角度。Mathf.Atan2 返回一個弧度制的角,所以你通過乘以 Mathf.Rad2Deg 來轉換它。
使用 Quaternion.Slerp 來平滑的轉到目標的角。Quaternion.Slep 可以在你指定的兩個角之間進行球面線性插值。這和你剛才看到的 Vector3.Lerp 很像,只是用旋轉信息代替了坐標信息。
之前,當你使用 Vector3.Lerp 的時候,你使用了 moveSpeed 來調節僵尸移動的速度,這次,我們使用 trunSpeed 做相似的事情。這個值越大,僵尸轉到目標地點越快。
Note:肯定會有一部分讀者說,“啊!我想讓僵尸在轉向的時候使用最短的路線,就算我數學爛的像一坨屎,也可以肯定只用反正切是無法做到的,你在騙我!”
對于這些問題,我建議你先冷靜下來做一套廣播體操并且在飲食中多吃些蔬菜。我要告訴你 Quarternion.Slerp 很強大,它總是會在兩個角之間使用最近的路線來內插值。
現在保存 ZombieController.cs,回到Unity。
在 Hierarchy 中選擇 zombie,設置 Turn Speed 為 5,如圖。
運行游戲,無論你多么辛苦的在沙灘上點擊,僵尸都不會感到眩暈。
這就是你在本節教程中制作的 Zombie Conga。通過點擊 File\Save Scene as… 保存你的 Scene,就把它叫做 CongaScene吧,點擊保存。
下一章會講述Unity2D專業版中一些很有用的特性。對于我們制作 Zombie Conga 不是非常重要,但你可能會想了解它——Sprite Packing。
Sprite Packing – For Professionals Only (Sort of)
譯者:這章內容是關于打包 Sprite 紋理的一些描述,因為我使用的仍然是無需付費的Unity版本,這段的翻譯就放下了。有興趣的同學請去原文閱讀。
至此,何去何從?
我希望你能喜歡這套Unity 4.3 2D 教程,如果你不喜歡,我希望你最少能學到點東西。如果你什么都沒學到,可能你想和我們接觸一下,或者給我們一些建議。
你可以從這里下載完整的工程。
現在雖然 Zombie Conga 還沒完成,事實上你已經充分了解了如何編寫一個2D游戲,去第二部分學習如何使用Unity的內建動畫系統吧。在這系列的第三部分,你會有很多創建動畫剪輯的練習,你也會學到如何回放這些動畫,或者給它們之間添加過渡效果。在本系列最后一章,你將完成 Zombie Conga,同時了解Unity2D的物理引擎和更多的腳本。
當你學習Unity2D工具的時候,記得Unity的網站上有豐富的資源供你去探索,包括:
- 詳細高質量的文檔。
- 視頻教程。大多數不是關于2D的,但是他們最近在添加一個新的 2D章節。
- 培訓課程。幾乎每周都有,也有很多過去的課程存檔。
- 一個活躍的交流社區。
和往常一樣,你可以在評論區暢所欲言!
轉載于:https://www.cnblogs.com/wangzexi/p/3870423.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的Unity 4.3 2D 教程:新手上路的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 龙眼为什么叫龙眼 揭秘龙眼的命名由来?
- 下一篇: Android 图片合成:添加蒙板效果