給貓看的游戲AI實(shí)戰(zhàn)(一)Unity俯視角游戲初步

前言
大家好,如題目所說的,這個(gè)坑呢,專門講和游戲AI有關(guān)的內(nèi)容。難度不高,會(huì)從非常非?;A(chǔ)開始,假定用戶是我家的大貓 (′?ω?`) 。
現(xiàn)在Unity方面的教程和視頻可以說是汗牛充棟,為了找到有特點(diǎn)的角度作者我也是煞費(fèi)苦心。機(jī)緣巧合最近在做一些游戲AI相關(guān)的內(nèi)容,于是就開了這個(gè)坑。
廢話不說,第一節(jié)作為適應(yīng)課程(讓我適應(yīng)專欄寫作),內(nèi)容相對(duì)很少,但是之后有不少例子是基于這種俯視角游戲的,俯視角游戲在觀察AI行為方面很直觀很好用,所以要先搭一個(gè)學(xué)習(xí)用的工程。沒基礎(chǔ)的同學(xué)跟著自己做一下就能搞定,有基礎(chǔ)的同學(xué)可以一遍掃過去毫無壓力。

一、場景搭建

按照上圖所示,搭建一個(gè)簡單的場景
1、創(chuàng)建一個(gè)平面作為地板,地板放大一些,3倍左右,地板默認(rèn)有Mesh Collider組件。
2、放幾個(gè)方塊Cube作為障礙物,Cube默認(rèn)有碰撞體Box Collider組件。
3、創(chuàng)建一個(gè)膠囊體代表玩家,正面最好加上一個(gè)彩色的方塊以區(qū)分正面在哪。下面有主角特寫,感覺有點(diǎn)像小黃人。

4、創(chuàng)建材質(zhì)可以用來改變貼圖的顏色。在Assets目錄里創(chuàng)建Material,然后調(diào)個(gè)顏色,拖到物體上即可。下面有截圖。

5、為方便起見,給主角加上Rigid Body剛體組件,這是一種物理有關(guān)的組件。有了它就可以用速度、力等方法控制角色了。但是這里注意取消重力,也就是取消Use Gravity。

前面的步驟非?;荆壹业呢堃呀?jīng)做完了。接下來要寫點(diǎn)代碼控制主角的移動(dòng)。
6、在Project窗口Assets文件夾點(diǎn)擊右鍵——Create新建——C# Script,創(chuàng)建一個(gè)新的C#腳本,命名為Player,拖拽到場景里的Player上(膠囊體)。
7、雙擊這個(gè)腳本,開始編輯吧。我們的代碼都經(jīng)過了簡化,力求簡單。
public class Player : MonoBehaviour {
// 用于控制移動(dòng)速度,public變量方便在編輯器里修改
public float moveSpeed = 6;
// 代表剛體組件的變量
Rigidbody myRigidbody;
// Player GameObject初始化時(shí)調(diào)用
void Start()
{
// 在這里給myRigidbody變量賦值,方便后面的使用。
// 如果不用這個(gè)變量也可以,那每次都需要GetComponent<Rigidbody>,會(huì)很麻煩。
myRigidbody = GetComponent<Rigidbody>();
}
// 每幀被引擎調(diào)用一次,下面詳細(xì)說明
void Update()
{
// 后面添加
}
}
8、我們打算用鼠標(biāo)+鍵盤控制Player的移動(dòng),和大量流行的俯視角射擊游戲是一樣的,鼠標(biāo)用來指方向、開火。鍵盤的WASD用來移動(dòng)。首先解決鼠標(biāo)指哪,主角就轉(zhuǎn)向哪的問題:
根據(jù)鼠標(biāo)位置,創(chuàng)建一個(gè)射線:
// 說明:鼠標(biāo)在屏幕上有一個(gè)位置Input.mousePosition,這個(gè)位置和游戲無關(guān)
// 就是你windows鼠標(biāo)的位置而已
// 通過Camera.main,也就是主攝像機(jī)的,就可以把鼠標(biāo)位置轉(zhuǎn)換到游戲中去,制造一條射線
// 這個(gè)射線很好理解,你拿一根針,垂直屏幕,戳在鼠標(biāo)的位置,就是這條射線ray了。
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
我們拿著這個(gè)射線讓它往垂直屏幕的方向射過去,就會(huì)碰到物體(準(zhǔn)確的說是有Collider碰撞組件或者Rigid Body剛體組件的物體),然后碰撞的交點(diǎn)就是我們輸入的點(diǎn):
// 先創(chuàng)建一個(gè)RaycastHit變量,也就是射線碰撞信息,在下面一句用到。
RaycastHit hitt = new RaycastHit();
// 這句話的意思:讓射線ray打出去,距離100(很長的距離),把碰撞結(jié)果返回到hitt變量中。
// out參數(shù)就是用來輸出結(jié)果的,是C#特有的寫法。
Physics.Raycast(ray, out hitt, 100, LayerMask.GetMask("Ground"));
如果不嚴(yán)謹(jǐn)?shù)刈?,最后的LayerMask.GetMask("Ground")參數(shù)是不需要的,不寫的話如果鼠標(biāo)當(dāng)前位置正好是Player或者障礙物,就可能會(huì)造成偏差。所以我們限定射線只能和地板碰撞,穿過其他東西。這里需要設(shè)置一下地板的Layer,如下圖操作:

在任意一個(gè)空白的Layer上寫上Ground,就創(chuàng)建了一個(gè)Ground層。然后把地板的Layer設(shè)置為Ground層即可。

接著寫代碼:
// 打印Log,方便查看碰撞是否成功了。如果不成功八成是Layer設(shè)置的問題
Debug.Log("hitt", hitt.transform);
// 如果碰撞到了東西
if (hitt.transform != null)
{
// 讓當(dāng)前物體(也就是掛著這個(gè)腳本的Player)轉(zhuǎn)向目標(biāo)點(diǎn)。注意目標(biāo)點(diǎn)的寫法。
transform.LookAt(new Vector3(hitt.point.x, transform.position.y, hitt.point.z));
}
Update函數(shù)整個(gè)代碼如下:
void Update()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitt = new RaycastHit();
Physics.Raycast(ray, out hitt, 100, LayerMask.GetMask("Ground"));
Debug.Log("hitt", hitt.transform);
if (hitt.transform != null)
{
transform.LookAt(new Vector3(hitt.point.x, transform.position.y, hitt.point.z));
}
}
9、經(jīng)過步驟8的詳細(xì)說明,我們已經(jīng)可以能讓主角跟隨鼠標(biāo)轉(zhuǎn)動(dòng)了,播放一下,看看效果。

10、之后添加用WASD移動(dòng)的代碼,很簡單只有一句,加在Update函數(shù)的最后面一句即可:
myRigidbody.velocity = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")).normalized * moveSpeed;
這一句對(duì)新手很不友好,可以解釋為以下N句:
// 獲得輸入的H軸和V軸,也就是橫軸和縱軸,也就是W、S鍵或是A、D鍵的狀態(tài)。
float input_h = Input.GetAxisRaw("Horizontal");
float input_v = Input.GetAxisRaw("Vertical");
// 輸入是一個(gè)-1~+1之間的浮點(diǎn)數(shù),把它轉(zhuǎn)化成方向向量
Vector3 vec = new Vector3(input_h, 0, input_v);
// 當(dāng)W鍵和D鍵同時(shí)按下時(shí),vec會(huì)比單按W鍵要長一些,你可以想想為什么。
// 所以這里要把輸入歸一化,無論怎么按鍵,vec長度都要一致。
vec = vec.normalized;
// 乘以moveSpeed可以讓調(diào)整vec的長度
vec = vec * moveSpeed;
// 把vec賦值給剛體的速度,就可以讓剛體運(yùn)動(dòng)起來了
myRigidbody.velocity = vec;
以上兩種方法,任選一種,初學(xué)者建議把后面這段,粘貼到Update函數(shù)里面,最后的位置。
11、這樣,我們的主角就動(dòng)起來咯~~

小結(jié)
本節(jié)課程基礎(chǔ)到?jīng)]朋友,前半部分我真懷疑大猩猩經(jīng)過訓(xùn)練也能做出來 o(*≧▽≦)ツ┏━┓
主要是讓我自己也熟悉一下,下節(jié)課就開車咯,大家要親手做一下才能上車。
————————————————————————————————————
對(duì)游戲開發(fā)感興趣的同學(xué),歡迎圍觀我們:【皮皮關(guān)游戲開發(fā)教育】 ,會(huì)定期更新各種教程干貨,更有別具一格的線下小班教育~
我們的官網(wǎng)地址:http://levelpp.com/
我們的游戲開發(fā)技術(shù)交流群:610475807
我們的微信公眾號(hào):皮皮關(guān)