【Unity3D】二、制作滾球游戲學習Unity3D(上)

從創建項目開始

創建一個項目

打開unity,在Projects中可以查看當前的本地項目或者云端項目,點擊New project或者右上角的New都可以新建項目。


創建一個項目

然后在1處填寫創建項目的名稱,2處選擇創建地址,3處選擇Template(模板),可以選中3D或者2D。


創建一個項目

稍等片刻即可進入unity的主頁面。

保存Scene并管理Assets

進入unity之后,可以看到已經預設的SampleScene和其中的Main Camera(主攝像機)和Directional Light(平行光)組件,如果你不喜歡這些預設的名字,直接點擊修改并使用Ctrl+S保存你的修改即可。


保存Scene

為了使我們的Assets文件夾管理地更加井井有條,推薦對不同的assets進行分文件夾管理,這時一些文件夾的命名可以自己定義,但通常可以遵循一定的不成文的規定,比如通常將場景存放在Scenes目錄、將腳本存放在Scripts目錄等等,要根據自己來管理好Assets目錄,以后對于大量的assets可以很方便快捷。

創建游戲場景

創建Plane

可以使用unity的內置GameObject的Plane(平面)類型來作為游戲場景的“地面”。
可以在Hierarchy視窗下右鍵選擇3D Object下找到Plane創建,也可以在頂部菜單欄的GameObject下的3D Object下找到Plane創建。當然也可以看到unity為我們創建了很多預置的Game Object,比如3DO bject、2D Object、Effects、Light、Audio、 Video、UI、Camera等等,當然每一個分類下還有更詳細的分類,這些都可以直接拿來使用,非常方便,一些重要的Game Object以后還會慢慢使用。


新建GameObject的Plane

這里只需要創建一個Plane并將其命名為Ground來作為我們游戲的“地面”,可以看到Plane出現在了MainScene中,同時我們可以注意到Hierarchy視窗中的MainScene右上角出現了一個*號,這就表示該Scene處于待保存的狀態,可以通過菜單欄的File->Save或者快捷鍵Ctrl+S保存Scene。


待保存的Scene

選中剛剛創建的Ground,Inspector視窗中就會出現其所有的Components,這些都是預先被untiy設置給Plane的,點擊Transform這一Component的右側的齒輪狀圖標,可以選擇Reset(重置)選項,這樣,剛剛創建的Plane的Transform就會被重置為初始值,它的Position會被設置為(0,0,0),這是整個游戲世界的原點坐標,游戲中的所有GameObject的坐標都是基于此原點進行計算的。
初始化Transform

選中任何一個GameObject,比如選中Ground,然后按F鍵,或者在菜單欄中點擊Edit->Frame Select可以快速地調整Scene的角度,讓我們有一個非常合適的角度來觀察Ground的全貌。

改變Transform

改變Transform的三組值的方法有很多。

直接賦值

可以在Inspector面板中對Transform的九個值直接輸入數值來設置


在Inspector面板中設置Transform的值

拖動輸入框調節

當我們把鼠標指向每一個值的輸入框的左側邊界時,就會發現鼠標成為了一個左右雙箭頭的形狀,此時按下鼠標左鍵所有拖動,就會發現該輸入框變成了藍色,并可以隨著拖動改變它的值。


拖動輸入框

在Scene窗口中改變

在左上方有六個按鈕,分別表示對Scene中GameObject的操作。
這里提一句:不管選中六個按鈕中的哪一個,只要按住Alt鍵在Scene中拖動鼠標就可以轉動視角,只要滾動鼠標滾輪即可放大/縮小視角。
這六個按鈕從左到右依次為:


六個改變Scene中GameObject的選項
  • 第一個:拖動Scene的視角
  • 第二個:選中后,再選中Scene中的任何一個GameObject,就可以通過拖動它的三個方向箭頭(x、y、z)以及三個平面(xy平面、xz平面、yz平面)來改變Position的值。


    改變Position
  • 第三個:選中后可以在Scene中對選中的GameObject改變其Rotation的值


    改變Rotation
  • 第四個:選中后在Scene中可以對選中的GameObject進行三個方向的Scale的調整


    改變Scale
  • 第五個:選中后可以在Scene中對選中的GameObject進行頂點的位置調整從而改變Scale的值


    改變Scale
  • 第六個:選中后可以同時改變Position、Rotation、Scale的值,是第二三四個的結合。


    同時改變所有的Transform

創建游戲對象

創建Sphere

接下來創建小球,同樣地,在MainScene下右鍵->3D Object->Sphere來創建一個unity預置的Sphere(球體),命名為Player,并通過reset其Transform來使其位置重置到原點。


新建一個Sphere

這樣我們看到小球的中心已經被定位到了(0,0,0)處,為了讓小球能在平面上滾動,我們需要將小球放到平面上。
觀察小球的Transform我們可以得到,它的Scale的值為(1,1,1),也就是說它的三個方向的大小都為1單位,為了讓小球放到平面上邊,顯然我們需要將其向上移動半個球的距離,即將Position的Y值設置為0.5,小球就剛好在平面上了。


將小球放到平面上

關于光源

其實我們可以看到小球是有影子的,這是最開始unity為我們準備的Directional Light作用的結果,我們可以看到Scene中的一個小太陽的標志,這個就是我們的光源,使用Directional Light來模擬太陽的平行光。它的Transform則顯示了光源的位置、角度(也就是平行光的照射方向),如果我們將這個GameObject去掉的話就沒有了光的效果。
當然通過改變Rotation的值就可以調節光源的方向,比如為了效果我將Rotation的Y值改為60。


關閉光源后的效果

創建Material

為了使GameObject美觀,我們通常會對其表面進行一系列裝飾,而其表面的表現是通過為這個GameObject添加Material(材料)來實現的。
接下來為我們的Ground和Player添加最簡單材料:純顏色。
在Assets下新建Materials目錄用于管理各種材料,然后右鍵該目錄選擇Create->Material新建一個材料命名為Background。


新建一個Material

選中Background,就可以看到它的Inspector面板了,我們在Albedo(反射率)一欄中可以選擇一種顏色,在下方的預覽中就可以看到效果了,這里我們選擇RGB色(0,32,64)作為我們的Background的顏色。


為Material選擇顏色

想要將創建的Material運用在某個GameObject上,很簡單,只需要拖動該Material到Scene中的目標GameObject上或者拖動到Hierarchy的該GameObject上即可。
將Material運用到Scene中

可以看到我們的Ground已經變成了藍色
成功改變Plane的顏色

讓小球滾動起來

讓小球擁有成為剛體

為了讓小球有滾動的效果,我們需要小球擁有一系列的物理屬性,物理屬性已經由unity內置,我們只需為需要增加物理屬性的GameObject添加一個Rigidbody的Component即可。如上一節中所示,選中Player,在Inspector面板中通過Add Component中找到Physics下的Rigidbody即可。


添加Rigidbody屬性

為小球添加控制腳本

有了剛體屬性的小球需要在我們的控制下滾動,比如我們規定使用W,S,A,D四個按鍵來控制小球的方向,那么對于一個有物理屬性的剛體來說,為了能夠動起來,當然需要力(Force)作用在物體上,這些有關于如何控制GameObject的方法需要我們使用腳本(Scripts)來完成,假如你已經擁有了一定的C#編程基礎。
同樣我們在Assets下創建Scripts目錄來管理腳本,在該目錄處右鍵->Create->C# Script創建一個腳本,這里我們命名為PlayerController。


新建腳本

為了讓我們創建的腳本與Player聯系起來,可以在Player的Inspector面板下選擇Add Component,在其中搜索我們的腳本名字就可以找到該腳本,根據unity的命名規范,喜歡將腳本各個單詞使用“駝峰法”并且首字母同樣大寫的方式,有趣的是,unity對于這些腳本通常都會在每個大寫字母處將這些單詞分開,我也不知道為什么。簡單點兒的話可以直接將Assets中的腳本拖到Inspector面板下,就可以添加成功。


將腳本添加給GameObject

打開腳本

編輯腳本需要編輯器,Visual Studio是較好的選擇,它和unity之間有很好的合作關系,使用起來也很方便。雙擊腳本文件或者在Inspector面板中點擊腳本的右上角的齒輪圖標選擇Edit Scrpit都可以打開編輯器對其進行編輯。


Unity的預置腳本內容

unity已經為我們預置好了腳本的最基本結構,最基本的,我們可以看到所有的unity腳本都繼承自MonoBehaviour類,然后有兩個預設函數,Start函數是在第一幀開始渲染前調用,Update函數在每一幀刷新前調用,都是非常常用的函數。
接下來思考我們要做的事情,我們需要檢測用戶的輸入,并且通過輸入的按鍵來控制小球的滾動方向,檢測用戶的輸入同時也需要識別輸入的是哪一個按鍵,除此之外我們還需要一些物理學有關的邏輯,比如我們需要添加一個力來控制小球的移動,這就是物理學邏輯,這些邏輯當然是每一幀都要進行一次,所以我們需要將這些邏輯寫在每一幀更新都要執行的函數中。
顯然我們可以寫到Update函數下,因為Update函數是每一幀刷新前都會調用的,同時我們還有另外的選擇,即使用FixedUpdate函數,它在每一次進行物理學運算的時候調用,每次檢測到用戶輸入都需要進行物理學運算,所以我們可以將邏輯寫到FixedUpdate函數下。

開始編寫腳本

首先我們需要創建一個對于這個Player小球的引用,這樣才能知道我們控制的是哪個小球,這里小球是剛體,所以我們創建一個剛體(Rigidbody)的引用,并且需要在第一幀開始渲染之前通過GetComponent方法來找到小球創建剛體的引用,這一邏輯自然就需要寫到Start函數中了。

private Rigidbody rigidbodyPlayer;

void Start()
{
    rigidbodyPlayer = GetComponent<Rigidbody>();
}

接下來對用戶輸入的讀取就需要寫到FiexedUpdate函數中了,我們使用Input類的GetAxis方法來獲取水平或者垂直的運動軸,這個方法會返回一個float值作為該軸的移動距離。

float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");

通過以上兩行代碼我們就可以將用戶的W,S,A,D輸入轉化為水平軸和垂直軸的移動距離,分別存儲在moveHorizontal和moveVertical兩個float類型的變量中。

接下來通過Rigidbody類的AddForce方法可以為剛體添加作用力,AddForce方法接受一個三維向量(Vector3)參數,這個三維向量就可以表示力,顯然我們的三維向量可以用剛才的moveHorizontal和moveVertical兩個變量作為X值和Z值,同時我們是不需要小球在Y方向上移動的,也就是將Y方向的力作用設置為0.0f即可,經過調試我們會發現小球的移動速度過慢,為了方便調節小球的速度,只需要在表示力的三維向量前乘以一個倍數即可,為了方便調整,我們設置一個public的float類型的變量speed來調節這個乘積。
這里必須說明的是,凡在unity的腳本中被聲明為public類型的變量,在unity的Inspector界面中的該腳本的Component下都會出現一個可以設置的值的方框。

public float speed;
void FixedUpdate()
{
    Vector3 movement = new Vector3(moveHorizontal,0.0f,moveVertical);
    rigidbodyPlayer.AddForce(movement*speed);
}
更改public的Speed的值

此處我們將speed的值設為10比較合理,運行游戲就會發現通過W,S,A,D的控制,小球動了起來。


讓小球滾動起來

完整的代碼:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    private Rigidbody rigidbodyPlayer;
    public float speed;

    void Start()
    {
        rigidbodyPlayer = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
        float moveHorizontal = Input.GetAxis("Horizontal");
        float moveVertical = Input.GetAxis("Vertical");

        Vector3 movement = new Vector3(moveHorizontal,0.0f,moveVertical);

        rigidbodyPlayer.AddForce(movement*speed);
    }
}

當然你也會發現,小球超出了Plane的邊界居然掉了下去,其實這是合理的,因為小球為剛體,也就擁有物理引擎,當然受到重力的影響,在沒有Plane的向上的作用力的情況下自然會下落。

設置攝像機

可以發現,我們的Camera的角度和位置都比較刁鉆,這導致我們的游戲看到的畫面并不完整,接下來我們對Camera進行設置,使其能夠跟隨我們的小球滾動來同時移動。
首先調節Main Camera的Position和Rotation使得畫面和角度比較合適,比如這里將Position的Y值設為6,Z值設為-6,將Rotation的X值設為45得到了一個較為合適的位置。


改變攝像機的Transform

接下來通過腳本控制Main Camera跟隨小球Player一同移動,即在Position上保持相對靜止。
可能你會想到,只需要將Main Camera拖動給Player使其成為Player的子物體不就可以保持兩者相對位置不變化了嗎?但是問題在于球體Player是滾動的,如果兩者的位置完全相對靜止,就會導致球滾動時Main Cmaera也會跟著球滾動,有一種天旋地轉的感覺。感興趣的話可以嘗試一下。
新建腳本CameraController并添加給Main Camera做一個Component。為了使Main Camera的Transform的Position和Player的保持相對靜止,Rotation并不和其保持一致,可以想到一個辦法:設置一個偏移量,這個值初始化為游戲開始時Main Camera和Player之間的Position的差值,然后在球滾動時,每一次滾動都改變Main Cmaera的Position,使其新的Position等于現在球的Position的值加上剛才的偏移量,這樣就會在每次球的位置改變時Main Camera都會跟上它的步驟。
顯然,偏移量的設置需要在Start函數中完成,每一次球的位置發生變化時的邏輯可以在Update函數中完成,但還有一個更好的選擇,就是LateUpdate函數,該函數在每次有GameObject發生變動時才會調用。
同時,我們的腳本使加在Main Camera上的,所以Main Camera的Transform可以直接調用,但是球的Transform則需要單獨獲取,這里我們設置一個public的GameObject量,然后在unity中將球Player拖動到這個量處作為參數即可。

private Vector3 offset;
public GameObject player;

void Start()
{
    offset = transform.position - player.transform.position;
}

void LateUpdate()
{
    transform.position = player.transform.position + offset;
}
添加Player實例

這時候運行游戲就可以發現Main Camera的位置隨著球的改變而發生了改變。


MainCamera成功跟隨小球變化位置

完整的代碼:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraController : MonoBehaviour
{
    private Vector3 offset;
    public GameObject player;

    void Start()
    {
        offset = transform.position - player.transform.position;
    }

    void LateUpdate()
    {
        transform.position = player.transform.position + offset;
    }
}

建立圍墻

為了不讓小球總是滾落到Plane之外,可以在其四周圍建立起一圈兒圍墻,很簡單,使用預設的Cube就可以了。
為了更好的管理四個圍墻,我們可以先創建一個空的GameObject,將其命名為Walls,Reset使其重置位置,然后在其上右鍵新建一個Cube,并命名為WestWall,這樣這個Cube就成為了Walls的子物體。


新建Cube

接下來如何調整這面墻的大小、位置就很簡單了,可以在Inspector中直接輸入具體數值,也可以直接在Scene中拖動和縮放,最好我們可以得到這個墻體結構。


改變Cube的Transform

為了簡單方便,只要選中WestWall,在菜單欄的Edit中選擇Duplicate(復制)(快捷鍵:Ctrl+D)即可,然后將復制好的墻拖動到適合的地點,在復制,最后可以得到四面墻。
復制Cube建立圍墻

接下來測試游戲,墻起作用了!
圍墻正常運行

下一篇文章:http://www.lxweimin.com/p/7e0e85092e5a

參考資料:https://unity3d.com/learn/tutorials/s/roll-ball-tutorial
本節內容的完整官方教程視頻分享(英文無字幕):https://pan.baidu.com/s/1TNMMFjs7pZqLPhGQZ1tPqQ 提取碼:1u70


轉載請注明出處,本文永久更新鏈接:https://blogs.littlegenius.xin/2019/02/10/從滾球游戲初步體驗Unity3D/

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內容