一篇文章教會你用Unity制作網(wǎng)格地圖生成組件
前言
如果你玩過三國志這種類型的戰(zhàn)旗游戲或者模擬城市、部落沖突、海島奇兵這種模擬經(jīng)營類的游戲,那么你對網(wǎng)格地圖一定不會陌生。在這些游戲中,所有地圖場景中的物體都是基于整齊的網(wǎng)格來記錄位置等信息。如下圖:
如果你還是感知不到什么是網(wǎng)格地圖。俄羅斯方塊或者貪吃蛇你一定不會陌生,物體的存在是依托于規(guī)整的網(wǎng)格地圖而存在的。
還是一如既往,本篇文章為零基礎(chǔ)小白文,如果你是小萌新,并且對網(wǎng)格地圖感興趣的話,可以學(xué)習(xí)本片文章,然后嘗試創(chuàng)建自己的游戲吧!
本文章的最終顯示效果為:
1,創(chuàng)建組建出網(wǎng)格的基本單元
我們知道網(wǎng)格是由一個個格子組成的,所以第一步需要先創(chuàng)建出一個基本的模板:
創(chuàng)建一個腳本命名為Grid,并定義一些我們需要修改的屬性,由于本案例我想要創(chuàng)建一個有障礙物的地圖,用來作為A*尋路的地圖。所以需要下面的信息:
- 模板寬度
- 模板高度
- 模板顏色
- 模板是否為障礙(由顏色標(biāo)識)
- 模板點擊事件(模板顏色轉(zhuǎn)換)
編寫模板腳本:
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; public class Grid : MonoBehaviour { public float gridWidght; public float girdHeight; public bool isHinder; public Color color; public Action OnClick; //當(dāng)網(wǎng)格地圖比較大時,每幀更新模板顏色比較消耗性能,可以修改為通過事件觸發(fā) void Update() { gameObject.GetComponent<MeshRenderer>().material.color=color; } //委托綁定模板點擊事件 private void OnMouseDown() { OnClick?.Invoke(); } }
編寫好腳本后,創(chuàng)建模板預(yù)制體,本案例就使用一個簡單的方塊來作為演示案例,為了保證可以區(qū)分每一個方格,大小縮放到0.9,這樣兩個方格之間就會有空隙來分割不同的網(wǎng)格塊。
創(chuàng)建好方格后,將Grid腳本掛在到物體上,并設(shè)置相關(guān)的初始參數(shù),具體如圖:
2,編輯網(wǎng)格創(chuàng)建腳本
接下來我們就需要封裝一個網(wǎng)格創(chuàng)建的腳本,創(chuàng)建一個腳本命名為GridMeshCreate
,然后編寫該腳本,為了實現(xiàn)創(chuàng)建網(wǎng)格地圖的功能,我們需要獲取到一些基本信息:
- 創(chuàng)建網(wǎng)格的寬度:x軸Grid預(yù)制體的個數(shù)
- 創(chuàng)建網(wǎng)格的高度:y軸Grid預(yù)制體的個數(shù)
- 創(chuàng)建網(wǎng)格中Grid的位置:通過一個初始點,然后通過Grid的長寬計算
完成上面的信息的定義后,我們就可以編寫腳本來實現(xiàn)網(wǎng)格創(chuàng)建的功能了,但是在此之前我們要思考一個問題,我們的創(chuàng)建的每一個Grid的會完全一摸一樣嗎。答案肯定是不會。比如說,在一些模擬經(jīng)營的游戲中,一個物體可能會對周圍的環(huán)境造成一些影響,為了標(biāo)識其影響范圍,就需要通過不同顏色的網(wǎng)格來表示,如圖所示:
在上面的圖片中可以看出,我們需要對于不同區(qū)塊的網(wǎng)格進(jìn)行不同的信息展示,這就需要我們在網(wǎng)格創(chuàng)建時傳入對應(yīng)的處理邏輯。具體的代碼結(jié)構(gòu)為:
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; public class GridMeshCreate : MonoBehaviour { [Serializable] public class MeshRange { public int widght; public int height; } //網(wǎng)格的寬高范圍 public MeshRange meshRange; //生成網(wǎng)格起始點 public Vector3 startPos; //網(wǎng)格生成的父物體 public Transform parentTran; //模板預(yù)制體 public GameObject gridPre; private Grid[,] m_grids; public Grid[,] MeshGridData { get { return m_grids; } } //注冊模板事件 public Action<Grid> gridEvent; /// <summary> /// 基于掛載組件的初始數(shù)據(jù)創(chuàng)建網(wǎng)格 /// </summary> public void CreateMesh() { if (meshRange.widght == 0 || meshRange.height == 0) { return; } ClearMesh(); m_grids = new Grid[meshRange.widght, meshRange.height]; for (int i = 0; i < meshRange.widght; i++) { for (int j = 0; j < meshRange.height; j++) { CreateGrid(i, j); } } } /// <summary> /// 重載,基于傳入寬高數(shù)據(jù)來創(chuàng)建網(wǎng)格 /// </summary> /// <param name="height"></param> /// <param name="widght"></param> public void CreateMesh(int height,int widght) { if (widght == 0 || height == 0) { return; } ClearMesh(); m_grids = new Grid[widght, height]; for (int i = 0; i < widght; i++) { for (int j = 0; j < height; j++) { CreateGrid(i, j); } } } /// <summary> /// 根據(jù)位置創(chuàng)建一個基本的Grid物體 /// </summary> /// <param name="row">x軸坐標(biāo)</param> /// <param name="column">y軸坐標(biāo)</param> public void CreateGrid(int row,int column) { GameObject go = GameObject.Instantiate(gridPre, parentTran); Grid grid = go.GetComponent<Grid>(); float posX = startPos.x + grid.gridWidght * row; float posZ = startPos.z + grid.girdHeight * column; go.transform.position = new Vector3(posX, startPos.y, posZ); m_grids[row, column] = grid; gridEvent?.Invoke(grid); } /// <summary> /// 刪除網(wǎng)格地圖,并清除緩存數(shù)據(jù) /// </summary> public void ClearMesh() { if (m_grids == null || m_grids.Length == 0) { return; } foreach (Grid grid in m_grids) { if (grid.gameObject != null) { Destroy(grid.gameObject); } } Array.Clear(m_grids, 0, m_grids.Length); } }
關(guān)于上面的腳本,有下面的兩個關(guān)鍵點:
- 創(chuàng)建網(wǎng)格
- 對外暴露處理Grid邏輯的方法
關(guān)于網(wǎng)格的創(chuàng)建,在腳本中,我們寫了一個重載的方法public void CreateMesh(int height,int widght)
,傳入了網(wǎng)格寬和高,來方便通過后期通過腳本靈活的修改網(wǎng)格的寬和高(注意這里的寬和高指的是x軸與y軸格子的個數(shù))
而對于Grid邏輯對外暴露的實現(xiàn),是利用在創(chuàng)建預(yù)制體時,為其添加一個委托事件。這樣就可以在我們其他腳本創(chuàng)建時寫入邏輯方法,而不需要對于這個封裝好的網(wǎng)格地圖創(chuàng)建類進(jìn)行修改,而關(guān)于委托的一些知識,可以查看我之前的文章:
關(guān)于委托的文章:
C# 委托基礎(chǔ)與入門
3,地圖生成案例
在我們封裝好網(wǎng)格創(chuàng)建的腳本后,就可以通過該腳本來做一個簡單的網(wǎng)格地圖來演示其用法
創(chuàng)建腳本命名為MainRun ,并進(jìn)行編輯:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MainRun : MonoBehaviour { //獲取網(wǎng)格創(chuàng)建腳本 public GridMeshCreate gridMeshCreate; //控制網(wǎng)格元素grid是障礙的概率 [Range(0,1)] public float probability; private void Update() { if (Input.GetKeyDown(KeyCode.Space)) { Run(); } } private void Run() { gridMeshCreate.gridEvent = GridEvent; gridMeshCreate.CreateMesh(); } /// <summary> /// 創(chuàng)建grid時執(zhí)行的方法,通過委托傳入 /// </summary> /// <param name="grid"></param> private void GridEvent(Grid grid) { //概率隨機決定該元素是否為障礙 float f = Random.Range(0, 1.0f); Debug.Log(f.ToString()); grid.color = f <= probability ? Color.red : Color.white; grid.isHinder = f <= probability; //模板元素點擊事件 grid.OnClick = () => { if (!grid.isHinder) grid.color = Color.blue; }; } }
可以看到,在Run方法中是對于我們網(wǎng)格創(chuàng)建框架的一個調(diào)用,而在GridEvent(Grid grid)
中我們就可以寫入我們的邏輯,并通過修改Grid腳本中的代碼來輔助完成我們需要的效果,比如本案例中在Grid寫入了一個點擊事件,就可以在創(chuàng)建時通過委托定義該事件。
注意:
在腳本里面用到了Random.Range(0, 1.0f)
來生成一個概率,注意不要寫成Random.Range(0, 1)
,因為這樣輸出的結(jié)果只能為整數(shù),即只能輸出零
在編寫完成腳本后,就可以將GridMeshCreate
腳本掛載到場景中的物體上,并根據(jù)注釋進(jìn)行相關(guān)的賦值。如圖:
完成腳本掛載后點擊運行,進(jìn)入游戲后,點擊空格鍵就會創(chuàng)建一張地圖,在地圖中會有隨機的障礙物,以紅色來標(biāo)識障礙物,不可被點擊,而白色區(qū)域點擊后顏色變?yōu)樗{(lán)色,具體效果如圖所示:
總結(jié)
這里只是介紹了一個簡單的案例,如果你覺得有用的話,可以嘗試基于GridMeshCreate
腳本創(chuàng)建自己的網(wǎng)格地圖生成方法,來做出自己想要的效果!
到此這篇關(guān)于Unity制作網(wǎng)格地圖生成組件的文章就介紹到這了,更多相關(guān)Unity網(wǎng)格地圖生成組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#進(jìn)行圖像處理的常見方法(Bitmap,BitmapData,IntPtr)使用詳解
這篇文章主要為大家詳細(xì)介紹了C#進(jìn)行圖像處理的幾個常見方法(Bitmap,BitmapData,IntPtr)具體使用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2024-01-01

Extjs4如何處理后臺json數(shù)據(jù)中日期和時間