孙广东 2015.6.20
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私人定制
原文地址:http://blog.csdn.net/u010019717/article/details/46039081