zoukankan      html  css  js  c++  java
  • 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参数的变化:

            

      上面的代码一眼很难看懂,所以可以逐个变换来理解。

  • 相关阅读:
    【读书笔记《Android游戏编程之从零开始》】6.Android 游戏开发常用的系统控件(TabHost、ListView)
    【读书笔记《Android游戏编程之从零开始》】5.Android 游戏开发常用的系统控件(ProgressBar、Seekbar)
    【读书笔记《Android游戏编程之从零开始》】4.Android 游戏开发常用的系统控件(EditText、CheckBox、Radiobutton)
    【读书笔记《Android游戏编程之从零开始》】3.Android 游戏开发常用的系统控件(Button、Layout、ImageButton)
    【读书笔记《Android游戏编程之从零开始》】2.Hello,World!
    【读书笔记《Android游戏编程之从零开始》】1.Android 平台简介与环境搭建
    【Android Demo】通过WebService获取今日天气情况
    布局优化之ViewStub源码分析
    http2.0与http1.X的区别
    OkHttpHelper使用
  • 原文地址:https://www.cnblogs.com/sifenkesi/p/3963290.html
Copyright © 2011-2022 走看看