【Unity】绘制网格 (2D场景)

简介

使用GL绘制网格,格子大小固定为1x1,鼠标放在的格子上用不同的颜色表示,网格比摄像机的视野略大,可以随意移动摄像机和改变摄像机的大小,格子看起来是无限的,并且是固定在地面上的。使用时需挂载在主摄像机上。

效果图

代码

using System;
using UnityEngine;
using System.Collections;
/// <summary>
/// 挂在主摄像机上
/// </summary>
public class MapGridDraw : MonoBehaviour
{
    /// <summary>
    /// 线的材质
    /// </summary>
    public Material lineMat;

    /// <summary>
    /// 线的颜色
    /// </summary>
    public Color lineColor = new Color(1, 1, 1, 0.5f);

    /// <summary>
    /// 鼠标放在的方格的颜色
    /// </summary>
    public Color mouseOverColor = new Color(0, 1, 0, 1);

    private Camera _camera;

    void Start()
    {
        _camera = GetComponent<Camera>();
    }

    void OnPostRender()
    {
        DrawGrid();
        DrawMouseOver();
    }

    /// <summary>
    /// 把一个世界坐标转换为格子的坐标
    /// </summary>
    /// <param name="pos"></param>
    public static Vector2 WorldPosToCellPos(Vector2 pos)
    {
        int x = (int)(pos.x > 0 ? pos.x + 0.5 : pos.x - 0.5);
        int y = (int)(pos.y > 0 ? pos.y + 0.5 : pos.y - 0.5);
        return new Vector2(x, y);
    }

    /// <summary>
    /// 得到鼠标所在的格子的坐标
    /// </summary>
    /// <returns></returns>
    public static Vector2 GetMouseCellPos()
    {
        return WorldPosToCellPos(Camera.main.ScreenToWorldPoint(Input.mousePosition));
    }


    /// <summary>
    /// 绘制网格
    /// </summary>
    void DrawGrid()
    {
        if (lineMat == null)
        {
            throw new Exception("lineMat is null");
        }
        Vector2 cameraPos = _camera.transform.position;

        //相机的宽高
        int width = _camera.pixelWidth;
        int height = _camera.pixelHeight;

        //视口在世界空间的四个点
        Vector2 leftUp = _camera.ScreenToWorldPoint(new Vector2(0, height));
        Vector2 rightUp = _camera.ScreenToWorldPoint(new Vector2(width, height));
        Vector2 leftDown = _camera.ScreenToWorldPoint(new Vector2(0, 0));
        Vector2 rightDown = _camera.ScreenToWorldPoint(new Vector3(width, 0));

        //相机视口在世界坐标中的宽高
        float viewWidth = rightUp.x - leftDown.x;
        float viewHeight = rightUp.y - leftDown.y;

        //cell在横轴和纵轴上的个数
        int x = (int) viewWidth + 1;
        int y = (int) viewHeight + 1;

        //x y变为奇数
        x = x / 2 * 2 + 1;
        y = y / 2 * 2 + 1;

        //中间的方块位置
        float centerX = x / 2 + 1;
        float centerY = y / 2 + 1;

        //偏移
        float offsetX = cameraPos.x % 1;
        float offsetY = cameraPos.y % 1;

        //竖线
        for (int i = 0; i <= x; i++)
        {
            //初始位置
            float posX = i - centerX + 0.5f;
            //线跟随摄像机移动
            posX += cameraPos.x;
            //产生偏移
            posX -= offsetX;

            DrawLine(new Vector2(posX, leftUp.y), new Vector2(posX, leftDown.y), lineColor);
        }
        //横线
        for (int j = 0; j <= y; j++)
        {
            //线跟随摄像机移动
            float posY = j - centerY + 0.5f;
            //线跟随摄像机移动
            posY += cameraPos.y;
            //产生偏移
            posY -= offsetY;

            DrawLine(new Vector2(leftUp.x, posY), new Vector2(rightUp.x, posY), lineColor);
        }
    }

    /// <summary>
    /// 绘制鼠标放在某个格子上的效果
    /// </summary>
    void DrawMouseOver()
    {
        DrawSquare(GetMouseCellPos(), mouseOverColor);
    }

    /// <summary>
    /// 画一条线 世界坐标
    /// </summary>
    /// <param name="posA"></param>
    /// <param name="posB"></param>
    /// /// <param name="color"></param>
    void DrawLine(Vector2 posA, Vector2 posB,Color color)
    {
        GL.Begin(GL.LINES);
        lineMat.SetPass(0);
        GL.Color(color);
        GL.Vertex3(posA.x, posA.y, 0);
        GL.Vertex3(posB.x, posB.y, 0);
        GL.End();
    }

    /// <summary>
    /// 画一个方形 世界坐标
    /// </summary>
    /// <param name="center"></param>
    /// <param name="width"></param>
    /// <param name="height"></param>
    /// <param name="color"></param>
    void DrawSquare(Vector2 center, float width, float height, Color color)
    {
        Vector2 leftUp = new Vector2(center.x - width / 2f, center.y + height / 2f);
        Vector2 rightUp = new Vector2(center.x + width / 2f, center.y + height / 2f);
        Vector2 leftDown = new Vector2(center.x - width / 2f, center.y - height / 2f);
        Vector2 rightDown = new Vector2(center.x + width / 2f, center.y - height / 2f);

        DrawLine(rightUp, leftUp, color);
        DrawLine(leftUp, leftDown, color);
        DrawLine(leftDown, rightDown, color);
        DrawLine(rightDown, rightUp, color);
    }

    /// <summary>
    /// 画一个 1x1 正方形 世界坐标
    /// </summary>
    /// <param name="center"></param>
    /// <param name="color"></param>
    void DrawSquare(Vector2 center, Color color)
    {
        DrawSquare(center, 1, 1, color);
    }
}

 

 

  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要使用Shader绘制网格,需要在Unity中创建一个材质(Material)并将其分配给网格对象(Mesh)。材质中包含着Shader的代码,它会告诉Unity如何绘制网格。 以下是一个简单的示例,演示如何使用Shader绘制一个简单的网格: 1. 创建一个新的Shader 在Unity中,选择"Create" -> "Shader"创建一个新的Shader。选择一个合适的命名,例如"MyShader"。 2. 编写Shader代码 打开新创建的Shader,你会看到一个空白的代码文件。在这里,你可以自由编写你的Shader代码。以下是一个简单的示例,它会绘制一个灰色的网格: ``` Shader "Custom/MyShader" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags {"Queue"="Transparent" "RenderType"="Opaque"} Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } fixed4 frag (v2f i) : SV_Target { return tex2D(_MainTex, i.uv) * 0.5; } ENDCG } } } ``` 这个Shader中包含一个名为"_MainTex"的属性,它是一个2D纹理。在Pass块中,Shader使用这个纹理对网格进行着色,并将颜色乘以0.5,以便将其变为灰色。 3. 创建一个材质 现在,你需要创建一个材质(Material),并将Shader分配给它。在Unity中,选择"Create" -> "Material"创建一个新的材质。给它一个合适的名称,例如"MyMaterial"。 选择新创建的材质,将Shader分配给它。在Inspector窗口中,将Shader字段设置为新创建的Shader。 4. 将材质分配给网格对象 最后一步是将材质分配给网格对象。在Unity中,选择你想要绘制网格对象,并将新创建的材质分配给它。 现在,当你在场景中查看网格对象时,它应该使用你编写的Shader进行着色了。如果需要,你可以进一步调整你的Shader代码,以实现更复杂的效果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值