從創(chuàng)建項(xiàng)目開始
創(chuàng)建一個(gè)項(xiàng)目
打開unity,在Projects中可以查看當(dāng)前的本地項(xiàng)目或者云端項(xiàng)目,點(diǎn)擊New project或者右上角的New都可以新建項(xiàng)目。

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

稍等片刻即可進(jìn)入unity的主頁(yè)面。
保存Scene并管理Assets
進(jìn)入unity之后,可以看到已經(jīng)預(yù)設(shè)的SampleScene和其中的Main Camera(主攝像機(jī))和Directional Light(平行光)組件,如果你不喜歡這些預(yù)設(shè)的名字,直接點(diǎn)擊修改并使用Ctrl+S保存你的修改即可。

為了使我們的Assets文件夾管理地更加井井有條,推薦對(duì)不同的assets進(jìn)行分文件夾管理,這時(shí)一些文件夾的命名可以自己定義,但通??梢宰裱欢ǖ牟怀晌牡囊?guī)定,比如通常將場(chǎng)景存放在Scenes目錄、將腳本存放在Scripts目錄等等,要根據(jù)自己來(lái)管理好Assets目錄,以后對(duì)于大量的assets可以很方便快捷。
創(chuàng)建游戲場(chǎng)景
創(chuàng)建Plane
可以使用unity的內(nèi)置GameObject的Plane(平面)類型來(lái)作為游戲場(chǎng)景的“地面”。
可以在Hierarchy視窗下右鍵選擇3D Object下找到Plane創(chuàng)建,也可以在頂部菜單欄的GameObject下的3D Object下找到Plane創(chuàng)建。當(dāng)然也可以看到unity為我們創(chuàng)建了很多預(yù)置的Game Object,比如3DO bject、2D Object、Effects、Light、Audio、 Video、UI、Camera等等,當(dāng)然每一個(gè)分類下還有更詳細(xì)的分類,這些都可以直接拿來(lái)使用,非常方便,一些重要的Game Object以后還會(huì)慢慢使用。

這里只需要?jiǎng)?chuàng)建一個(gè)Plane并將其命名為Ground來(lái)作為我們游戲的“地面”,可以看到Plane出現(xiàn)在了MainScene中,同時(shí)我們可以注意到Hierarchy視窗中的MainScene右上角出現(xiàn)了一個(gè)*號(hào),這就表示該Scene處于待保存的狀態(tài),可以通過(guò)菜單欄的File->Save或者快捷鍵Ctrl+S保存Scene。

選中剛剛創(chuàng)建的Ground,Inspector視窗中就會(huì)出現(xiàn)其所有的Components,這些都是預(yù)先被untiy設(shè)置給Plane的,點(diǎn)擊Transform這一Component的右側(cè)的齒輪狀圖標(biāo),可以選擇Reset(重置)選項(xiàng),這樣,剛剛創(chuàng)建的Plane的Transform就會(huì)被重置為初始值,它的Position會(huì)被設(shè)置為(0,0,0),這是整個(gè)游戲世界的原點(diǎn)坐標(biāo),游戲中的所有GameObject的坐標(biāo)都是基于此原點(diǎn)進(jìn)行計(jì)算的。

選中任何一個(gè)GameObject,比如選中Ground,然后按F鍵,或者在菜單欄中點(diǎn)擊Edit->Frame Select可以快速地調(diào)整Scene的角度,讓我們有一個(gè)非常合適的角度來(lái)觀察Ground的全貌。
改變Transform
改變Transform的三組值的方法有很多。
直接賦值
可以在Inspector面板中對(duì)Transform的九個(gè)值直接輸入數(shù)值來(lái)設(shè)置

拖動(dòng)輸入框調(diào)節(jié)
當(dāng)我們把鼠標(biāo)指向每一個(gè)值的輸入框的左側(cè)邊界時(shí),就會(huì)發(fā)現(xiàn)鼠標(biāo)成為了一個(gè)左右雙箭頭的形狀,此時(shí)按下鼠標(biāo)左鍵所有拖動(dòng),就會(huì)發(fā)現(xiàn)該輸入框變成了藍(lán)色,并可以隨著拖動(dòng)改變它的值。

在Scene窗口中改變
在左上方有六個(gè)按鈕,分別表示對(duì)Scene中GameObject的操作。
這里提一句:不管選中六個(gè)按鈕中的哪一個(gè),只要按住Alt鍵在Scene中拖動(dòng)鼠標(biāo)就可以轉(zhuǎn)動(dòng)視角,只要滾動(dòng)鼠標(biāo)滾輪即可放大/縮小視角。
這六個(gè)按鈕從左到右依次為:

- 第一個(gè):拖動(dòng)Scene的視角
-
第二個(gè):選中后,再選中Scene中的任何一個(gè)GameObject,就可以通過(guò)拖動(dòng)它的三個(gè)方向箭頭(x、y、z)以及三個(gè)平面(xy平面、xz平面、yz平面)來(lái)改變Position的值。
改變Position -
第三個(gè):選中后可以在Scene中對(duì)選中的GameObject改變其Rotation的值
改變Rotation -
第四個(gè):選中后在Scene中可以對(duì)選中的GameObject進(jìn)行三個(gè)方向的Scale的調(diào)整
改變Scale -
第五個(gè):選中后可以在Scene中對(duì)選中的GameObject進(jìn)行頂點(diǎn)的位置調(diào)整從而改變Scale的值
改變Scale -
第六個(gè):選中后可以同時(shí)改變Position、Rotation、Scale的值,是第二三四個(gè)的結(jié)合。
同時(shí)改變所有的Transform
創(chuàng)建游戲?qū)ο?/h1>
創(chuàng)建Sphere
接下來(lái)創(chuàng)建小球,同樣地,在MainScene下右鍵->3D Object->Sphere來(lái)創(chuàng)建一個(gè)unity預(yù)置的Sphere(球體),命名為Player,并通過(guò)reset其Transform來(lái)使其位置重置到原點(diǎn)。

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

關(guān)于光源
其實(shí)我們可以看到小球是有影子的,這是最開始unity為我們準(zhǔn)備的Directional Light作用的結(jié)果,我們可以看到Scene中的一個(gè)小太陽(yáng)的標(biāo)志,這個(gè)就是我們的光源,使用Directional Light來(lái)模擬太陽(yáng)的平行光。它的Transform則顯示了光源的位置、角度(也就是平行光的照射方向),如果我們將這個(gè)GameObject去掉的話就沒(méi)有了光的效果。
當(dāng)然通過(guò)改變Rotation的值就可以調(diào)節(jié)光源的方向,比如為了效果我將Rotation的Y值改為60。

創(chuàng)建Material
為了使GameObject美觀,我們通常會(huì)對(duì)其表面進(jìn)行一系列裝飾,而其表面的表現(xiàn)是通過(guò)為這個(gè)GameObject添加Material(材料)來(lái)實(shí)現(xiàn)的。
接下來(lái)為我們的Ground和Player添加最簡(jiǎn)單材料:純顏色。
在Assets下新建Materials目錄用于管理各種材料,然后右鍵該目錄選擇Create->Material新建一個(gè)材料命名為Background。

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

想要將創(chuàng)建的Material運(yùn)用在某個(gè)GameObject上,很簡(jiǎn)單,只需要拖動(dòng)該Material到Scene中的目標(biāo)GameObject上或者拖動(dòng)到Hierarchy的該GameObject上即可。

可以看到我們的Ground已經(jīng)變成了藍(lán)色

讓小球滾動(dòng)起來(lái)
讓小球擁有成為剛體
為了讓小球有滾動(dòng)的效果,我們需要小球擁有一系列的物理屬性,物理屬性已經(jīng)由unity內(nèi)置,我們只需為需要增加物理屬性的GameObject添加一個(gè)Rigidbody的Component即可。如上一節(jié)中所示,選中Player,在Inspector面板中通過(guò)Add Component中找到Physics下的Rigidbody即可。

為小球添加控制腳本
有了剛體屬性的小球需要在我們的控制下滾動(dòng),比如我們規(guī)定使用W,S,A,D四個(gè)按鍵來(lái)控制小球的方向,那么對(duì)于一個(gè)有物理屬性的剛體來(lái)說(shuō),為了能夠動(dòng)起來(lái),當(dāng)然需要力(Force)作用在物體上,這些有關(guān)于如何控制GameObject的方法需要我們使用腳本(Scripts)來(lái)完成,假如你已經(jīng)擁有了一定的C#編程基礎(chǔ)。
同樣我們?cè)贏ssets下創(chuàng)建Scripts目錄來(lái)管理腳本,在該目錄處右鍵->Create->C# Script創(chuàng)建一個(gè)腳本,這里我們命名為PlayerController。

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

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

unity已經(jīng)為我們預(yù)置好了腳本的最基本結(jié)構(gòu),最基本的,我們可以看到所有的unity腳本都繼承自MonoBehaviour類,然后有兩個(gè)預(yù)設(shè)函數(shù),Start函數(shù)是在第一幀開始渲染前調(diào)用,Update函數(shù)在每一幀刷新前調(diào)用,都是非常常用的函數(shù)。
接下來(lái)思考我們要做的事情,我們需要檢測(cè)用戶的輸入,并且通過(guò)輸入的按鍵來(lái)控制小球的滾動(dòng)方向,檢測(cè)用戶的輸入同時(shí)也需要識(shí)別輸入的是哪一個(gè)按鍵,除此之外我們還需要一些物理學(xué)有關(guān)的邏輯,比如我們需要添加一個(gè)力來(lái)控制小球的移動(dòng),這就是物理學(xué)邏輯,這些邏輯當(dāng)然是每一幀都要進(jìn)行一次,所以我們需要將這些邏輯寫在每一幀更新都要執(zhí)行的函數(shù)中。
顯然我們可以寫到Update函數(shù)下,因?yàn)閁pdate函數(shù)是每一幀刷新前都會(huì)調(diào)用的,同時(shí)我們還有另外的選擇,即使用FixedUpdate函數(shù),它在每一次進(jìn)行物理學(xué)運(yùn)算的時(shí)候調(diào)用,每次檢測(cè)到用戶輸入都需要進(jìn)行物理學(xué)運(yùn)算,所以我們可以將邏輯寫到FixedUpdate函數(shù)下。
開始編寫腳本
首先我們需要?jiǎng)?chuàng)建一個(gè)對(duì)于這個(gè)Player小球的引用,這樣才能知道我們控制的是哪個(gè)小球,這里小球是剛體,所以我們創(chuàng)建一個(gè)剛體(Rigidbody)的引用,并且需要在第一幀開始渲染之前通過(guò)GetComponent方法來(lái)找到小球創(chuàng)建剛體的引用,這一邏輯自然就需要寫到Start函數(shù)中了。
private Rigidbody rigidbodyPlayer;
void Start()
{
rigidbodyPlayer = GetComponent<Rigidbody>();
}
接下來(lái)對(duì)用戶輸入的讀取就需要寫到FiexedUpdate函數(shù)中了,我們使用Input類的GetAxis方法來(lái)獲取水平或者垂直的運(yùn)動(dòng)軸,這個(gè)方法會(huì)返回一個(gè)float值作為該軸的移動(dòng)距離。
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
通過(guò)以上兩行代碼我們就可以將用戶的W,S,A,D輸入轉(zhuǎn)化為水平軸和垂直軸的移動(dòng)距離,分別存儲(chǔ)在moveHorizontal和moveVertical兩個(gè)float類型的變量中。
接下來(lái)通過(guò)Rigidbody類的AddForce方法可以為剛體添加作用力,AddForce方法接受一個(gè)三維向量(Vector3)參數(shù),這個(gè)三維向量就可以表示力,顯然我們的三維向量可以用剛才的moveHorizontal和moveVertical兩個(gè)變量作為X值和Z值,同時(shí)我們是不需要小球在Y方向上移動(dòng)的,也就是將Y方向的力作用設(shè)置為0.0f即可,經(jīng)過(guò)調(diào)試我們會(huì)發(fā)現(xiàn)小球的移動(dòng)速度過(guò)慢,為了方便調(diào)節(jié)小球的速度,只需要在表示力的三維向量前乘以一個(gè)倍數(shù)即可,為了方便調(diào)整,我們?cè)O(shè)置一個(gè)public的float類型的變量speed來(lái)調(diào)節(jié)這個(gè)乘積。
這里必須說(shuō)明的是,凡在unity的腳本中被聲明為public類型的變量,在unity的Inspector界面中的該腳本的Component下都會(huì)出現(xiàn)一個(gè)可以設(shè)置的值的方框。
public float speed;
void FixedUpdate()
{
Vector3 movement = new Vector3(moveHorizontal,0.0f,moveVertical);
rigidbodyPlayer.AddForce(movement*speed);
}

此處我們將speed的值設(shè)為10比較合理,運(yùn)行游戲就會(huì)發(fā)現(xiàn)通過(guò)W,S,A,D的控制,小球動(dòng)了起來(lái)。

完整的代碼:
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);
}
}
當(dāng)然你也會(huì)發(fā)現(xiàn),小球超出了Plane的邊界居然掉了下去,其實(shí)這是合理的,因?yàn)樾∏驗(yàn)閯傮w,也就擁有物理引擎,當(dāng)然受到重力的影響,在沒(méi)有Plane的向上的作用力的情況下自然會(huì)下落。
設(shè)置攝像機(jī)
可以發(fā)現(xiàn),我們的Camera的角度和位置都比較刁鉆,這導(dǎo)致我們的游戲看到的畫面并不完整,接下來(lái)我們對(duì)Camera進(jìn)行設(shè)置,使其能夠跟隨我們的小球滾動(dòng)來(lái)同時(shí)移動(dòng)。
首先調(diào)節(jié)Main Camera的Position和Rotation使得畫面和角度比較合適,比如這里將Position的Y值設(shè)為6,Z值設(shè)為-6,將Rotation的X值設(shè)為45得到了一個(gè)較為合適的位置。

接下來(lái)通過(guò)腳本控制Main Camera跟隨小球Player一同移動(dòng),即在Position上保持相對(duì)靜止。
可能你會(huì)想到,只需要將Main Camera拖動(dòng)給Player使其成為Player的子物體不就可以保持兩者相對(duì)位置不變化了嗎?但是問(wèn)題在于球體Player是滾動(dòng)的,如果兩者的位置完全相對(duì)靜止,就會(huì)導(dǎo)致球滾動(dòng)時(shí)Main Cmaera也會(huì)跟著球滾動(dòng),有一種天旋地轉(zhuǎn)的感覺(jué)。感興趣的話可以嘗試一下。
新建腳本CameraController并添加給Main Camera做一個(gè)Component。為了使Main Camera的Transform的Position和Player的保持相對(duì)靜止,Rotation并不和其保持一致,可以想到一個(gè)辦法:設(shè)置一個(gè)偏移量,這個(gè)值初始化為游戲開始時(shí)Main Camera和Player之間的Position的差值,然后在球滾動(dòng)時(shí),每一次滾動(dòng)都改變Main Cmaera的Position,使其新的Position等于現(xiàn)在球的Position的值加上剛才的偏移量,這樣就會(huì)在每次球的位置改變時(shí)Main Camera都會(huì)跟上它的步驟。
顯然,偏移量的設(shè)置需要在Start函數(shù)中完成,每一次球的位置發(fā)生變化時(shí)的邏輯可以在Update函數(shù)中完成,但還有一個(gè)更好的選擇,就是LateUpdate函數(shù),該函數(shù)在每次有GameObject發(fā)生變動(dòng)時(shí)才會(huì)調(diào)用。
同時(shí),我們的腳本使加在Main Camera上的,所以Main Camera的Transform可以直接調(diào)用,但是球的Transform則需要單獨(dú)獲取,這里我們?cè)O(shè)置一個(gè)public的GameObject量,然后在unity中將球Player拖動(dòng)到這個(gè)量處作為參數(shù)即可。
private Vector3 offset;
public GameObject player;
void Start()
{
offset = transform.position - player.transform.position;
}
void LateUpdate()
{
transform.position = player.transform.position + offset;
}

這時(shí)候運(yùn)行游戲就可以發(fā)現(xiàn)Main Camera的位置隨著球的改變而發(fā)生了改變。

完整的代碼:
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之外,可以在其四周圍建立起一圈兒圍墻,很簡(jiǎn)單,使用預(yù)設(shè)的Cube就可以了。
為了更好的管理四個(gè)圍墻,我們可以先創(chuàng)建一個(gè)空的GameObject,將其命名為Walls,Reset使其重置位置,然后在其上右鍵新建一個(gè)Cube,并命名為WestWall,這樣這個(gè)Cube就成為了Walls的子物體。

接下來(lái)如何調(diào)整這面墻的大小、位置就很簡(jiǎn)單了,可以在Inspector中直接輸入具體數(shù)值,也可以直接在Scene中拖動(dòng)和縮放,最好我們可以得到這個(gè)墻體結(jié)構(gòu)。

為了簡(jiǎn)單方便,只要選中WestWall,在菜單欄的Edit中選擇Duplicate(復(fù)制)(快捷鍵:Ctrl+D)即可,然后將復(fù)制好的墻拖動(dòng)到適合的地點(diǎn),在復(fù)制,最后可以得到四面墻。

接下來(lái)測(cè)試游戲,墻起作用了!

下一篇文章:http://www.itdecent.cn/p/7e0e85092e5a
參考資料:https://unity3d.com/learn/tutorials/s/roll-ball-tutorial
本節(jié)內(nèi)容的完整官方教程視頻分享(英文無(wú)字幕):https://pan.baidu.com/s/1TNMMFjs7pZqLPhGQZ1tPqQ 提取碼:1u70
轉(zhuǎn)載請(qǐng)注明出處,本文永久更新鏈接:https://blogs.littlegenius.xin/2019/02/10/從滾球游戲初步體驗(yàn)Unity3D/




