【Unity俯視角射擊】我們來做一個《元?dú)怛T士》的完整Demo(三)

作者:Yumir
哈嘍大家好我的yumir。
慣例先上成果鏈接:
https://connect.unity.com/mg/other/untitled-9864
本篇相對前面兩篇會比較簡短啦,但是剩下的內(nèi)容一篇講完又太多太復(fù)雜,所以還是單獨(dú)開一片力求把問題將清楚,也歡迎大家多多提出自己的疑惑。
接下來開始制作元?dú)怛T士小地圖吧。

地圖UI
我在元?dú)怛T士地圖自動生成那篇文章提到過,元?dú)怛T士的地圖實(shí)際上是在5*5的格子里面從中心開始向四周隨機(jī)衍生房間,沒記錯的話是五到六個。
比如這次Demo做的地圖是這樣的:

表現(xiàn)到小地圖上就是這樣的:

地圖整體的UI布局是這樣的:

將上圖切割成9*9的矩陣可知,該圖是由若干方塊、橫向長方形和縱向長方形組成的,在組成的圖形對應(yīng)位置上放上小房間的圖標(biāo)表示為起點(diǎn),另外再新建一個紅色的小方塊作為玩家定位點(diǎn)。
可以利用Grid Layout Group進(jìn)行排版,制作一個9*9的方塊布局,再在方塊中設(shè)置對應(yīng)的形狀,在Ctrl+D的加持下一兩分鐘就可以做完了。
需要注意的是,在使用這個UI的時候是需要通過顯示隱藏當(dāng)中的方塊來繪制地圖的,如果這時候物體身上掛載了Grid Layout Group,就會導(dǎo)致顯示出來的格子全都會自動對齊,所以在使用之前需要將Grid Layout Group去掉。
地圖邏輯
我想要編寫一個用于管理小地圖的UI顯示的腳本,首先對腳本的需求進(jìn)行分析,該腳本管理的就是一個小地圖UI(上面的9*9格子)和一個用于表示玩家位置的小方塊。
所以新建一個用于管理小地圖UI的腳本,持有小地圖本體和表示玩家位置的小方塊,聲明一個list用于管理小地圖上所有的格子。
在Start方法中進(jìn)行初始化:
public Transform littlemap;
public Transform playerIndex;
List<Transform> mapItems;
void Start(){
??? mapItems = new List<Transform>();
??? foreach (Transform item in littlemap){
??????? mapItems.Add(item);
??? }
??? for (int i = 0; i < mapItems.Count; i++){
??????? mapItems[i].gameObject.SetActive(false);
??? }
??? mapItems[40].gameObject.SetActive(true);
}
?
掐指一算我的小地圖需要三個功能,分別是:更新玩家所在的房間、更新可以探索的地方、更新已探索的房間等。除此之外還有一個顯示特定某個房間的需求,但是只有在初始房間需要用到,所以就沒有提取為方法。
1、更新玩家所在的房間
小地圖實(shí)現(xiàn)這個功能的任務(wù)其實(shí)可以簡化到兩行代碼,由調(diào)用者輸入房間號,小地圖根據(jù)房間號計(jì)算出房間在小地圖對應(yīng)的位置,將玩家方塊設(shè)置到該位置即可。
public void UpdatePlayerIndex(int num){
??? int mapNum = num / 5 * 18 + num % 5 * 2;
??? playerIndex.transform.position = mapItems[mapNum].transform.position;
}
?
那么我們需要如何使游戲在合適的時候更新玩家的位置呢?
目前我是這樣解決的:
首先在每個房間新建一個觸發(fā)器覆蓋房間范圍(省事,后期進(jìn)行優(yōu)化)。這樣一來我們就能得到一個“玩家進(jìn)入某房間”的事件,每個房間有各自的管理腳本,我在房間腳本的父類中聲明了玩家進(jìn)入的方法。

public class RoomTrig : MonoBehaviour{
??? private void OnTriggerEnter2D(Collider2D collision){
??????? if (collision.transform.tag == "Player")
??????????? GetComponent<Room>().PlayerEnter();
??? }
}
?
雖然本篇只涉及到更新玩家所在位置這一操作,但是后續(xù)可以在該事件中對不同房間進(jìn)行多樣化操作。
在游戲管理腳本中聲明更新玩家所處房間的方法:
public void UpdatePlayerRoom(Room room){
??? this.room = room;
??? //更新地圖顯示
??? littleMap.UpdatePlayerIndex(room.roomNum);
??? if (!room.isExplored){//如果沒有被探索過
??????? littleMap.UpdateCanExploreInMap(room);
??????? littleMap.UpdateRoomsExploredInMap(room.roomNum);
??? }
}
?
2、更新可以探索的地方
這個操作需要用到一組數(shù)據(jù),也就是我之前實(shí)現(xiàn)地圖自動生成時用到的樹狀結(jié)構(gòu)的“房間類”,因?yàn)橹谱鱠emo的時候地圖并不是動態(tài)生成的,所以房間的數(shù)據(jù)也需要手動添加。

等以后有機(jī)會做動態(tài)生成的時候再將數(shù)據(jù)剝離即可。
可以看到目前的數(shù)據(jù)結(jié)構(gòu)是每個房間持有自己的子節(jié)點(diǎn)房間,存放于nextRooms數(shù)組中。
在小地圖管理腳本中聲明一個新的方法:
public void UpdateCanExploreInMap(Room room){
??? foreach (Room nextRoom in room.nextRooms){
??????? int data = nextRoom.roomNum - room.roomNum;
??????? int roomNum = room.roomNum;
??????? int roadNum = 0;
??????? switch (data){
??????????? case -5://上
??????????????? roadNum = roomNum / 5 * 18 + roomNum % 5 * 2 - 9;
??????????????? break;
??????????? case 5://下
??????????????? roadNum = roomNum / 5 * 18 + roomNum % 5 * 2 + 9;
??????????????? break;
?????? ?????case -1://左
??????????????? roadNum = roomNum / 5 * 18 + roomNum % 5 * 2 - 1;
??????????????? break;
??????????? case 1://右
??????????????? roadNum = roomNum / 5 * 18 + roomNum % 5 * 2 + 1;
??????????????? break;
??????????? default:
??????????????? break;
??????? }
??????? int nextRoomNum = nextRoom.roomNum / 5 * 18 + nextRoom.roomNum % 5 * 2;
??????? mapItems[nextRoomNum].gameObject.SetActive(true);
??????? mapItems[roadNum].gameObject.SetActive(true);
??? }
}
?
該方法遍歷傳入的房間對象所持有的nextRooms數(shù)組,根據(jù)房間號的差判斷可探索房間位于所處房間的哪一個方位,計(jì)算兩個房間之間的道路格子的位置。
最后將小地圖上房間之間的“道路”和可探索的房間設(shè)置顯示,就可以了。
3、更新已探索的房間
上文游戲管理腳本中的更新玩家所處房間方法中有一個if判斷,當(dāng)玩家進(jìn)入一個房間,如果該房間還沒有被探索過,是需要執(zhí)行兩個方法的,一個是上文中的更新可以探索的房間,那么玩家當(dāng)前所處的房間也就可以被標(biāo)記為已探索。
現(xiàn)在想想這里改成將整個地圖隱藏,當(dāng)玩家探索完畢的時候再調(diào)用這個方法會更好,下次一定。
public void UpdateRoomsExploredInMap(int room){
??? int mapNum = room / 5 * 18 + room % 5 * 2;
??? mapItems[mapNum].GetComponent<Image>().color = new Color(1, 1, 1, 1);
}
?
我事先把所有表示房間的格子的顏色都設(shè)置為白色半透明的格子,當(dāng)玩家探索完之后,改為不透明格子,就是已經(jīng)探索完了。
一個簡單好用的小地圖UI就這樣制作完成了,文中提到的地圖自動生成方法如果沒有看過并且感興趣,傳送門在這里:
用uinty實(shí)現(xiàn)元?dú)怛T士地圖的自動生成

歡迎加入游戲開發(fā)群歡樂攪基:1082025059
對游戲開發(fā)感興趣的童鞋可戳這里進(jìn)一步了解:http://www.levelpp.com/