Unity Editor Extensions – Handle 和Gizmos私人定制
来源:互联网 发布:圣火明尊进阶数据 编辑:程序博客网 时间:2024/06/09 23:58
孙广东 2015.6.20
先贴一个 Grid网格吧。 可以标记一个对象的正方形范围等
拖拽到指定的对象就OK了。
using UnityEngine;using System.Collections; // DrawGizmoGrid.cs// draws a useful reference grid in the editor in Unity. // 09/01/15 - Hayden Scott-Baron// twitter.com/docky // no attribution needed, but please tell me if you like it ^_^ public class DrawGizmoGrid : MonoBehaviour{// universal grid scalepublic float gridScale = 1f; // extents of the gridpublic int minX = -15; public int minY = -15; public int maxX = 15; public int maxY = 15; // nudges the whole grid relpublic Vector3 gridOffset = Vector3.zero; // is this an XY or an XZ grid?public bool topDownGrid = true; // choose a colour for the gizmospublic int gizmoMajorLines = 5; public Color gizmoLineColor = new Color (0.4f, 0.4f, 0.3f, 1f); // rename + centre the gameobject upon first time dragging the script into the editor. void Reset (){if (name == "GameObject")name = "~~ GIZMO GRID ~~"; transform.position = Vector3.zero; } // draw the grid :) void OnDrawGizmos (){// orient to the gameobject, so you can rotate the grid independently if desiredGizmos.matrix = transform.localToWorldMatrix; // set coloursColor dimColor = new Color(gizmoLineColor.r, gizmoLineColor.g, gizmoLineColor.b, 0.25f* gizmoLineColor.a); Color brightColor = Color.Lerp (Color.white, gizmoLineColor, 0.75f); // draw the horizontal linesfor (int x = minX; x < maxX+1; x++){// find major linesGizmos.color = (x % gizmoMajorLines == 0 ? gizmoLineColor : dimColor); if (x == 0)Gizmos.color = brightColor; Vector3 pos1 = new Vector3(x, minY, 0) * gridScale; Vector3 pos2 = new Vector3(x, maxY, 0) * gridScale; // convert to topdown/overhead units if necessaryif (topDownGrid){pos1 = new Vector3(pos1.x, 0, pos1.y); pos2 = new Vector3(pos2.x, 0, pos2.y); } Gizmos.DrawLine ((gridOffset + pos1), (gridOffset + pos2)); } // draw the vertical linesfor (int y = minY; y < maxY+1; y++){// find major linesGizmos.color = (y % gizmoMajorLines == 0 ? gizmoLineColor : dimColor); if (y == 0)Gizmos.color = brightColor; Vector3 pos1 = new Vector3(minX, y, 0) * gridScale; Vector3 pos2 = new Vector3(maxX, y, 0) * gridScale; // convert to topdown/overhead units if necessaryif (topDownGrid){pos1 = new Vector3(pos1.x, 0, pos1.y); pos2 = new Vector3(pos2.x, 0, pos2.y); } Gizmos.DrawLine ((gridOffset + pos1), (gridOffset + pos2)); }}}
3、Layingthe groundwork for our handles为我们处理奠定基础
4、Creatinga handle
5、Drawinglines in the scene view
6、Coloringhandles
7、Dynamicallysizing handles
public class TerrainPiece : MonoBehaviour { public SpriteRenderer spriteRenderer; public Vector3 mountPoint; void Awake () { if (spriteRenderer == null) spriteRenderer = GetComponentInChildren<SpriteRenderer>(); }}
下面就来定制这个类:
[CustomEditor(typeof(TerrainPiece))]public class TerrainPieceEditor : Editor{ SerializedProperty mountPointProp; // TerrainPiece. mountPoint TerrainPiece terrainPiece; // TerrainPiece void OnEnable() { terrainPiece = (TerrainPiece) target; mountPointProp = serializedObject.FindProperty("mountPoint"); } void OnSceneGUI() { serializedObject.Update(); Vector3 worldMountPt = terrainPiece.transform.TransformPoint(mountPointProp.vector3Value); // 转成世界坐标系 float sizeFactor = HandleUtility.GetHandleSize(worldMountPt) * 0.25f; // 这样就不会随着scene面板的远近而动态改变大小,一直不变。 Handles.color = Color.magenta; // 设置颜色 worldMountPt = Handles.FreeMoveHandle(worldMountPt, Quaternion.identity, sizeFactor * 0.2f, Vector3.zero, Handles.RectangleCap); // 拖动handle来改变值 Handles.DrawLine(worldMountPt - Vector3.up * sizeFactor, worldMountPt + Vector3.up * sizeFactor); Handles.DrawLine(worldMountPt - Vector3.right * sizeFactor, worldMountPt + Vector3.right * sizeFactor); Vector3 mountPointLocal = terrainPiece.transform.InverseTransformPoint(worldMountPt); // 转成相对父级的本地坐标 mountPointLocal.z = 0; mountPointProp.vector3Value = mountPointLocal; serializedObject.ApplyModifiedProperties(); }}
8、Previewingthe status bar
9、Sizinga status bar with handles
10、Snappinghandles
public class Statusbar : MonoBehaviour { publicstring barTextureName = "statusbar"; //The name of our bar texture (must be located in Resources folder) publicGradient colorGrad; publicVector2 offset; publicVector2 drawSize = new Vector2(5f, 1f); protectedTexture2D barTexture; protectedfloat targetPercent = 1f; //The normalized percentage the bar is to represent protectedfloat displayPercent = 1f; //The value actually used to render the bar, allows us to animate the bar towardthe targetPercent value protectedRect srcRect; //The rect of the area to use from the source texture protectedRect scrExtents; //The rect that defines the screen area extents protectedVector2 size;。。。。。。。。。。。。。。。。。。。。。。}
---- Editor 的定制显示?:
[CustomEditor(typeof(Statusbar))]public class StatusbarEditor : Editor { SerializedPropertyoffsetProp; SerializedPropertydrawSizeProp; Statusbarbar; //要定制的类 staticTexture2D barTexture; //用于显示加载的图片 voidOnEnable() { bar= (Statusbar) target; offsetProp= serializedObject.FindProperty("offset"); drawSizeProp= serializedObject.FindProperty("drawSize"); barTexture= Resources.Load(bar.barTextureName, typeof(Texture2D)) as Texture2D; } voidOnSceneGUI() { serializedObject.Update(); DrawBar(); DrawHandles(); serializedObject.ApplyModifiedProperties(); } voidDrawBar() { Vector2pos = HandleUtility.WorldToGUIPoint(bar.transform.position +(Vector3)bar.offset); // 坐标转换 Vector2size = bar.drawSize / bar.GetWorldUnitsPerPixel(Camera.current); //大小 RectscreenRect = new Rect(pos.x - size.x * 0.5f, pos.y - size.y * 0.5f, size.x, size.y); // 显示位置 Handles.BeginGUI(); GUI.DrawTexture(screenRect,barTexture); //显示图片 Handles.EndGUI(); } voidDrawHandles() { Handles.matrix= bar.transform.localToWorldMatrix; // 矩阵变换初值 Vector3barPos = offsetProp.vector2Value; //位置初值 floathandleSize = HandleUtility.GetHandleSize(barPos) * 0.1f; // 大小初值 Handles.color= Color.green; //设置颜色 //Bar position/offset: //计算位置,这是中间的圆handle barPos= Handles.FreeMoveHandle(barPos, Quaternion.identity, handleSize, Vector3.zero,Handles.CircleCap); //Save new offset: offsetProp.vector2Value= barPos; // 通过拖拽改变大小 //Top handle: Vector3handlePt = barPos + Vector3.up * bar.drawSize.y * 0.5f; Vector3newPos = Handles.FreeMoveHandle(handlePt, Quaternion.identity, handleSize,Vector3.zero, Handles.RectangleCap); Vector2delta = new Vector2(0, newPos.y - handlePt.y); drawSizeProp.vector2Value+= delta; //Bottom handle: handlePt= barPos + Vector3.down * bar.drawSize.y * 0.5f; newPos= Handles.FreeMoveHandle(handlePt, Quaternion.identity, handleSize,Vector3.zero, Handles.RectangleCap); delta= new Vector2(0, newPos.y - handlePt.y); drawSizeProp.vector2Value-= delta; //Left handle: handlePt= barPos + Vector3.left * bar.drawSize.x * 0.5f; newPos= Handles.FreeMoveHandle(handlePt, Quaternion.identity, handleSize, Vector3.zero,Handles.RectangleCap); delta= new Vector2(newPos.x - handlePt.x, 0); drawSizeProp.vector2Value-= delta; //Right handle: handlePt= barPos + Vector3.right * bar.drawSize.x * 0.5f; newPos= Handles.FreeMoveHandle(handlePt, Quaternion.identity, handleSize,Vector3.zero, Handles.RectangleCap); delta= new Vector2(newPos.x - handlePt.x, 0); drawSizeProp.vector2Value+= delta; }}
运行效果:
11、Executingscripts in edit mode
[ExecuteInEditMode]public class Statusbar : MonoBehaviour { }
这样Statusbar中的代码就会执行了,在Game面板中就可以看到ship的上方有两个血条。
如果我拖动Scene面板中的血条或者大小,下方就会跟着改变。
还想这样改变大小怎么办:
添加如下:
[ExecuteInEditMode]public class Statusbar : MonoBehaviour { voidOnGUI() {………………………………………………..#if UNITY_EDITOR if(!Application.isPlaying) size= drawSize / GetWorldUnitsPerPixel(Camera.main);#endif……………………………………………….. }
12、Drawinga detection range indicator
// 可以在Scene中动态改变坦克的攻击范围:
[CustomEditor(typeof(GroundTurretAI))]public class GroundTurretAIEditor : Editor { GroundTurretAIai; SerializedPropertyrangeProp; voidOnEnable() { ai= (GroundTurretAI) target; // 要定制的脚本 rangeProp= serializedObject.FindProperty("detectionRange"); // 得到其中的范围属性 } voidOnSceneGUI() { serializedObject.Update(); Handles.color= Color.green; // RadiusHandle来拖来改变值 rangeProp.floatValue= Handles.RadiusHandle(Quaternion.identity, ai.transform.position,rangeProp.floatValue); serializedObject.ApplyModifiedProperties(); }}
不过通过 拖动scene的视图可以发现,这个东西是3D的球形。
在13、中单独做一个2D的
13、Visualizingour range indicator for 2D games
[CustomEditor(typeof(GroundTurretAI))]public class GroundTurretAIEditor : Editor { GroundTurretAIai; SerializedPropertyrangeProp; void OnEnable() { ai= (GroundTurretAI) target; rangeProp= serializedObject.FindProperty("detectionRange"); } voidOnSceneGUI() { serializedObject.Update(); Handles.color= Color.green; Vector3aiPos = ai.transform.position; floathandleSize = HandleUtility.GetHandleSize(aiPos) * 0.15f; //Left handle: Vector3handlePos = aiPos + Vector3.left * rangeProp.floatValue; handlePos= Handles.FreeMoveHandle(handlePos, Quaternion.identity, handleSize,Vector3.zero, Handles.SphereCap); rangeProp.floatValue= Vector3.Distance(aiPos, handlePos); //Right handle: handlePos= aiPos + Vector3.right * rangeProp.floatValue; handlePos= Handles.FreeMoveHandle(handlePos, Quaternion.identity, handleSize,Vector3.zero, Handles.SphereCap); rangeProp.floatValue= Vector3.Distance(aiPos, handlePos); //Top handle: handlePos= aiPos + Vector3.up * rangeProp.floatValue; handlePos= Handles.FreeMoveHandle(handlePos, Quaternion.identity, handleSize,Vector3.zero, Handles.SphereCap); rangeProp.floatValue= Vector3.Distance(aiPos, handlePos); //Bottom handle: handlePos= aiPos + Vector3.down * rangeProp.floatValue; handlePos= Handles.FreeMoveHandle(handlePos, Quaternion.identity, handleSize,Vector3.zero, Handles.SphereCap); rangeProp.floatValue= Vector3.Distance(aiPos, handlePos); //Detection area: Handles.color= new Color(0, 1f, 0, 0.15f); Handles.DrawSolidDisc(aiPos,Vector3.back, rangeProp.floatValue); serializedObject.ApplyModifiedProperties(); }}
看看效果:
通过拖动四个中的任何一个绿色的小圆,就可以改变范围了。
14、Drawingthe turret field of fire handles
[CustomEditor(typeof(GroundTurret))]public class GroundTurretEditor : Editor{ constfloat arcRadius = 12f; SerializedPropertyminAngleProp; SerializedPropertymaxAngleProp; GroundTurretturret; voidOnEnable() { turret= (GroundTurret) target; // 要定制的脚本 //目标属性 minAngleProp= serializedObject.FindProperty("minAngle"); maxAngleProp= serializedObject.FindProperty("maxAngle"); } voidOnSceneGUI() { serializedObject.Update(); //Set the handle color: Handles.color= Color.red; //Draw handle controllings the minimum angle: Vector3handlePos = turret.transform.position +turret.transform.TransformDirection(HandleHelper.GetVectorFromAngle(turret.minAngle))* arcRadius; floathandleSize = HandleUtility.GetHandleSize(handlePos) * 0.1f; handlePos= Handles.FreeMoveHandle(handlePos, Quaternion.identity, handleSize,Vector3.zero, Handles.CircleCap); //Calculate the angle from the new handle position: minAngleProp.floatValue= HandleHelper.GetAngleFromHandlePos(handlePos, turret.transform); //Draw handle controllings the maximum angle: handlePos= turret.transform.position +turret.transform.TransformDirection(HandleHelper.GetVectorFromAngle(turret.maxAngle))* arcRadius; handleSize= HandleUtility.GetHandleSize(handlePos) * 0.1f; handlePos= Handles.FreeMoveHandle(handlePos, Quaternion.identity, handleSize,Vector3.zero, Handles.CircleCap); //Calculate the angle from the new handle position: maxAngleProp.floatValue= HandleHelper.GetAngleFromHandlePos(handlePos, turret.transform); serializedObject.ApplyModifiedProperties(); }}
通过拖动两个红色的小圆圈,就确定了,炮筒的攻击视野了。
15、Visualizingthe turret field of fire
就在14、中的最后添加如下的内容:
//Calculate the angle from the new handle position: maxAngleProp.floatValue= HandleHelper.GetAngleFromHandlePos(handlePos, turret.transform); //Draw field-of-fire arc: Handles.color= new Color(1f, 0, 0, 0.1f); Vector3startVec = turret.transform.TransformDirection(HandleHelper.GetVectorFromAngle(minAngleProp.floatValue)); Handles.DrawSolidArc(turret.transform.position,Vector3.forward, startVec, maxAngleProp.floatValue - minAngleProp.floatValue,arcRadius); serializedObject.ApplyModifiedProperties();
看看效果呢?
16、IntroducingGizmos
来到 Gun.cs的脚本中添加如下的函数:
例如:
voidOnDrawGizmos () // 函数会一直执行 { Gizmos.DrawSphere(transform.position, 3f);}
void OnDrawGizmosSelected() // 函数只有脚本所在对象被选择时执行 { Vector3shotVector = Vector3.zero; Vector3arrowTip; Vector3arrowLeft = Vector3.zero; Vector3arrowRight = Vector3.zero; floatarrowLength = 5f; switch(direction) { caseShotDirection.Up: shotVector= Vector3.up; arrowLeft= Vector3.left * arrowLength * 0.2f; arrowRight= -arrowLeft; break; caseShotDirection.Down: shotVector= Vector3.down; arrowLeft= Vector3.right * arrowLength * 0.2f; arrowRight= -arrowLeft; break; caseShotDirection.Left: shotVector= Vector3.left; arrowLeft= Vector3.down * arrowLength * 0.2f; arrowRight= -arrowLeft; break; caseShotDirection.Right: shotVector= Vector3.right; arrowLeft= Vector3.up * arrowLength * 0.2f; arrowRight= -arrowLeft; break; } arrowTip= shotVector * arrowLength; arrowLeft+= shotVector * arrowLength * 0.7f; arrowRight+= shotVector * arrowLength * 0.7f; Gizmos.color= Color.yellow; Gizmos.matrix= transform.localToWorldMatrix; Gizmos.DrawLine(arrowTip,Vector3.zero); Gizmos.DrawLine(arrowTip,arrowLeft); Gizmos.DrawLine(arrowTip,arrowRight); }
17、DrawingGizmos in a custom editor to complete our course
在16中,把相当于Editor的内容写在逻辑脚本中很不合适。
所以:
[CustomEditor(typeof(Gun))]public class GunEditor : Editor { [DrawGizmo(GizmoType.SelectedOrChild)] staticvoid DrawDirection(Gun gun, GizmoType gizmoType) { if(GizmoType.Selected == (gizmoType & GizmoType.Selected)) // 脚本所在对象被选择就不执行,父对象没有问题: return; Vector3shotVector = Vector3.zero; Vector3arrowTip; Vector3arrowLeft = Vector3.zero; Vector3arrowRight = Vector3.zero; floatarrowLength = 5f; switch(gun.direction) { caseGun.ShotDirection.Up: shotVector= Vector3.up; arrowLeft= Vector3.left * arrowLength * 0.2f; arrowRight= -arrowLeft; break; caseGun.ShotDirection.Down: shotVector= Vector3.down; arrowLeft= Vector3.right * arrowLength * 0.2f; arrowRight= -arrowLeft; break; caseGun.ShotDirection.Left: shotVector= Vector3.left; arrowLeft= Vector3.down * arrowLength * 0.2f; arrowRight= -arrowLeft; break; caseGun.ShotDirection.Right: shotVector= Vector3.right; arrowLeft= Vector3.up * arrowLength * 0.2f; arrowRight= -arrowLeft; break; } arrowTip= shotVector * arrowLength; arrowLeft+= shotVector * arrowLength * 0.7f; arrowRight+= shotVector * arrowLength * 0.7f; Gizmos.color= Color.yellow; Gizmos.matrix= gun.transform.localToWorldMatrix; Gizmos.DrawLine(arrowTip,Vector3.zero); Gizmos.DrawLine(arrowTip,arrowLeft); Gizmos.DrawLine(arrowTip,arrowRight); }}
- Unity Editor Extensions – Handle 和Gizmos私人定制
- Unity Editor Extensions – Inspectors私人定制
- Unity Editor Extensions – Menu Items私人定制
- Unity Editor Extensions – Menu Items私人定制
- UNITY EDITOR EXTENSIONS – MENU ITEMS[详]
- Unity Editor 编辑器扩展 九 Gizmos
- Unity Editor 基础篇(五):Gizmos
- Unity Editor 编辑器扩展 十 Handle控件
- 【Unity】Gizmos:可视化Debug
- Unity中Gizmos 画线参考
- 私人定制 观感
- 私人定制注释
- 2014上半年私人定制
- 私人定制--家庭理财软件
- 私人定制推送铃声
- unity3d控制台 私人定制
- 私人定制:linux系统
- LaTex:私人定制
- 实时大数据处理性能瓶颈的测试
- Hadoop之——数据类型
- CSDN blog停更,已切博客园
- 实时大数据处理性能瓶颈
- android简易双屏支持
- Unity Editor Extensions – Handle 和Gizmos私人定制
- asio中奇怪的代码
- POJ1611---The Suspects
- 2015-05-26 为RHEL7设置本地光盘yum并安装net-tools
- eclipse新建的android application project目录下src和layout为空
- UIScrollView 滚动视图 (实例)
- 扩展HT for Web之HTML5表格组件的Renderer和Editor
- HDU1856---More is better
- mysql 数据库优化总结