Unity3d 实现在Build后的项目中显示Gizimos辅助线的方法(限OPENGL)

首先想说下,U3D自带的Gizmos真是太爽了,而且经常测试也需要用到这个东西,不过坑爹的是,似乎它不能在Build后的Project里显示出来,即使是Development Build也不行,emmmm, 这我就想吐槽下U3D官方了,为啥要把这么好用的功能给在build后屏蔽,难道大家都是一次Build到位无BUG的么.

好,那么废话不多说,进入正题

来源

这个方法是我在谷歌搜到的,由一个叫做Phill的大神提供的方法,感兴趣的话可以去看看 https://itch.io/t/162915/drawing-unity-gizmos-in-builds

目前这方法是我见过最好用的方法,绘制出来的效果和U3D官方一样,唯一多的2个麻烦点的地方就是需要创建个空的Material(用来绘制)还有在你场景的Main Camera上绑定多一个脚本,但总比之前在CSDN上看到那些用Linerender来画之类的方法简单很多。

局限性

这个方法是通过U3D提供的OnPostRender()回调上做Trick的,该方法提供了原生GL函数让你有办法控制绘制,但是有个问题,因为这里是使用Opengl下的函数进行绘制,所以DX环境下不会适用,并且崩溃,不过反正是用来Debug,也无所谓,最后也会去掉这些线条的233

使用方法

首先你需要2个脚本,GizmoManager.csGizmos.cs

  • GizmosManager.cs 是用来处理线条绘制的,你需要把它绑定到Main Camera上
  • Gizmos.cs 是用来提供绘制线条的方法的,这里简易封装类下各种基本的绘制函数例如,DrawLine,DrawBox 等,你会在你需要用到Debug线条的时候用它。
    • 不过需要注意的是,你千万别把class名称写成class Gizmos, 因为Unity3D官方的Gizmos绘制类也是叫这个名称的,这样会引起冲突,如果你非常执着就喜欢Gizmos这个名字的话,那么你可以通过加个namespace命名空间来解决这个问题,只要不要和unity3d官方的Gizmos类在同一个命名空间下就可以了=w= ,我这边为了图块,就暂时取为:GLDebug好了,虽然可能会引起某些重度洁癖者的不适 –>–>

其次你需要创建一个空的Material,叫什么名称都行,然后在把它绑定到 GizmoManager.css 上面,你可以注意下 GizmoManager.cs 代码中不是有个:

public Material material;

这里就是你需要绑定这个Material的地方,然后就是设置下这个Material的Shader(着色器)了,我个人建议选择UI/Default,因为这个基本属于UI的东西,而且我们也不需要他有阴影之类的啥的效果,如下图所示:

这部做完了之后,就大功告成啦~最后就是记得使用OpenGL渲染,好像在DX渲染下会崩溃,如果你是Windows用户的话,记得在保存Project前在Player Settings里把DirectX的API去掉,不然很有可能会导致下次项目文件打不开(估计是Windows平台U3D会优先使用DX渲染的原因)

那么下面放出这2大脚本的代码,(原作者:Phill再次感谢下这位大佬提供的这个方法)

GizmoManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GizmoManager : MonoBehaviour
{ 
    public struct GizmoLine {
        public Vector3 a;
        public Vector3 b;
        public Color color;

        public GizmoLine(Vector3 a, Vector3 b, Color color)
        {
            this.a = a;
            this.b = b;
            this.color = color;
        }
    }
    
    public bool showGizmos = true;
    public Material material;
    public static List<GizmoLine> lines = new List<GizmoLine>();

    public static bool Show { get; private set; }

    private void Update()
    {
        Show = showGizmos;
    }

    void OnPostRender()
    {
        material.SetPass(0);
        GL.Begin(GL.LINES);

        for (int i = 0; i < lines.Count; i++)
        {
            GL.Color(lines[i].color);
            GL.Vertex(lines[i].a);
            GL.Vertex(lines[i].b);
        }

        GL.End();
        lines.Clear();
    }
}

Gizmos.cs

using UnityEngine;
using System.Collections.Generic;

public class GLDebug
{
    public static void DrawLine(Vector3 a, Vector3 b, Color color)
    {
        if (!GizmoManager.Show) return;

        GizmoManager.lines.Add(new GizmoManager.GizmoLine(a, b, color));
        /* 
        try
        {
            UnityEngine.Gizmos.color = color;
            UnityEngine.Gizmos.DrawLine(a, b);
        }
        catch (UnityException unityException)
        {
            //ignores the annoying
            //UnityException: Gizmo drawing functions can only be used in OnDrawGizmos and OnDrawGizmosSelected.
            //error
        }
        */
    }

    public static void DrawBox(Vector3 position, Vector3 size, Color color)
    {
        if (!GizmoManager.Show) return;

        Vector3 point1 = new Vector3(position.x - size.x / 2f, position.y - size.y / 2f, position.z - size.z / 2f);
        Vector3 point2 = new Vector3(position.x + size.x / 2f, position.y - size.y / 2f, position.z - size.z / 2f);
        Vector3 point3 = new Vector3(position.x + size.x / 2f, position.y + size.y / 2f, position.z - size.z / 2f);
        Vector3 point4 = new Vector3(position.x - size.x / 2f, position.y + size.y / 2f, position.z - size.z / 2f);

        Vector3 point5 = new Vector3(position.x - size.x / 2f, position.y - size.y / 2f, position.z + size.z / 2f);
        Vector3 point6 = new Vector3(position.x + size.x / 2f, position.y - size.y / 2f, position.z + size.z / 2f);
        Vector3 point7 = new Vector3(position.x + size.x / 2f, position.y + size.y / 2f, position.z + size.z / 2f);
        Vector3 point8 = new Vector3(position.x - size.x / 2f, position.y + size.y / 2f, position.z + size.z / 2f);

        DrawLine(point1, point2, color);
        DrawLine(point2, point3, color);
        DrawLine(point3, point4, color);
        DrawLine(point4, point1, color);

        DrawLine(point5, point6, color);
        DrawLine(point6, point7, color);
        DrawLine(point7, point8, color);
        DrawLine(point8, point5, color);

        DrawLine(point1, point5, color);
        DrawLine(point2, point6, color);
        DrawLine(point3, point7, color);
        DrawLine(point4, point8, color);
    }

    public static void DrawSquare(Vector3 position, Vector3 size, Color color)
    {
        if (!GizmoManager.Show) return;

        Vector3 point1 = new Vector3(position.x - size.x / 2f, position.y - size.y / 2f, position.z);
        Vector3 point2 = new Vector3(position.x + size.x / 2f, position.y - size.y / 2f, position.z);
        Vector3 point3 = new Vector3(position.x + size.x / 2f, position.y + size.y / 2f, position.z);
        Vector3 point4 = new Vector3(position.x - size.x / 2f, position.y + size.y / 2f, position.z);

        DrawLine(point1, point2, color);
        DrawLine(point2, point3, color);
        DrawLine(point3, point4, color);
        DrawLine(point4, point1, color);
    }

    public static void DrawCircle(Vector3 position, float radius, Color color)
    {
        if (!GizmoManager.Show) return;

        DrawPolygon(position, radius, 18, color);
    }

    public static void DrawPolygon(Vector3 position, float radius, int points, Color color)
    {
        if (!GizmoManager.Show) return;

        float angle = 360f / points;

        for (int i = 0; i < points; ++i)
        {
            float sx = Mathf.Cos(Mathf.Deg2Rad * angle * i) * radius / 2;
            float sy = Mathf.Sin(Mathf.Deg2Rad * angle * i) * radius / 2;

            float nx = Mathf.Cos(Mathf.Deg2Rad * angle * (i + 1)) * radius / 2;
            float ny = Mathf.Sin(Mathf.Deg2Rad * angle * (i + 1)) * radius / 2;

            Vector3 a = new Vector3(sx, sy, position.z);
            Vector3 b = new Vector3(nx, ny, position.z);

            DrawLine(position + a, position + b, color);
        }
    }
}

 

效果

基本和在Unity3d的Editor效果差不多,结果相当满意~

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください