Unity crea un componente de generación de mapas de cuadrícula

prefacio

Si ha jugado juegos de banderas de batalla del tipo Three Kingdoms o juegos de gestión de simulación como Sim City, Clash of Clans y Boom Beach, entonces debe estar familiarizado con los mapas de cuadrícula. En estos juegos, todos los objetos en la escena del mapa se basan en una cuadrícula ordenada para registrar información como la ubicación. Como se muestra abajo:
Encontré una foto en línea.

Si aún no puede percibir qué es un mapa de cuadrícula. No debes estar familiarizado con Tetris o Snake.La existencia de objetos depende de un mapa de cuadrícula regular.

Como siempre, este artículo no tiene contenido básico. Si eres nuevo en Xiaomeng y estás interesado en los mapas de cuadrícula, ¡puedes estudiar este artículo e intentar crear tu propio juego!

El efecto de visualización final de este artículo es:
inserte la descripción de la imagen aquí

1. Crea las unidades básicas que componen la grilla

Sabemos que las cuadrículas se componen de cuadrículas, por lo que el primer paso es crear una plantilla básica:

Cree un script llamado Gridy defina algunas propiedades que necesitamos modificar.Por este caso, quiero crear un mapa con obstáculos para usar como mapa para la búsqueda de rutas A*. Por lo que se requiere la siguiente información:

  • Ancho de la plantilla
  • Altura de la plantilla
  • Color de la plantilla
  • Si la plantilla es un obstáculo (identificado por color)
  • Evento de clic de plantilla (conversión de color de plantilla)

Escriba el guión de la plantilla:

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();
    }

}

Después de escribir el guión, cree una plantilla prefabricada. En este caso, se usa un cuadrado simple como ejemplo de demostración. Para garantizar que cada cuadrado se pueda distinguir, el tamaño se escala de 0.9tal manera que haya un espacio entre los dos. cuadrados para separar diferentes cuadrados bloque de rejilla.

Después de crear la cuadrícula, Gridcuelgue el script en el objeto y configure los parámetros iniciales relevantes, como se muestra en la figura:

inserte la descripción de la imagen aquí

2. Edite el script de creación de cuadrícula

A continuación, debemos encapsular un script de creación de cuadrícula, crear un script llamado GridMeshCreatey luego escribir el script. Para realizar la función de crear un mapa de cuadrícula, necesitamos obtener información básica:

  • El ancho de la cuadrícula creada: el número de xejes Gridprefabricados
  • Crear altura de cuadrícula: número de prefabricados de yejeGrid
  • Cree una posición en la cuadrícula Grid: pase un punto inicial, luego pase Gridel cálculo de longitud y ancho

Después de completar la definición de la información anterior, podemos escribir scripts para implementar la función de creación de cuadrículas, pero antes de eso tenemos que pensar en una pregunta, ¿cada una de nuestras creaciones Gridserá exactamente igual? La respuesta es definitivamente no. Por ejemplo, en algunos juegos de simulación de negocios, un objeto puede tener alguna influencia en el entorno que lo rodea.Para identificar su rango de influencia, debe representarse mediante cuadrículas de diferentes colores, como se muestra en la figura:

Por favor agregue la descripción de la imagenComo se puede ver en la imagen de arriba, necesitamos mostrar información diferente para las grillas de diferentes bloques, lo que requiere que pasemos la lógica de procesamiento correspondiente cuando se crea la grilla. La estructura del código específico es:

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);
    }
}

Hay dos puntos clave sobre el guión anterior:

  • crear una cuadrícula
  • Métodos para exponer la Gridlógica de procesamiento al mundo exterior

Con respecto a la creación de la cuadrícula, en el script, escribimos un método sobrecargado public void CreateMesh(int height,int widght), pasando el ancho y el alto de la cuadrícula, para facilitar la modificación flexible del ancho y el alto de la cuadrícula a través del script más tarde (tenga en cuenta el ancho y el alto). aquí se refiere al número de xejes y ycuadrículas de ejes)

Para Gridla implementación de la exposición lógica, se usa para agregar un evento delegado al prefabricado cuando se crea. De esta manera, los métodos lógicos se pueden escribir cuando se crean nuestros otros scripts, sin necesidad de modificar esta clase de creación de mapa de cuadrícula encapsulada, y para obtener algunos conocimientos sobre la delegación, puede consultar mi artículo anterior:

Artículos sobre delegación:

3. Caso de generación de mapas

Después de encapsular la secuencia de comandos para la creación de cuadrículas, podemos usar la secuencia de comandos para hacer un mapa de cuadrícula simple para demostrar su uso.

Cree un script llamado MainRuny edítelo:

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;
        };

    }
}

Se puede ver que en el Runmétodo hay una llamada a nuestro marco de creación de cuadrícula, y en GridEvent(Grid grid)él podemos escribir nuestra lógica y modificar Gridel código en el script para ayudar a completar el efecto que necesitamos, como en este caso en GridWrite a haga clic en evento, puede definir el evento a través del delegado en el momento de la creación.

Aviso:

  • Se usa en el script Random.Range(0, 1.0f)para generar una probabilidad, tenga cuidado de no escribirlo Random.Range(0, 1), porque el resultado de salida solo puede ser un número entero, es decir, solo puede salir cero

Después de escribir el guión, puede GridMeshCreatemontar el guión en los objetos de la escena y realizar tareas relacionadas de acuerdo con los comentarios. Como se muestra en la figura:
inserte la descripción de la imagen aquí

Después de montar el script, haga clic para ejecutar. Después de ingresar al juego, haga clic en la barra espaciadora para crear un mapa. Habrá obstáculos aleatorios en el mapa. Los obstáculos están marcados en rojo y no se puede hacer clic, y el color del blanco El área cambia después de hacer clic. Es azul y el efecto específico se muestra en la figura:
inserte la descripción de la imagen aquí

Reponer

Al usar el código creado por el mapa de cuadrícula, tal vez encontró un inconveniente, es decir, uno de los tipos de variables en él es el nombre de la clase Grid, por lo que habrá limitaciones. Mi script prefabricado solo se puede montar Grid, lo que obviamente es un inconveniente, así que le hice algunas modificaciones más tarde y Gridlo reemplacé con el GameObjectscript modificado:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class GridMeshCreate : MonoBehaviour 
{
    
    
    [Serializable]
    public class MeshRange
    {
    
    
        public int horizontal;
        public int vertical;
    }
    [Header("网格地图范围")]
    public MeshRange meshRange;
    [Header("网格地图起始点")]
    private Vector3 startPos;
    [Header("创建地图网格父节点")]
    public Transform parentTran;
    [Header("网格地图模板预制体")]
    public GameObject gridPre;
    [Header("网格地图模板大小")]
    public Vector2 scale;


    private GameObject[,] m_grids;
    public GameObject[,] grids
    {
    
    
        get
        {
    
    
            return m_grids;
        }
    }
    //注册模板事件
    public Action<GameObject, int, int> gridEvent;

    /// <summary>
    /// 基于挂载组件的初始数据创建网格
    /// </summary>
    public void CreateMesh()
    {
    
    
        if (meshRange.horizontal == 0 || meshRange.vertical == 0)
        {
    
    
            return;
        }
        ClearMesh();
        m_grids = new GameObject[meshRange.horizontal, meshRange.vertical];
        for (int i = 0; i < meshRange.horizontal; i++)
        {
    
    
            for (int j = 0; j < meshRange.vertical; 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 GameObject[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);
        //T grid = go.GetComponent<T>();

        float posX = startPos.x + scale.x * row;
        float posZ = startPos.z + scale.y * column;
        go.transform.position = new Vector3(posX, startPos.y, posZ);
        m_grids[row, column] = go;
        gridEvent?.Invoke(go, row, column);
    }
    /// <summary>
    /// 删除网格地图,并清除缓存数据
    /// </summary>
    public void ClearMesh()
    {
    
    
        if (m_grids == null || m_grids.Length == 0)
        {
    
    
            return;
        }
        foreach (GameObject go in m_grids)
        {
    
    
            if (go != null)
            {
    
    
                Destroy(go);
            }
        }
        Array.Clear(m_grids, 0, m_grids.Length);
    }

}

Resumir

Aquí hay un caso simple, si lo encuentra útil, puede intentar GridMeshCreatecrear su propio método de generación de mapas de cuadrícula basado en un script para lograr el efecto que desea.

Supongo que te gusta

Origin blog.csdn.net/xinzhilinger/article/details/119302097
Recomendado
Clasificación