Scene視圖輔助線繪制


  有時候需要在Scene視圖中繪制一些輔助線,方便進行一些編輯的工作,可以通過如下類和函數完成:

  繪制輔助線,相關類:

  Gizmos類:用於在Scene視圖中繪制調試信息或輔助線,這些輔助線只有在Scene中能看到,Game視圖中看不到。

  Handles類:繪制各種東西,可以繪制一些3D gizmo、2D GUI、進行坐標系統轉換等。

  相關函數(MonoBehaviour類):

  OnDrawGizmos:每幀調用,所繪gizmos可用於對對應物體拾取選中;

  OnDrawGizmosSelected :在物體被選中時繪制。

  下面的代碼用於繪制一個Sphere的輔助線:

 

using UnityEngine;
using System.Collections;

#if UNITY_EDITOR
using UnityEditor;
#endif

public class CylinderHelper : MonoBehaviour 
{

    public void OnDrawGizmos()
    {
        Gizmos.color = Color.blue;
        Gizmos.DrawSphere(transform.position, 0.3f);

#if UNITY_EDITOR
        Handles.color = Color.blue;
        Handles.ArrowCap(0, transform.position, transform.rotation, transform.localScale.z);
        Handles.Disc(transform.rotation, transform.position, Vector3.up, transform.localScale.z * 0.5f, false, 1);
#endif

    }

    public void OnDrawGizmosSelected()
    {
#if UNITY_EDITOR
        Handles.color = new Color(1f, 0f, 0f, 0.2f);
        Handles.DrawSolidDisc(transform.position, Vector3.up, transform.localScale.z * 0.5f);
#endif
    }

}

  未選中和選中的效果圖分別如下所示:

未選中:       選中:

  這其中有一個問題值得一提的,看繪制立方體的接口:

  public static void DrawCube(Vector3 center, Vector3 size);

  可以看出參數值傳入了位置和縮放,沒有旋轉參數,也就是該函數不支持旋轉,咋辦呢,不着急,可以通過設置Gizmos.matrix或Handles.matrix來實現:

public class CubeHelper : MonoBehaviour 
{
    public void OnDrawGizmos()
    {
        Gizmos.color = Color.blue;
        Gizmos.DrawSphere(transform.position, 0.3f);

        // 設置旋轉矩陣
        Matrix4x4 rotationMatrix = Matrix4x4.TRS(Vector3.zero, transform.rotation, Vector3.one);
        Gizmos.matrix = transform.localToWorldMatrix;
        // 在Local坐標原點繪制標准尺寸的對象
        Gizmos.color = new Color(1f, 0f, 0f, 0.8f);
        Gizmos.DrawCube(Vector3.zero, Vector3.one);
        Gizmos.color = Color.black;
        Gizmos.DrawWireCube(Vector3.zero, Vector3.one);
        
#if UNITY_EDITOR
        Handles.color = Color.blue;
        Handles.ArrowCap(0, transform.position, transform.rotation, transform.localScale.x);
#endif
    }        

}

  上面的代碼支持Gizmos的旋轉,原理很簡單,不贅述。

   Handles類也支持手動設置變換矩陣,我們再來看一個稍微復雜點的例子。在使用NavMeshObstacle時,因為阻擋區域是一個圓柱體形狀(cylinder),在給這個cylinder繪制輔助線時,最合適的是Handles.CylinderCap函數。但該函數默認繪制的圓柱體和碰撞區域是不吻合的,不只是大小、位置,寧方向都不一致,所以這里面要做一些變換,代碼如下所示:

using UnityEngine;
using System.Collections;

#if UNITY_EDITOR
using UnityEditor;
#endif

// NavMesh阻擋物的繪制
[ExecuteInEditMode]
public class ObstacleHelper : MonoBehaviour 
{
    private NavMeshObstacle obstacle;

    void Start()
    {
        obstacle = transform.GetComponent<NavMeshObstacle>();
    }

    public void OnDrawGizmos()
    {
#if UNITY_EDITOR

        Handles.color = new Color(Color.blue.r, Color.blue.g, Color.blue.b, 0.5f);

        // 圓柱體網上平移height * 0.5
        Vector3 vecUpOffset = transform.TransformDirection(transform.up);
        vecUpOffset.Normalize();
        vecUpOffset *= obstacle.height * 0.5f * transform.lossyScale.y;

        // 縮放,只能繪制圓形不能繪制橢圓
        Vector3 vecScale = Vector3.one;
        vecScale.x = Mathf.Max(transform.lossyScale.x, transform.lossyScale.z);     
        vecScale.y = vecScale.x;
        vecScale.z = transform.lossyScale.y * obstacle.height;
        // 乘以碰撞半徑
        vecScale.x *= obstacle.radius * 2f;
        vecScale.y *= obstacle.radius * 2f;

        // 設置變換矩陣
        Matrix4x4 cylinderMatrix = Matrix4x4.TRS(transform.position + vecUpOffset, transform.rotation * Quaternion.Euler(90f, 0f, 0f), vecScale);
        Handles.matrix = cylinderMatrix;
        Handles.CylinderCap(0, Vector3.zero, Quaternion.identity, 1f);
        Handles.matrix = Matrix4x4.identity;

#endif
    }    

}

  效果圖如下所示,輔助線可以自由適應gameobject和Obstacle參數的變化:

        

  上面的代碼一眼很難看懂,所以可以逐個變換來理解。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM