前言
如果你玩過三國志這種型別的戰旗游戲或者模擬城市、部落沖突、海島奇兵這種模擬經營類的游戲,那么你對網格地圖一定不會陌生,在這些游戲中,所有地圖場景中的物體都是基于整齊的網格來記錄位置等資訊,如下圖:

如果你還是感知不到什么是網格地圖,俄羅斯方塊或者貪吃蛇你一定不會陌生,物體的存在是依托于規整的網格地圖而存在的,
還是一如既往,本篇文章為零基礎小白文,如果你是小萌新,并且對網格地圖感興趣的話,可以學習本片文章,然后嘗試創建自己的游戲吧!
本文章的最終顯示效果為:

1,創建組建出網格的基本單元
我們知道網格是由一個個格子組成的,所以第一步需要先創建出一個基本的模板:
創建一個腳本命名為Grid,并定義一些我們需要修改的屬性,由于本案例我想要創建一個有障礙物的地圖,用來作為A*尋路的地圖,所以需要下面的資訊:
- 模板寬度
- 模板高度
- 模板顏色
- 模板是否為障礙(由顏色標識)
- 模板點擊事件(模板顏色轉換)
撰寫模板腳本:
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;
//當網格地圖比較大時,每幀更新模板顏色比較消耗性能,可以修改為通過事件觸發
void Update()
{
gameObject.GetComponent<MeshRenderer>().material.color=color;
}
//委托系結模板點擊事件
private void OnMouseDown()
{
OnClick?.Invoke();
}
}
撰寫好腳本后,創建模板預制體,本案例就使用一個簡單的方塊來作為演示案例,為了保證可以區分每一個方格,大小縮放到0.9,這樣兩個方格之間就會有空隙來分割不同的網格塊,
創建好方格后,將Grid腳本掛在到物體上,并設定相關的初始引數,具體如圖:

2,編輯網格創建腳本
接下來我們就需要封裝一個網格創建的腳本,創建一個腳本命名為GridMeshCreate,然后撰寫該腳本,為了實作創建網格地圖的功能,我們需要獲取到一些基本資訊:
- 創建網格的寬度:
x軸Grid預制體的個數 - 創建網格的高度:
y軸Grid預制體的個數 - 創建網格中
Grid的位置:通過一個初始點,然后通過Grid的長寬計算
完成上面的資訊的定義后,我們就可以撰寫腳本來實作網格創建的功能了,但是在此之前我們要思考一個問題,我們的創建的每一個Grid的會完全一摸一樣嗎,答案肯定是不會,比如說,在一些模擬經營的游戲中,一個物體可能會對周圍的環境造成一些影響,為了標識其影響范圍,就需要通過不同顏色的網格來表示,如圖所示:
在上面的圖片中可以看出,我們需要對于不同區塊的網格進行不同的資訊展示,這就需要我們在網格創建時傳入對應的處理邏輯,具體的代碼結構為:
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;
}
//網格的寬高范圍
public MeshRange meshRange;
//生成網格起始點
public Vector3 startPos;
//網格生成的父物體
public Transform parentTran;
//模板預制體
public GameObject gridPre;
private Grid[,] m_grids;
public Grid[,] MeshGridData
{
get
{
return m_grids;
}
}
//注冊模板事件
public Action<Grid> gridEvent;
/// <summary>
/// 基于掛載組件的初始資料創建網格
/// </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>
/// 多載,基于傳入寬高資料來創建網格
/// </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>
/// 根據位置創建一個基本的Grid物體
/// </summary>
/// <param name="row">x軸坐標</param>
/// <param name="column">y軸坐標</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>
/// 洗掉網格地圖,并清除快取資料
/// </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);
}
}
關于上面的腳本,有下面的兩個關鍵點:
- 創建網格
- 對外暴露處理
Grid邏輯的方法
關于網格的創建,在腳本中,我們寫了一個多載的方法public void CreateMesh(int height,int widght),傳入了網格寬和高,來方便通過后期通過腳本靈活的修改網格的寬和高(注意這里的寬和高指的是x軸與y軸格子的個數)
而對于Grid邏輯對外暴露的實作,是利用在創建預制體時,為其添加一個委托事件,這樣就可以在我們其他腳本創建時寫入邏輯方法,而不需要對于這個封裝好的網格地圖創建類進行修改,而關于委托的一些知識,可以查看我之前的文章:
關于委托的文章:
- C# 委托基礎與入門
3,地圖生成案例
在我們封裝好網格創建的腳本后,就可以通過該腳本來做一個簡單的網格地圖來演示其用法
創建腳本命名為MainRun ,并進行編輯:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MainRun : MonoBehaviour
{
//獲取網格創建腳本
public GridMeshCreate gridMeshCreate;
//控制網格元素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>
/// 創建grid時執行的方法,通過委托傳入
/// </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方法中是對于我們網格創建框架的一個呼叫,而在GridEvent(Grid grid)中我們就可以寫入我們的邏輯,并通過修改Grid腳本中的代碼來輔助完成我們需要的效果,比如本案例中在Grid寫入了一個點擊事件,就可以在創建時通過委托定義該事件,
注意:
- 在腳本里面用到了
Random.Range(0, 1.0f)來生成一個概率,注意不要寫成Random.Range(0, 1),因為這樣輸出的結果只能為整數,即只能輸出零
在撰寫完成腳本后,就可以將GridMeshCreate腳本掛載到場景中的物體上,并根據注釋進行相關的賦值,如圖:

完成腳本掛載后點擊運行,進入游戲后,點擊空格鍵就會創建一張地圖,在地圖中會有隨機的障礙物,以紅色來標識障礙物,不可被點擊,而白色區域點擊后顏色變為藍色,具體效果如圖所示:

總結
這里只是介紹了一個簡單的案例,如果你覺得有用的話,可以嘗試基于GridMeshCreate腳本創建自己的網格地圖生成方法,來做出自己想要的效果!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/291952.html
標籤:其他
上一篇:Python游戲開發,pygame模塊,Python實作打磚塊小游戲
下一篇:C語言的掃雷簡化版
