Unity3D Gizmos 调试可视化

利用 Gizmos 直观地看到一些调试信息。

Unity3D Gizmos 调试可视化

在 Unity 开发中,很多时候我们需要在 Scene / Game 视图 里直观地看到一些调试信息,比如角色的攻击范围、AI 的巡逻路径、摄像机的视野等。

这时候,Unity 提供的 Gizmos 系统就是非常好用的工具。

基本用法

只要在脚本里实现 OnDrawGizmosOnDrawGizmosSelected 方法,就能绘制调试辅助图形。

csharp 复制代码
using UnityEngine;

public class GizmosDemo : MonoBehaviour
{
    [SerializeField] private float radius = 2f;

    private void OnDrawGizmos()
    {
        // 设置颜色
        Gizmos.color = Color.green;

        // 画一个球体
        Gizmos.DrawWireSphere(transform.position, radius);

        // 画一个立方体
        Gizmos.color = Color.yellow;
        Gizmos.DrawWireCube(transform.position + Vector3.up * 2, Vector3.one);

        // 画一条射线
        Gizmos.color = Color.red;
        Gizmos.DrawRay(transform.position, transform.forward * 5f);
    }

    private void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.cyan;
        Gizmos.DrawWireSphere(transform.position, radius * 1.5f);
    }
}
  • OnDrawGizmos -> 始终显示(场景中会很乱)
  • OnDrawGizmosSelected -> 只有选中物体时显示(推荐)

注:如果在视图中没有显示绘制的图形,请检查右上角的图形开关,勾选对应的脚本。

常用 Gizmos API

方法 描述
Gizmos.DrawWireSphere(pos, radius) 线框球体
Gizmos.DrawSphere(pos, radius) 实心球体
Gizmos.DrawWireCube(pos, size) 线框立方体
Gizmos.DrawCube(pos, size) 实心立方体
Gizmos.DrawLine(start, end) 绘制线段
Gizmos.DrawRay(origin, dir) 绘制射线
Gizmos.DrawIcon(pos, "icon.png", true) 绘制图标(方便定位)
Gizmos.matrix = transform.localToWorldMatrix 设置坐标系(绘制局部网格时很有用)
Gizmos.DrawMesh(mesh, pos, rot, scale) 绘制自定义 Mesh

实际应用场景

显示攻击范围

csharp 复制代码
private void OnDrawGizmosSelected()
{
    Gizmos.color = Color.red;
    Gizmos.DrawWireSphere(transform.position, attackRange);
}

显示 AI 巡逻路径

csharp 复制代码
private void OnDrawGizmos()
{
    Gizmos.color = Color.blue;
    for (int i = 0; i < waypoints.Length - 1; i++)
    {
        Gizmos.DrawLine(waypoints[i].position, waypoints[i + 1].position);
    }
}

显示摄像机视野

csharp 复制代码
private void OnDrawGizmos()
{
    Camera cam = GetComponent<Camera>();
    Gizmos.color = Color.green;
    Gizmos.matrix = cam.transform.localToWorldMatrix;
    Gizmos.DrawFrustum(Vector3.zero, cam.fieldOfView, cam.farClipPlane, cam.nearClipPlane, cam.aspect);
}

通用 Gizmos 工具类

为了避免每次都写重复代码,可以整理一个 GizmosHelper 工具类,例如:

  • 绘制调试网格
  • 绘制扇形范围
  • 绘制路径箭头
csharp 复制代码
using UnityEngine;

public static class GizmosHelper
{
    /// <summary>
    /// 绘制调试网格
    /// </summary>
    public static void DrawGrid(Vector3 origin, int width, int height, float cellSize, Color color)
    {
        Gizmos.color = color;
        for (int x = 0; x <= width; x++)
        {
            Gizmos.DrawLine(origin + new Vector3(x * cellSize, 0, 0),
                            origin + new Vector3(x * cellSize, 0, height * cellSize));
        }
        for (int z = 0; z <= height; z++)
        {
            Gizmos.DrawLine(origin + new Vector3(0, 0, z * cellSize),
                            origin + new Vector3(width * cellSize, 0, z * cellSize));
        }
    }

    /// <summary>
    /// 绘制扇形范围
    /// </summary>
    public static void DrawSector(Vector3 center, Vector3 forward, float angle, float radius, int segments = 20)
    {
        Gizmos.color = Color.yellow;
        float halfAngle = angle * 0.5f;
        Quaternion leftRot = Quaternion.AngleAxis(-halfAngle, Vector3.up);
        Quaternion rightRot = Quaternion.AngleAxis(halfAngle, Vector3.up);

        Vector3 leftDir = leftRot * forward * radius;
        Vector3 rightDir = rightRot * forward * radius;

        Gizmos.DrawLine(center, center + leftDir);
        Gizmos.DrawLine(center, center + rightDir);

        Vector3 lastPoint = center + leftDir;
        for (int i = 1; i <= segments; i++)
        {
            float t = (float)i / segments;
            Quaternion rot = Quaternion.AngleAxis(Mathf.Lerp(-halfAngle, halfAngle, t), Vector3.up);
            Vector3 nextPoint = center + rot * forward * radius;
            Gizmos.DrawLine(lastPoint, nextPoint);
            lastPoint = nextPoint;
        }
    }

    /// <summary>
    /// 绘制路径箭头
    /// </summary>
    public static void DrawPath(Vector3[] points, Color color)
    {
        if (points == null || points.Length < 2) return;

        Gizmos.color = color;
        for (int i = 0; i < points.Length - 1; i++)
        {
            Gizmos.DrawLine(points[i], points[i + 1]);
            DrawArrowHead(points[i], points[i + 1], color);
        }
    }

    private static void DrawArrowHead(Vector3 start, Vector3 end, Color color)
    {
        Vector3 dir = (end - start).normalized;
        Vector3 right = Quaternion.LookRotation(dir) * Quaternion.Euler(0, 150, 0) * Vector3.forward;
        Vector3 left = Quaternion.LookRotation(dir) * Quaternion.Euler(0, -150, 0) * Vector3.forward;

        Gizmos.DrawLine(end, end + right * 0.5f);
        Gizmos.DrawLine(end, end + left * 0.5f);
    }
}

使用示例:

csharp 复制代码
private void OnDrawGizmos()
{
    // 调试网格
    GizmosHelper.DrawGrid(Vector3.zero, 5, 5, 1f, Color.gray);

    // 扇形范围
    GizmosHelper.DrawSector(transform.position, transform.forward, 90f, 5f);

    // 路径箭头
    Vector3[] path = { transform.position, transform.position + Vector3.forward * 3, transform.position + Vector3.right * 3 };
    GizmosHelper.DrawPath(path, Color.cyan);
}

效果:

注意事项

  • Gizmos 只在 Scene / Game 视图 可见,不会出现在游戏发布版本。
  • Gizmos 面板 勾选对应脚本才能看到。
  • 建议用 OnDrawGizmosSelected,避免场景太乱。

总结

  • OnDrawGizmos / OnDrawGizmosSelected 是调试可视化的核心入口。
  • Gizmos 常用来显示 网格、范围、路径、摄像机视野等调试辅助信息
  • 封装 GizmosHelper 工具类 能极大提高开发效率。
相关推荐
天人合一peng2 小时前
unity 生成标记根据背景色标记变色
unity·游戏引擎
天人合一peng5 小时前
unity 生成标记根据背景色变色为明显的颜色
unity·游戏引擎
魔士于安6 小时前
Unity 超市总动员 超市收银台 超市货架 超市购物手推车 超市常见商品
游戏·unity·游戏引擎·贴图·模型
CandyU26 小时前
Unity —— 数据持久化
unity·游戏引擎
zh路西法6 小时前
【Unity实现Oneshot胶卷显形】游戏窗口化与Win32API的使用
游戏·unity·游戏引擎
凡情11 小时前
android隐私合规检测
android·unity
小贺儿开发11 小时前
Unity3D 本地 Stable Diffusion 文生图效果演示
人工智能·unity·stable diffusion·文生图·ai绘画·本地化
mxwin1 天前
Unity Shader 半透明物体为什么不能写入深度缓冲?
unity·游戏引擎·shader
晚枫歌F1 天前
三层时间轮的实现
网络·unity·游戏引擎
咸鱼永不翻身1 天前
Lua脚本事件检查工具
unity·lua·工具