Unity 编辑器篇|(十)Handles (全面总结 | 建议收藏)

目录

  • 1. 前言
  • 2 参数总览
  • 3 Handles两种使用方式
    • 3.1 基于Editor类的OnSceneGUI
    • 3.2 基于EditorWindow
  • 4 Handles绘制
    • 4.1 Draw:绘制元几何体(点、线、面)
      • 4.1.1 抗锯齿: DrawAAPolyLine 、 DrawAAConvexPolygon
      • 4.1.2 绘制实线: DrawLine 、 DrawLines 、DrawPolyLine
      • 4.1.3 绘制虚线: DrawDottedLine 、 DrawDottedLines
      • 4.1.4 绘制贝塞尔曲线: DrawBezier
      • 4.1.5 绘制圆形圆盘: DrawSolidDisc 、 DrawSolidArc 、 DrawSolidRectangleWithOutline
      • 4.1.6 绘制圆弧: DrawWireDisc 、 DrawWireArc 、 DrawWireCube
      • 4.1.7 绘制 3D 纹理: DrawTexture3DVolume 、 DrawTexture3DSlice 、 DrawTexture3DSDF
    • 4.2 Handle:可视化操作数值(Vector3、Vector2、float等)
      • 4.2.1 FreeMoveHandle
      • 4.2.2 FreeRotateHandle
      • 4.2.3 PositionHandle
      • 4.2.4 RadiusHandle
      • 4.2.5 RotationHandle
      • 4.2.6 ScaleHandle
      • 4.2.7 ScaleValueHandle
    • 4.3 Caps:绘制多边形几何体(如方块,点精灵,球形,圆锥等)
      • 4.3.1 ArrowHandleCap
      • 4.3.2 CircleHandleCap
      • 4.3.3 ConeHandleCap
      • 4.3.4 CubeHandleCap
      • 4.3.5 CylinderHandleCap
      • 4.3.6 DotHandleCap
      • 4.3.7 RectangleHandleCap
    • 4.4 GUI
      • 4.4.1 Label
      • 4.4.2 Button
      • 4.4.3 ScaleSlider
      • 4.4.4 Slider
      • 4.4.5 Slider2D
    • 4.5 Camera:摄像机

1. 前言

  • Sceneview(场景视图中)自定义3D GUI 控制器与绘制的类
  • Handles是Unity在场景视图中,用于操控物体的3D控制器,已内置许多操作GUI,比如我们熟悉的基于Transform对位置、缩放、旋转坐标的操作工具。当然,我们使用自定义的Editor,定义自己的Handle GUI操作显示也是可能的。这种GUIs将会非常有用于程序化生成的场景内容、“不可见”的子对象与组。比如路径点与坐标标记点。

2 参数总览

静态函数描述
ArrowHandleCap绘制一个类似于移动工具所用箭头的箭头。
BeginGUI在 3D 手柄 GUI 内开始一个 2D GUI 块。
Button创建一个 3D 按钮。
CircleHandleCap绘制一个圆形手柄。将此手柄传递给 handle 函数。
ClearCamera清除摄像机。
ConeHandleCap绘制一个锥体手柄。将此手柄传递给 handle 函数。
CubeHandleCap绘制一个立方体手柄。将此手柄传递给 handle 函数。
CylinderHandleCap绘制一个圆柱体手柄。将此手柄传递给 handle 函数。
Disc创建一个可使用鼠标拖动的 3D 圆盘。
DotHandleCap绘制一个圆点手柄。将此手柄传递给 handle 函数。
DrawAAConvexPolygon绘制使用点数组指定的抗锯齿凸多边形。
DrawAAPolyLine绘制使用点数组和宽度指定的抗锯齿线。
DrawBezier绘制通过给定切线的起点和终点的纹理化贝塞尔曲线。
DrawCamera在矩形内绘制一个摄像机。
DrawDottedLine绘制一条从 p1p2 的虚线。
DrawDottedLines从 p1 到 p2 绘制一条线。
DrawGizmos在给定相机的后处理之前或之后绘制 GizmoSubset。
DrawLine绘制一系列虚线段。
DrawLines绘制一系列线段。
DrawOutline在场景视图中围绕指定游戏对象绘制轮廓。
DrawPolyLine绘制一条穿过 points 列表的线。
DrawSelectionFrame在指定位置和旋转处创建一个具有指定大小的正方形。
DrawSolidArc在 3D 空间中绘制一个圆扇形(饼图)。
DrawSolidDisc在 3D 空间中绘制一个实心平面圆盘。
DrawSolidRectangleWithOutline在 3D 空间中绘制一个实心轮廓矩形。
DrawTexture3DSDF在 3D 空间中使用有符号距离场渲染模式绘制 3D 纹理。
DrawTexture3DSlice在 3D 空间中使用切片渲染模式绘制 3D 纹理。
DrawTexture3DVolume在 3D 空间中使用体积渲染模式绘制 3D 纹理。
DrawWireArc在 3D 空间中绘制圆弧。
DrawWireCube使用 center 和 size 绘制一个线框盒体。
DrawWireDisc在 3D 空间中绘制扁平圆盘的轮廓。
EndGUI结束一个 2D GUI 块并返回到 3D 手柄 GUI。
FreeMoveHandle创建一个不受约束的移动手柄。
FreeRotateHandle创建一个不受约束的旋转手柄。
GetMainGameViewSize获取主游戏视图的宽度和高度。
Label为位于 3D 空间中的手柄创建文本标签。
MakeBezierPoints返回表示贝塞尔曲线的点数组。
PositionHandle创建一个位置手柄。
RadiusHandle创建一个场景视图半径手柄。
RectangleHandleCap绘制一个矩形手柄。将此手柄传递给 handle 函数。
RotationHandle创建一个场景视图旋转手柄。
ScaleHandle创建一个场景视图缩放手柄。
ScaleSlider创建一个定向缩放滑动条。
ScaleValueHandle创建一个缩放单个浮点的 3D 手柄。
SetCamera设置当前摄像机,以便所有手柄和辅助图标均使用相应设置进行绘制。
ShouldRenderGizmos确定是否绘制 Gizmos。
Slider创建一个沿着一个轴移动的 3D 滑动条。
Slider2D创建一个沿两个轴定义的平面移动的 3D 滑动条。
SnapToGrid将每个 Transform.position 或 Vector3 舍入为 EditorSnapSettings.gridSize 的最接近倍数。
SnapValue如果对齐为 active,则将 value 四舍五入到 snap 的最接近倍数。注意,snap 只能为正数。
SphereHandleCap绘制一个球体手柄。将此手柄传递给 handle 函数。
TransformHandle创建变换手柄。

3 Handles两种使用方式

3.1 基于Editor类的OnSceneGUI

  • 在继承自Editor的类中,可以定义【OnSceneGUI()】
  • 这样当此Edtior在活跃状态时(比如一个Inspector面板展开),在【OnSceneGUI()】方法内的内容将根据SceneView的刷新而调用,触发对应逻辑。
using UnityEngine;

public class HandlesScript : MonoBehaviour
{

}
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    private void OnSceneGUI()
    {
        Debug.Log("在Editor OnSceneGUI中 调用....");
    }
}

  • 在【Hierarchy】中新建空对象,挂载脚本,点击对象在【Inspector】中显示【HandlesScript】信息,就可以看见信息打印:
    1
    注:下文实例代码都是在OnSceneGUI中编写调用。

3.2 基于EditorWindow

  • 有些时候,我们更想在一个Window中进行数据编辑与操作,但是EditorWindow可没有OnSceneGUI,怎么办呢?这时候,需要手动对SceneView的刷新事件进行注册了。
using UnityEngine;
using UnityEditor;
public class HandlesWindow : EditorWindow
{
    public static HandlesWindow m_mainWindow;

    [MenuItem("MyWindows/HandlesWindow")]
    public static void OpenWindow() //打开窗口
    {
        m_mainWindow = EditorWindow.GetWindow<HandlesWindow>();
        m_mainWindow.Show();
    }
    private void OnEnable() 
    {
        SceneView.duringSceneGui += OnSceneGUI; //对SceneView的刷新事件进行注册
    }
    private void OnDisable() 
    {
        SceneView.duringSceneGui -= OnSceneGUI; //对SceneView的刷新事件取消注册
    }
    private void OnSceneGUI(SceneView sceneView) //自定义刷新事件的委托方法
    {
        Debug.Log("在 Window OnSceneGUI中 调用...."); //具体逻辑
    }
}

4 Handles绘制

4.1 Draw:绘制元几何体(点、线、面)

4.1.1 抗锯齿: DrawAAPolyLine 、 DrawAAConvexPolygon

  • DrawAAPolyLine: 绘制使用点数组和宽度指定的抗锯齿线。
    • 注意:如果您希望拥有恒定屏幕大小的手柄,请使用 HandleUtility.GetHandleSize。
    • 注意:要获得抗锯齿效果,请使用 1x2 像素(一个透明的白色像素和一个不透明的白色像素)的纹理。
  • DrawAAConvexPolygon: 绘制使用点数组指定的抗锯齿凸多边形。

DrawAAPolyLine

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    private void OnSceneGUI()
    {
        Handles.DrawAAPolyLine(new Vector3[] { Vector3.zero, Vector3.one, new Vector3(2, 0, 2) });
    }
}

1

DrawAAConvexPolygon

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
[CanEditMultipleObjects]
public class HandlesEditor : Editor
{
    private void OnSceneGUI()
    {
        Handles.DrawAAConvexPolygon(new Vector3[] { Vector3.zero, Vector3.one, new Vector3(2, 0, 2) });
    }
}

2

4.1.2 绘制实线: DrawLine 、 DrawLines 、DrawPolyLine

  • DrawLine:从 p1 到 p2 绘制一条线。
  • DrawLines:绘制一系列线段。
  • DrawPolyLine:绘制一条穿过 points 列表的线。

DrawLine

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    private void OnSceneGUI()
    {
        Handles.DrawLine(Vector3.zero, Vector3.one);
    }
}

2
DrawLines

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    Vector3[] lineSegments = new Vector3[4]
    {
        //线段一
        Vector3.zero, Vector3.one,
        //线段二
        Vector3.one, new Vector3(2,0,2)
    };
    private void OnSceneGUI()
    { 
        Handles.DrawLines(lineSegments);
    }
}

2
DrawPolyLine

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    Vector3[] positions = new Vector3[4]
  {
        Vector3.zero, Vector3.one, new Vector3(2,0,2), Vector3.zero
  };
    private void OnSceneGUI()
    {
        Handles.DrawPolyLine(positions);
    }
}

3

4.1.3 绘制虚线: DrawDottedLine 、 DrawDottedLines

  • DrawDottedLine:绘制一条从 p1p2 的虚线。
  • DrawDottedLines:绘制一系列虚线段。

DrawDottedLine

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    //线段长度及其间距的大小(以像素为单位)。
    float screenSpaceSize = 4.0f;
    private void OnSceneGUI()
    {
        Handles.DrawDottedLine(Vector3.zero, Vector3.one, screenSpaceSize);
    }
}

1
DrawDottedLines

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    Vector3[] lineSegments = new Vector3[4]
    {
        //线段一
        Vector3.zero, Vector3.one,
        //线段二
        Vector3.one, new Vector3(2,0,2)
    };

    //线段长度及其间距的大小(以像素为单位)。
    float screenSpaceSize = 4.0f;
    private void OnSceneGUI()
    {
        Handles.DrawDottedLines(lineSegments, screenSpaceSize);
    }
}

1

4.1.4 绘制贝塞尔曲线: DrawBezier

  • DrawBezier:绘制通过给定切线的起点和终点的纹理化贝塞尔曲线。
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    public Vector3 startPoint = new Vector3(-0.0f, 0.0f, 0.0f);//贝塞尔曲线的起点。
    public Vector3 endPoint = new Vector3(-2.0f, 1.0f, 0.0f);//贝塞尔曲线的终点。
    public Vector3 startTangent = new Vector3(-2.0f, 2.0f, 0.0f);//贝塞尔曲线的起始切线。
    public Vector3 endTangent = Vector3.zero;//贝塞尔曲线的终点切线。
    private void OnSceneGUI()
    {
        Handles.DrawBezier(startPoint, endPoint, startTangent, endTangent, Color.red, null, 2f);
    }
}

2

4.1.5 绘制圆形圆盘: DrawSolidDisc 、 DrawSolidArc 、 DrawSolidRectangleWithOutline

  • DrawSolidDisc:在 3D 空间中绘制一个实心平面圆盘。
  • DrawSolidArc:在 3D 空间中绘制一个圆扇形(饼图)。
  • **DrawSolidRectangleWithOutline **:在 3D 空间中绘制一个实心轮廓矩形。

DrawSolidDisc

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    //圆盘的中心。
    Vector3 center = Vector3.zero;
    //圆盘的法线。
    Vector3 normal = Vector3.up;
    //该圆盘的半径。
    float radius = 1.0f;
    private void OnSceneGUI()
    {
        Handles.DrawSolidDisc(center, normal, radius);
    }
}

1
DrawSolidArc

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    //圆盘的中心。
    Vector3 center = Vector3.zero;
    //圆盘的法线。
    Vector3 normal = Vector3.up;
    //圆周上的点相对于圆心的方向,即扇形的起点。
    Vector3 from = Vector3.left;
    //扇形的角度(以度为单位)。
    float angle = 180;
    //该圆盘的半径。
    float radius = 1.0f;
    private void OnSceneGUI()
    {
        Handles.DrawSolidArc(center, normal, from, angle, radius);
    }
}

2
DrawSolidRectangleWithOutline

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    private void OnSceneGUI()
    {
        HandlesScript t = target as HandlesScript;
        Vector3 pos = t.transform.position;

        Vector3[] verts = new Vector3[]
        {
            new Vector3(pos.x -2, pos.y, pos.z -2),
            new Vector3(pos.x -2, pos.y, pos.z + 2),
            new Vector3(pos.x + 2, pos.y, pos.z + 2),
            new Vector3(pos.x +2, pos.y, pos.z -2)
        };

        Handles.DrawSolidRectangleWithOutline(verts, new Color(0.5f, 0.5f, 0.5f, 0.1f), new Color(0, 0, 0, 1));
    }
}

3

4.1.6 绘制圆弧: DrawWireDisc 、 DrawWireArc 、 DrawWireCube

  • DrawWireDisc:在 3D 空间中绘制扁平圆盘的轮廓。
  • DrawWireArc:在 3D 空间中绘制圆弧。
  • DrawWireCube:使用 center 和 size 绘制一个线框盒体。

DrawWireDisc

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    //圆盘的中心。
    Vector3 center = Vector3.zero;
    //圆盘的法线。
    Vector3 normal = Vector3.up;
    //条粗细(零粗细绘制单像素线条)。
    float thickness = 3;
    //该圆盘的半径。
    float radius = 1.0f;
    private void OnSceneGUI()
    {
        Handles.color = Color.red;
        Handles.DrawWireDisc(center, normal, radius, thickness);
    }
}

1
DrawWireArc

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    //圆盘的中心。
    Vector3 center = Vector3.zero;
    //圆盘的法线。
    Vector3 normal = Vector3.up;
    //圆周上的点相对于圆心的方向,即圆弧的起点。
    Vector3 from = Vector3.left;
    //条粗细(零粗细绘制单像素线条)。
    float thickness = 3;
    //圆的半径。
    float angle = 180;
    //该圆盘的半径。
    float radius = 1.0f;
    private void OnSceneGUI()
    {
        Handles.color = Color.red;
        Handles.DrawWireArc(center, normal, from, angle, radius, thickness);
    }
}

2
DrawWireCube

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    Vector3 center = Vector3.zero;
    Vector3 size = Vector3.one;
    private void OnSceneGUI()
    {
        Handles.color = Color.red;
        Handles.DrawWireCube(center, size);
    }
}

3

4.1.7 绘制 3D 纹理: DrawTexture3DVolume 、 DrawTexture3DSlice 、 DrawTexture3DSDF

  • DrawTexture3DVolume:在 3D 空间中使用体积渲染模式绘制 3D 纹理。
  • DrawTexture3DSlice:在 3D 空间中使用切片渲染模式绘制 3D 纹理。
  • DrawTexture3DSDF:在 3D 空间中使用有符号距离场渲染模式绘制 3D 纹理。

DrawTexture3DVolume

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
[CanEditMultipleObjects]
public class HandlesEditor : Editor
{
    //要绘制的体积纹理。
    public Texture texture;
    //非线性体积不透明度修改器。使用它来控制可视化的不透明度。有效值为 0-1(含)。
    //值为 1 时完全不透明,值为 0 时完全透明。默认值为 1。
    float opacity = 0;
    //设置每个纹理像素计数的样本。值越高,渲染质量越高。默认值为 1。
    float qualityModifier = 0;
    //设置要使用的纹理过滤模式。
    FilterMode filterMode = FilterMode.Trilinear;
    //启用颜色渐变可视化。
    bool useColorRamp = true;
    //Unity 用作颜色渐变的自定义渐变。如果未指定,Unity 将使用 Google Turbo 色带。
    Gradient customColorRamp;
    private void OnSceneViewGUI(SceneView sv)
    {
        Handles.DrawTexture3DVolume(texture, opacity, qualityModifier, filterMode,
            useColorRamp, useColorRamp ? customColorRamp : null);
    }
}

DrawTexture3DSlice

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
[CanEditMultipleObjects]
public class HandlesEditor : Editor
{
    //要绘制的体积纹理。
    public Texture texture;
    //纹理采样平面的位置。
    public Vector3 slicePositions;
    //设置要使用的纹理过滤模式。
    FilterMode filterMode = FilterMode.Trilinear;
    //启用颜色渐变可视化。
    bool useColorRamp = true;
    //Unity 用作颜色渐变的自定义渐变。如果未指定,Unity 将使用 Google Turbo 色带。
    Gradient customColorRamp;
    private void OnSceneViewGUI(SceneView sv)
    {
        Handles.DrawTexture3DSlice(texture, slicePositions, filterMode,
            useColorRamp, useColorRamp ? customColorRamp : null);
    }
}

DrawTexture3DSDF

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
[CanEditMultipleObjects]
public class HandlesEditor : Editor
{
    //要绘制的体积纹理。
    public Texture texture;
    //与光线步长相乘的数字。光线步长是两个相邻像素之间的距离。默认值为 1。
    float stepScale;
    //渲染表面时的像素强度。当该值为正数时,Unity 将扩展渲染表面。
    //当该值为负数时,Unity 会将空的空间渲染为表面,并将表面渲染为空的空间。默认值为 0。
    float surfaceOffset;
    //Unity 用作颜色渐变的自定义渐变。如果未指定,Unity 将使用 Google Turbo 色带。
    Gradient customColorRamp;
    private void OnSceneViewGUI(SceneView sv)
    {
        Handles.DrawTexture3DSDF(texture, stepScale, surfaceOffset, customColorRamp);
    }
}

4.2 Handle:可视化操作数值(Vector3、Vector2、float等)

4.2.1 FreeMoveHandle

  • FreeMoveHandle: 创建一个不受约束的移动手柄。
 protected virtual void OnSceneGUI()
 {
     HandlesScript example = (HandlesScript)target;

     float size = HandleUtility.GetHandleSize(example.targetPosition) * 0.5f;
     Vector3 snap = Vector3.one * 0.5f;

     EditorGUI.BeginChangeCheck();
     Vector3 newTargetPosition = Handles.FreeMoveHandle(example.targetPosition, Quaternion.identity, size, snap, Handles.RectangleHandleCap);
     if (EditorGUI.EndChangeCheck())
     {
         Undo.RecordObject(example, "Change Look At Target Position");
         example.targetPosition = newTargetPosition;
         example.Update();
     }
 }
using UnityEngine;

public class HandlesScript : MonoBehaviour
{
    public Vector3 targetPosition { get { return m_TargetPosition; } set { m_TargetPosition = value; } }
    [SerializeField]
    private Vector3 m_TargetPosition = new Vector3(1f, 0f, 2f);

    public virtual void Update()
    {
        transform.LookAt(m_TargetPosition);
    }
}

1

4.2.2 FreeRotateHandle

  • FreeRotateHandle: 创建一个不受约束的旋转手柄。
 public void OnSceneGUI()
 {
     HandlesScript t = (target as HandlesScript);

     EditorGUI.BeginChangeCheck();
     Quaternion rot = Handles.FreeRotateHandle(0, t.rot, Vector3.zero, 2);
     if (EditorGUI.EndChangeCheck())
     {
         Undo.RecordObject(target, "Free Rotate");
         t.rot = rot;
         t.Update();
     }
 }
using UnityEngine;

public class HandlesScript : MonoBehaviour
{
    public Quaternion rot = Quaternion.identity;
    public void Update()
    {
        transform.rotation = rot;
    }
}

1

4.2.3 PositionHandle

  • PositionHandle: 创建一个位置手柄。
 protected virtual void OnSceneGUI()
    {
        HandlesScript example = (HandlesScript)target;

        EditorGUI.BeginChangeCheck();
        Vector3 newTargetPosition = Handles.PositionHandle(example.targetPosition, Quaternion.identity);
        if (EditorGUI.EndChangeCheck())
        {
            Undo.RecordObject(example, "Change Look At Target Position");
            example.targetPosition = newTargetPosition;
            example.Update();
        }
    }
using UnityEngine;

public class HandlesScript : MonoBehaviour
{
    public Vector3 targetPosition { get { return m_TargetPosition; } set { m_TargetPosition = value; } }
    [SerializeField]
    private Vector3 m_TargetPosition = new Vector3(1f, 0f, 2f);

    public virtual void Update()
    {
        transform.LookAt(m_TargetPosition);
    }
}

1

4.2.4 RadiusHandle

  • RadiusHandle: 创建一个场景视图半径手柄。
using UnityEngine;

public class HandlesScript : MonoBehaviour
{
    public float areaOfEffect = 1;
}
public void OnSceneGUI()
{
    HandlesScript t = (target as HandlesScript);

    EditorGUI.BeginChangeCheck();
    float areaOfEffect = Handles.RadiusHandle(Quaternion.identity, t.transform.position, t.areaOfEffect);
    if (EditorGUI.EndChangeCheck())
    {
        Undo.RecordObject(target, "Changed Area Of Effect");
        t.areaOfEffect = areaOfEffect;
    }
}

1

4.2.5 RotationHandle

  • RotationHandle: 创建一个场景视图旋转手柄。
using UnityEngine;

public class HandlesScript : MonoBehaviour
{
    public Quaternion rot = Quaternion.identity;
    public void Update()
    {
        transform.rotation = rot;
    }
}
 public void OnSceneGUI()
    {
        HandlesScript t = (target as HandlesScript );

        EditorGUI.BeginChangeCheck();
        Quaternion rot = Handles.RotationHandle(t.rot, Vector3.zero);
        if (EditorGUI.EndChangeCheck())
        {
            Undo.RecordObject(target, "Rotated RotateAt Point");
            t.rot = rot;
            t.Update();
        }
    }

1

4.2.6 ScaleHandle

  • ScaleHandle:创建一个场景视图缩放手柄。
using UnityEngine;

public class HandlesScript : MonoBehaviour
{
    public Vector3 scale = Vector3.one;
    public void Update()
    {
        transform.localScale = scale;
    }
}
 public void OnSceneGUI()
    {
        HandlesScript t = (target as HandlesScript );

        EditorGUI.BeginChangeCheck();
        Vector3 scale = Handles.ScaleHandle(t.scale, Vector3.zero, Quaternion.identity, 1);
        if (EditorGUI.EndChangeCheck())
        {
            Undo.RecordObject(target, "Scaled ScaleAt Point");
            t.scale = scale;
            t.Update();
        }
    }

1

4.2.7 ScaleValueHandle

  • ScaleValueHandle:创建一个缩放单个浮点的 3D 手柄。
using UnityEngine;

public class HandlesScript : MonoBehaviour
{
    [SerializeField]
    private Color m_Color1 = Color.red;
    [SerializeField]
    private Color m_Color2 = Color.green;

    public float amount { get { return m_Amount; } set { m_Amount = Mathf.Clamp01(value); } }
    [SerializeField, Range(0f, 1f)]
    private float m_Amount = 1f;

    private Light m_Light;

    protected virtual void OnEnable()
    {
        m_Light = GetComponent<Light>();
    }

    public virtual void Update()
    {
        m_Light.color = Color.Lerp(m_Color1, m_Color2, m_Amount);
    }
}
 protected virtual void OnSceneGUI()
    {
        LightColorLerp colorLerp = (LightColorLerp)target;

        float size = HandleUtility.GetHandleSize(colorLerp.transform.position) * 5f;
        float snap = 0.1f;

        EditorGUI.BeginChangeCheck();
        float newAmount = Handles.ScaleValueHandle(colorLerp.amount, colorLerp.transform.position, Quaternion.identity, size, Handles.ArrowHandleCap, snap);
        if (EditorGUI.EndChangeCheck())
        {
            Undo.RecordObject(colorLerp, "Change Light Color Interpolation");
            colorLerp.amount = newAmount;
            colorLerp.Update();
        }
    }

1

4.3 Caps:绘制多边形几何体(如方块,点精灵,球形,圆锥等)

4.3.1 ArrowHandleCap

  • ArrowHandleCap:绘制一个类似于移动工具所用箭头的箭头。
using System.Drawing.Drawing2D;
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
[CanEditMultipleObjects]
public class HandlesEditor : Editor
{
    float size = 1f;

    protected virtual void OnSceneGUI()
    {
        if (Event.current.type == EventType.Repaint)
        {
            Transform transform = ((HandlesScript)target).transform;
            Handles.color = Handles.yAxisColor;
            Handles.ArrowHandleCap(
                0,
                transform.position + new Vector3(3f, 0f, 0f),
                transform.rotation * Quaternion.LookRotation(Vector3.right),
                size,
                EventType.Repaint
            );
            Handles.color = Handles.yAxisColor;
            Handles.ArrowHandleCap(
                0,
                transform.position + new Vector3(0f, 3f, 0f),
                transform.rotation * Quaternion.LookRotation(Vector3.up),
                size,
                EventType.Repaint
            );
            Handles.color = Handles.yAxisColor;
            Handles.ArrowHandleCap(
                0,
                transform.position + new Vector3(0f, 0f, 3f),
                transform.rotation * Quaternion.LookRotation(Vector3.forward),
                size,
                EventType.Repaint
            );
        }
    }
}

1

4.3.2 CircleHandleCap

  • CircleHandleCap:绘制一个圆形手柄。将此手柄传递给 handle 函数。
using System.Drawing.Drawing2D;
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
[CanEditMultipleObjects]
public class HandlesEditor : Editor
{
    float size = 1f;

    protected virtual void OnSceneGUI()
    {
        if (Event.current.type == EventType.Repaint)
        {
            Transform transform = ((HandlesScript)target).transform;
            Handles.color = Handles.xAxisColor;
            Handles.CircleHandleCap(
                0,
                transform.position + new Vector3(3f, 0f, 0f),
                transform.rotation * Quaternion.LookRotation(Vector3.right),
                size,
                EventType.Repaint
            );
            Handles.color = Handles.yAxisColor;
            Handles.CircleHandleCap(
                0,
                transform.position + new Vector3(0f, 3f, 0f),
                transform.rotation * Quaternion.LookRotation(Vector3.up),
                size,
                EventType.Repaint
            );
            Handles.color = Handles.zAxisColor;
            Handles.CircleHandleCap(
                0,
                transform.position + new Vector3(0f, 0f, 3f),
                transform.rotation * Quaternion.LookRotation(Vector3.forward),
                size,
                EventType.Repaint
            );
        }
    }
}

1

4.3.3 ConeHandleCap

  • ConeHandleCap:绘制一个锥体手柄。将此手柄传递给 handle 函数。
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
[CanEditMultipleObjects]
public class HandlesEditor : Editor
{
    float size = 1f;

    protected virtual void OnSceneGUI()
    {
        if (Event.current.type == EventType.Repaint)
        {
            Transform transform = ((HandlesScript)target).transform;
            Handles.color = Handles.xAxisColor;
            Handles.ConeHandleCap(
                0,
                transform.position + new Vector3(3f, 0f, 0f),
                transform.rotation * Quaternion.LookRotation(Vector3.right),
                size,
                EventType.Repaint
            );
            Handles.color = Handles.yAxisColor;
            Handles.ConeHandleCap(
                0,
                transform.position + new Vector3(0f, 3f, 0f),
                transform.rotation * Quaternion.LookRotation(Vector3.up),
                size,
                EventType.Repaint
            );
            Handles.color = Handles.zAxisColor;
            Handles.ConeHandleCap(
                0,
                transform.position + new Vector3(0f, 0f, 3f),
                transform.rotation * Quaternion.LookRotation(Vector3.forward),
                size,
                EventType.Repaint
            );
        }
    }
}

1

4.3.4 CubeHandleCap

  • CubeHandleCap:绘制一个立方体手柄。将此手柄传递给 handle 函数。
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
[CanEditMultipleObjects]
public class HandlesEditor : Editor
{
    float size = 1f;

    protected virtual void OnSceneGUI()
    {
        if (Event.current.type == EventType.Repaint)
        {
            Transform transform = ((HandlesScript)target).transform;
            Handles.color = Handles.xAxisColor;
            Handles.CubeHandleCap(
                0,
                transform.position + new Vector3(3f, 0f, 0f),
                transform.rotation * Quaternion.LookRotation(Vector3.right),
                size,
                EventType.Repaint
            );
            Handles.color = Handles.yAxisColor;
            Handles.CubeHandleCap(
                0,
                transform.position + new Vector3(0f, 3f, 0f),
                transform.rotation * Quaternion.LookRotation(Vector3.up),
                size,
                EventType.Repaint
            );
            Handles.color = Handles.zAxisColor;
            Handles.CubeHandleCap(
                0,
                transform.position + new Vector3(0f, 0f, 3f),
                transform.rotation * Quaternion.LookRotation(Vector3.forward),
                size,
                EventType.Repaint
            );
        }
    }
}

1

4.3.5 CylinderHandleCap

  • CylinderHandleCap:绘制一个圆柱体手柄。将此手柄传递给 handle 函数。
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
[CanEditMultipleObjects]
public class HandlesEditor : Editor
{
    float size = 1f;

    protected virtual void OnSceneGUI()
    {
        if (Event.current.type == EventType.Repaint)
        {
            Transform transform = ((HandlesScript)target).transform;
            Handles.color = Handles.xAxisColor;
            Handles.CylinderHandleCap(
                0,
                transform.position + new Vector3(3f, 0f, 0f),
                transform.rotation * Quaternion.LookRotation(Vector3.right),
                size,
                EventType.Repaint
            );
            Handles.color = Handles.yAxisColor;
            Handles.CylinderHandleCap(
                0,
                transform.position + new Vector3(0f, 3f, 0f),
                transform.rotation * Quaternion.LookRotation(Vector3.up),
                size,
                EventType.Repaint
            );
            Handles.color = Handles.zAxisColor;
            Handles.CylinderHandleCap(
                0,
                transform.position + new Vector3(0f, 0f, 3f),
                transform.rotation * Quaternion.LookRotation(Vector3.forward),
                size,
                EventType.Repaint
            );
        }
    }
}

1

4.3.6 DotHandleCap

  • DotHandleCap:绘制一个圆点手柄。将此手柄传递给 handle 函数。
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    float size = 1f;

    protected virtual void OnSceneGUI()
    {
        if (Event.current.type == EventType.Repaint)
        {
            Transform transform = ((HandlesScript)target).transform;
            Handles.color = Handles.xAxisColor;
            Handles.DotHandleCap(
                0,
                transform.position + new Vector3(3f, 0f, 0f),
                transform.rotation * Quaternion.LookRotation(Vector3.right),
                size,
                EventType.Repaint
            );
            Handles.color = Handles.yAxisColor;
            Handles.DotHandleCap(
                0,
                transform.position + new Vector3(0f, 3f, 0f),
                transform.rotation * Quaternion.LookRotation(Vector3.up),
                size,
                EventType.Repaint
            );
            Handles.color = Handles.zAxisColor;
            Handles.DotHandleCap(
                0,
                transform.position + new Vector3(0f, 0f, 3f),
                transform.rotation * Quaternion.LookRotation(Vector3.forward),
                size,
                EventType.Repaint
            );
        }
    }
}

1

4.3.7 RectangleHandleCap

  • RectangleHandleCap:绘制一个矩形手柄。将此手柄传递给 handle 函数。
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    float size = 1f;

    protected virtual void OnSceneGUI()
    {
        if (Event.current.type == EventType.Repaint)
        {
            Transform transform = ((HandlesScript)target).transform;
            Handles.color = Handles.xAxisColor;
            Handles.RectangleHandleCap(
                0,
                transform.position + new Vector3(3f, 0f, 0f),
                transform.rotation * Quaternion.LookRotation(Vector3.right),
                size,
                EventType.Repaint
            );
            Handles.color = Handles.yAxisColor;
            Handles.RectangleHandleCap(
                0,
                transform.position + new Vector3(0f, 3f, 0f),
                transform.rotation * Quaternion.LookRotation(Vector3.up),
                size,
                EventType.Repaint
            );
            Handles.color = Handles.zAxisColor;
            Handles.RectangleHandleCap(
                0,
                transform.position + new Vector3(0f, 0f, 3f),
                transform.rotation * Quaternion.LookRotation(Vector3.forward),
                size,
                EventType.Repaint
            );
        }
    }
}

1

4.4 GUI

4.4.1 Label

  • Label:为位于 3D 空间中的手柄创建文本标签。
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    protected virtual void OnSceneGUI()
    {
        Handles.color = Color.red;
        Handles.Label(Vector3.zero,"测试Label");
    }
}

1

4.4.2 Button

  • Button:创建一个 3D 按钮。
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    protected virtual void OnSceneGUI()
    {
        if (Handles.Button(Vector3.zero, Quaternion.identity, 1, 2, Handles.RectangleHandleCap))
            Debug.Log("The button was pressed!");
    }
}

1

4.4.3 ScaleSlider

  • ScaleSlider:创建一个定向缩放滑动条。
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    protected virtual void OnSceneGUI()
    {
        float scale = Handles.ScaleSlider(1, Vector3.zero, Vector3.right, Quaternion.identity, 1, 0.5f);
    }
}

1

4.4.4 Slider

  • Slider:创建一个沿着一个轴移动的 3D 滑动条。
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    protected virtual void OnSceneGUI()
    {
        Vector3 newTargetPosition = Handles.Slider(Vector3.zero, Vector3.right, 1, Handles.ConeHandleCap, 0.5f);
    }
}

1

4.4.5 Slider2D

  • Slider2D:创建一个沿两个轴定义的平面移动的 3D 滑动条。
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(HandlesScript))]
public class HandlesEditor : Editor
{
    protected virtual void OnSceneGUI()
    {
        Vector3 newTargetPosition = Handles.Slider2D(Vector3.zero, Vector3.up, Vector3.right, Vector3.forward, 1, Handles.CircleHandleCap, 0.5f);
    }
}

1

4.5 Camera:摄像机

  • DrawCamera:在矩形内绘制一个摄像机。此函数还将 Camera.current 设置为 camera。它将摄像机的 pixelRect 设置为 position,但采用屏幕坐标。如果您使用高 DPI 显示屏,这可能会与 GUI 坐标有所不同。
  • ClearCamera:清除摄像机。Handle 类使用的摄像机将在使用前被清除
  • SnapValue:如果对齐为 active,则将 value 四舍五入到 snap 的最接近倍数。注意,snap 只能为正数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/332982.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(2)(2.1) Andruav Android Cellular(一)

文章目录 前言 1 Andruav 是什么&#xff1f; 2 Andruav入门 3 Andruav FPV 4 Andruav GCS App​​​​​​​ 前言 Andruav 是一个基于安卓的互联系统&#xff0c;它将安卓手机作为公司计算机&#xff0c;为你的无人机和遥控车增添先进功能。 1 Andruav 是什么&#xff…

门禁监控如何提升安全系数?这个技术,学习一下!

随着社会的不断发展和科技的快速进步&#xff0c;安全管理成为各个领域至关重要的议题。在这一背景下&#xff0c;门禁监控系统逐渐崭露头角&#xff0c;成为保障建筑物和场所安全的关键工具。 门禁监控系统不仅在提高安全性方面发挥着积极作用&#xff0c;而且通过智能化的技术…

《模拟龙生》|500行Go代码写一个随机冒险游戏|巨龙修为挑战开启

一、前言 新年就要到了&#xff0c;祝大家新的一年&#xff1a;&#x1f432; 龙行龘龘&#xff0c;&#x1f525; 前程朤朤&#xff01; 白泽花了点时间&#xff0c;用 500行 Go 代码写了一个控制台的小游戏&#xff1a;《模拟龙生》&#xff0c;在游戏中你将模拟一条新生的…

Linux系统三剑客之grep和正则表达式的介绍(一)

1.正则表达式 目录 1.正则表达式 1.什么是正则表达式 &#xff1f; 2.正则表达式的使用场景 3.正则表达式字符表示 4.它们之间的区别 2.grep命令 作用&#xff1a; 语法&#xff1a; 说明&#xff1a; 选项&#xff1a;options 重点 实例 3.后面的下次再更新。 …

C语言位域定义与使用

参考文章&#xff1a; 【C语言】详解位域定义与使用_c 语言定义位-CSDN博客 代码有修改&#xff0c;主要是变量初始化&#xff0c;原程序可能相应内存不能写。且第二个字节F不好区分各位。 #include <stdio.h>typedef struct {unsigned short b1 : 1;unsigned short b…

情人节专属--HTML制作情人节告白爱心

💕效果展示 💕html展示 <!DOCTYPE html> <html lang="en" > <head>

ros2仿真学习04 -turtlebot3实现cartographer算法建图演示

安装看这里 https://blog.csdn.net/hai411741962/article/details/135619608?spm1001.2014.3001.5502 虚拟机配置&#xff1a; 内存16g cpu 4 核 磁盘40G,20G 不够 启动仿真 ros2 launch turtlebot3_gazebo turtlebot3_world.launch.py启动成功如下 启动建图 重新开一个…

浅谈情绪的分类合集

什么是情绪分类 情绪分类&#xff0c;是指区分或者对比一种情绪与另一种情绪的方法&#xff0c;目前在情绪研究&#xff08;emotion research&#xff09;与情感科学&#xff08;affective science&#xff09;是具有争议的问题。有两个讨论情绪分类的基本观点&#xff1a; 情…

【计算机组成与体系结构Ⅱ】Tomasulo 算法模拟和分析(实验)

实验5&#xff1a;Tomasulo 算法模拟和分析 一、实验目的 1&#xff1a;加深对指令级并行性及开发的理解。 2&#xff1a;加深对 Tomasulo 算法的理解。 3&#xff1a;掌握 Tomasulo 算法在指令流出、执行、写结果各阶段对浮点操作指令以及 load 和 store 指令进行了什么处…

CC工具箱使用指南:【用地用海指标汇总】

一、简介 在湘源上画的规划用地图&#xff0c;想导出规划指标表是很容易的。 但是现在很多用地图最终是要在ArcGIS中处理的&#xff0c;想再导出指标表就比较麻烦。 这个工具的主要功能就是在ArcGIS中汇总统计&#xff0c;生成类似湘源的Excel格式用地指标表。 二、工具参数…

20240117在本地机器识别OCR法语电影的字幕效果PK

20240117在本地机器识别OCR法语电影的字幕效果PK 2024/1/17 11:18 1959 - Jirai Cracher Sur Vos Tombes [Gast, Vian].avi https://www.pianbar.net//drama/52892.html 1959[我唾弃你的坟墓]Jirai cracher sur vos tombes[BT下载/迅雷下载] magnet:?xturn:btih:7c9c99d9d048…

【备战蓝桥杯】图论重点 敲黑板啦!

蓝桥杯备赛 | 洛谷做题打卡day11 文章目录 蓝桥杯备赛 | 洛谷做题打卡day11杂务题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 题解代码我的一些话 杂务 题目描述 John 的农场在给奶牛挤奶前有很多杂务要完成&#xff0c;每一项杂务都需要一定的时间来完成它。比如&a…

canvas绘制不同样式的六角星(示例源代码)

查看专栏目录 canvas实例应用100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

Python如何便捷的执行JavaScript代码,调用JS函数

文章目录 📖 介绍 📖🏡 环境 🏡📒 实现方法 📒📝 安装📝 使用⚓️ 相关链接 ⚓️📖 介绍 📖 Python在写一些爬虫代码的时候经常需要接触到JS逆向,其中如何让Python便捷的执行JS代码就成了一个很关键的问题,本文分享一种便捷的方式实现这个需求。 🏡 环…

司铭宇老师:二手房地产中介销售培训:二手房经纪人必备的七种销售能力

二手房地产中介销售培训&#xff1a;二手房经纪人必备的七种销售能力 在房地产行业中&#xff0c;二手房经纪人扮演着至关重要的角色。他们需要具备一系列的销售能力&#xff0c;以便更好地为客户服务&#xff0c;实现业绩增长。本文将详细介绍二手房经纪人必备的七种销售能力…

带你解析Git的基础功能(三)

文章目录 前言一.远程仓库的概念二.远程仓库的操作2.1新建远程仓库2.2 克隆远程仓库2.3 向远程仓库推送2.4 拉取远程仓库2.5 忽略特殊⽂件2.6 标签管理 三.Git实战场景3.1 Git多人实战场景一准备工作由开发者1和开发者2新增加文件内容。将dev的文件合并到master上总结 3.2 Git多…

20240118-最小下降路径总和

昨天的爬楼梯以前写过&#xff0c;是一道基础的动态规划&#xff0c;就不重新写了。 题目要求 给定一个n*n的矩阵数组&#xff0c;返回通过矩阵的任何下降路径的最小和。 下降路径从第一行中的任何元素开始&#xff0c;并选择下一行中正下方或左右对角线的元素。具体来说&am…

【Flink-1.17-教程】-【三】Flink 运行架构、Flink 核心概念【并行度、算子链、任务槽】、Flink 作业提交流程

【Flink-1.17-教程】-【三】Flink 运行架构、Flink 核心概念【并行度、算子链、任务槽】、Flink 作业提交流程 1&#xff09;系统架构1.1.系统成员组成1.2.作业提交流程 2&#xff09;核心概念2.1. 并行度&#xff08;Parallelism&#xff09;2.1.1.并行子任务和并行度2.1.2.并…

如何无公网ip使用Potplayer访问群晖NAS中储存的本地资源【内网穿透】

文章目录 本教程解决的问题是&#xff1a;按照本教程方法操作后&#xff0c;达到的效果是&#xff1a;1 使用环境要求&#xff1a;2 配置webdav3 测试局域网使用potplayer访问webdav3 内网穿透&#xff0c;映射至公网4 使用固定地址在potplayer访问webdav ​ 国内流媒体平台的内…

2023 年顶级前端工具

谁不喜欢一个好的前端工具&#xff1f;在本综述中&#xff0c;您将找到去年流行的有用的前端工具&#xff0c;它们将帮助您加快开发工作流程。让我们深入了解一下&#xff01; 在过去的 12 个月里&#xff0c;我在我的时事通讯 Web Tools Weekly 中分享了数百种工具。我为前端…