[Unity实战]攻击范围的绘制

原文链接:http://blog.csdn.net/lyh916/article/details/50383376

效果图:












代码如下:

[csharp]  view plain  copy
 
  1. using UnityEngine;  
  2. using System.Collections.Generic;  
  3.   
  4. public class DrawTool : MonoBehaviour {  
  5.   
  6.     private static LineRenderer GetLineRenderer(Transform t)  
  7.     {  
  8.         LineRenderer lr = t.GetComponent();  
  9.         if (lr == null)  
  10.         {  
  11.             lr = t.gameObject.AddComponent();  
  12.         }  
  13.         lr.SetWidth(0.1f, 0.1f);  
  14.         return lr;  
  15.     }  
  16.   
  17.     public static void DrawLine(Transform t, Vector3 start, Vector3 end)  
  18.     {  
  19.         LineRenderer lr = GetLineRenderer(t);  
  20.         lr.SetVertexCount(2);  
  21.         lr.SetPosition(0, start);  
  22.         lr.SetPosition(1, end);  
  23.     }  
  24.   
  25.     //绘制空心扇形    
  26.     public static void DrawSector(Transform t, Vector3 center, float angle, float radius)  
  27.     {  
  28.         LineRenderer lr = GetLineRenderer(t);  
  29.         int pointAmount = 100;//点的数目,值越大曲线越平滑    
  30.         float eachAngle = angle / pointAmount;  
  31.         Vector3 forward = t.forward;  
  32.   
  33.         lr.SetVertexCount(pointAmount);  
  34.         lr.SetPosition(0, center);  
  35.         lr.SetPosition(pointAmount - 1, center);  
  36.   
  37.         for (int i = 1; i < pointAmount - 1; i++)  
  38.         {  
  39.             Vector3 pos = Quaternion.Euler(0f, -angle / 2 + eachAngle * (i - 1), 0f) * forward * radius + center;  
  40.             lr.SetPosition(i, pos);  
  41.         }  
  42.     }  
  43.   
  44.     //绘制空心圆    
  45.     public static void DrawCircle(Transform t, Vector3 center, float radius)  
  46.     {  
  47.         LineRenderer lr = GetLineRenderer(t);  
  48.         int pointAmount = 100;//点的数目,值越大曲线越平滑    
  49.         float eachAngle = 360f / pointAmount;  
  50.         Vector3 forward = t.forward;  
  51.   
  52.         lr.SetVertexCount(pointAmount + 1);  
  53.   
  54.         for (int i = 0; i <= pointAmount; i++)  
  55.         {  
  56.             Vector3 pos = Quaternion.Euler(0f, eachAngle * i, 0f) * forward * radius + center;  
  57.             lr.SetPosition(i, pos);  
  58.         }  
  59.     }  
  60.   
  61.     //绘制空心长方形  
  62.     //以长方形的底边中点为攻击方位置(从俯视角度来看)  
  63.     public static void DrawRectangle(Transform t, Vector3 bottomMiddle, float length, float width)  
  64.     {  
  65.         LineRenderer lr = GetLineRenderer(t);  
  66.         lr.SetVertexCount(5);  
  67.   
  68.         lr.SetPosition(0, bottomMiddle - t.right * (width / 2));  
  69.         lr.SetPosition(1, bottomMiddle - t.right * (width / 2) + t.forward * length);  
  70.         lr.SetPosition(2, bottomMiddle + t.right * (width / 2) + t.forward * length);  
  71.         lr.SetPosition(3, bottomMiddle + t.right * (width / 2));  
  72.         lr.SetPosition(4, bottomMiddle - t.right * (width / 2));  
  73.     }  
  74.   
  75.     //绘制空心长方形2D  
  76.     //distance指的是这个长方形与Transform t的中心点的距离  
  77.     public static void DrawRectangle2D(Transform t, float distance, float length, float width)  
  78.     {  
  79.         LineRenderer lr = GetLineRenderer(t);  
  80.         lr.SetVertexCount(5);  
  81.   
  82.         if (MathTool.IsFacingRight(t))  
  83.         {  
  84.             Vector2 forwardMiddle = new Vector2(t.position.x + distance, t.position.y);  
  85.             lr.SetPosition(0, forwardMiddle + new Vector2(0, width / 2));  
  86.             lr.SetPosition(1, forwardMiddle + new Vector2(length, width / 2));  
  87.             lr.SetPosition(2, forwardMiddle + new Vector2(length, -width / 2));  
  88.             lr.SetPosition(3, forwardMiddle + new Vector2(0, -width / 2));  
  89.             lr.SetPosition(4, forwardMiddle + new Vector2(0, width / 2));  
  90.         }  
  91.         else  
  92.         {  
  93.             Vector2 forwardMiddle = new Vector2(t.position.x - distance, t.position.y);  
  94.             lr.SetPosition(0, forwardMiddle + new Vector2(0, width / 2));  
  95.             lr.SetPosition(1, forwardMiddle + new Vector2(-length, width / 2));  
  96.             lr.SetPosition(2, forwardMiddle + new Vector2(-length, -width / 2));  
  97.             lr.SetPosition(3, forwardMiddle + new Vector2(0, -width / 2));  
  98.             lr.SetPosition(4, forwardMiddle + new Vector2(0, width / 2));  
  99.         }  
  100.     }  
  101.   
  102.   
  103.     public static GameObject go;  
  104.     public static MeshFilter mf;  
  105.     public static MeshRenderer mr;  
  106.     public static Shader shader;  
  107.     private static GameObject CreateMesh(List vertices)  
  108.     {  
  109.         int[] triangles;  
  110.         Mesh mesh = new Mesh();  
  111.   
  112.         int triangleAmount = vertices.Count - 2;  
  113.         triangles = new int[3 * triangleAmount];  
  114.   
  115.         //根据三角形的个数,来计算绘制三角形的顶点顺序(索引)      
  116.         //顺序必须为顺时针或者逆时针      
  117.         for (int i = 0; i < triangleAmount; i++)  
  118.         {  
  119.             triangles[3 * i] = 0;//固定第一个点      
  120.             triangles[3 * i + 1] = i + 1;  
  121.             triangles[3 * i + 2] = i + 2;  
  122.         }  
  123.   
  124.         if (go == null)  
  125.         {  
  126.             go = new GameObject("mesh");  
  127.             go.transform.position = new Vector3(0, 0.1f, 0);//让绘制的图形上升一点,防止被地面遮挡  
  128.             mf = go.AddComponent();  
  129.             mr = go.AddComponent();  
  130.             shader = Shader.Find("Unlit/Color");  
  131.         }  
  132.   
  133.         mesh.vertices = vertices.ToArray();  
  134.         mesh.triangles = triangles;  
  135.   
  136.         mf.mesh = mesh;  
  137.         mr.material.shader = shader;  
  138.         mr.material.color = Color.red;  
  139.      
  140.         return go;  
  141.     }  
  142.   
  143.     //绘制实心扇形    
  144.     public static void DrawSectorSolid(Transform t, Vector3 center, float angle, float radius)  
  145.     {  
  146.         int pointAmount = 100;//点的数目,值越大曲线越平滑    
  147.         float eachAngle = angle / pointAmount;  
  148.         Vector3 forward = t.forward;  
  149.   
  150.         List vertices = new List();  
  151.         vertices.Add(center);  
  152.   
  153.         for (int i = 1; i < pointAmount - 1; i++)  
  154.         {  
  155.             Vector3 pos = Quaternion.Euler(0f, -angle / 2 + eachAngle * (i - 1), 0f) * forward * radius + center;  
  156.             vertices.Add(pos);  
  157.         }  
  158.   
  159.         CreateMesh(vertices);  
  160.     }  
  161.   
  162.     //绘制实心圆    
  163.     public static void DrawCircleSolid(Transform t, Vector3 center, float radius)  
  164.     {  
  165.         int pointAmount = 100;//点的数目,值越大曲线越平滑    
  166.         float eachAngle = 360f / pointAmount;  
  167.         Vector3 forward = t.forward;  
  168.   
  169.         List vertices = new List();  
  170.   
  171.         for (int i = 0; i <= pointAmount; i++)  
  172.         {  
  173.             Vector3 pos = Quaternion.Euler(0f, eachAngle * i, 0f) * forward * radius + center;  
  174.             vertices.Add(pos);  
  175.         }  
  176.   
  177.         CreateMesh(vertices);  
  178.     }  
  179.   
  180.     //绘制实心长方形  
  181.     //以长方形的底边中点为攻击方位置(从俯视角度来看)  
  182.     public static void DrawRectangleSolid(Transform t, Vector3 bottomMiddle, float length, float width)  
  183.     {  
  184.         List vertices = new List();  
  185.   
  186.         vertices.Add(bottomMiddle - t.right * (width / 2));  
  187.         vertices.Add(bottomMiddle - t.right * (width / 2) + t.forward * length);  
  188.         vertices.Add(bottomMiddle + t.right * (width / 2) + t.forward * length);  
  189.         vertices.Add(bottomMiddle + t.right * (width / 2));  
  190.   
  191.         CreateMesh(vertices);  
  192.     }  
  193.   
  194.     //绘制实心长方形2D  
  195.     //distance指的是这个长方形与Transform t的中心点的距离  
  196.     public static void DrawRectangleSolid2D(Transform t, float distance, float length, float width)  
  197.     {  
  198.         List vertices = new List();  
  199.   
  200.         if (MathTool.IsFacingRight(t))  
  201.         {  
  202.             Vector3 forwardMiddle = new Vector3(t.position.x + distance, t.position.y);  
  203.             vertices.Add(forwardMiddle + new Vector3(0, width / 2));  
  204.             vertices.Add(forwardMiddle + new Vector3(length, width / 2));  
  205.             vertices.Add(forwardMiddle + new Vector3(length, -width / 2));  
  206.             vertices.Add(forwardMiddle + new Vector3(0, -width / 2));  
  207.         }  
  208.         else  
  209.         {  
  210.             //看不到颜色但点击mesh可以看到形状  
  211.             Vector3 forwardMiddle = new Vector3(t.position.x - distance, t.position.y);  
  212.             vertices.Add(forwardMiddle + new Vector3(0, width / 2));  
  213.             vertices.Add(forwardMiddle + new Vector3(-length, width / 2));  
  214.             vertices.Add(forwardMiddle + new Vector3(-length, -width / 2));  
  215.             vertices.Add(forwardMiddle + new Vector3(0, -width / 2));  
  216.         }  
  217.   
  218.         CreateMesh(vertices);  
  219.     }  
  220.   
  221. }  


测试:

[csharp]  view plain  copy
 
  1. using UnityEngine;  
  2. using System.Collections;  
  3.   
  4. public class TestDraw : MonoBehaviour {  
  5.   
  6.     void Start ()   
  7.     {  
  8.         //DrawTool.DrawSector(transform, transform.localPosition, 60, 3);  
  9.   
  10.         //DrawTool.DrawCircle(transform, transform.localPosition, 3);  
  11.   
  12.         //DrawTool.DrawRectangle(transform, transform.localPosition, 5, 2);  
  13.   
  14.         //DrawTool.DrawSectorSolid(transform, transform.localPosition, 60, 3);  
  15.   
  16.         //DrawTool.DrawCircleSolid(transform, transform.localPosition, 3);  
  17.   
  18.         DrawTool.DrawRectangleSolid(transform, transform.localPosition, 5, 2);  
  19.     }  
  20.       
  21. }  

然后,为了更好地测试数据,应该要有这样一个东西:


[csharp]  view plain  copy
 
  1. using UnityEngine;  
  2. using System.Collections;  
  3.   
  4. public enum DrawType  
  5. {  
  6.     DrawSector,              //绘制空心扇形  
  7.     DrawCircle,              //绘制空心圆  
  8.     DrawRectangle,           //绘制空心长方形  
  9.     DrawRectangle2D,         //绘制空心长方形2D  
  10.     DrawSectorSolid,         //绘制实心扇形  
  11.     DrawCircleSolid,         //绘制实心圆  
  12.     DrawRectangleSolid,      //绘制实心长方形  
  13.     DrawRectangleSolid2D,    //绘制实心长方形2D  
  14. }  
  15.   
  16. ///   
  17. /// 要把动画上的脚本(继承StateMachineBehaviour)取消勾选  
  18. ///   
  19. public class DebugDistanceAngle : MonoBehaviour {  
  20.   
  21.     private GameObject go;  
  22.     private Animator animator;  
  23.   
  24.     public string modelName;//角色路径  
  25.     public string animationName;//动画名字,即Animator窗口看到的动画名字  
  26.   
  27.     public float time;//播放进度  
  28.     public DrawType drawType;  
  29.   
  30.     public float distance;  
  31.     public float angle;  
  32.     public float radius;  
  33.     public float length;  
  34.     public float width;  
  35.   
  36.     void Start ()   
  37.     {  
  38.         if (modelName.Length > 0)  
  39.         {  
  40.             go = Instantiate(Resources.Load(modelName));  
  41.             go.transform.localPosition = Vector3.zero;  
  42.             animator = go.GetComponent();  
  43.         }  
  44.     }  
  45.       
  46.     void Update ()   
  47.     {  
  48.         if ((go != null) && (time != 0))  
  49.         {  
  50.             animator.Play(animationName, 0, time);   
  51.         }  
  52.   
  53.         switch (drawType)  
  54.         {  
  55.             case DrawType.DrawSector :  
  56.                 DrawTool.DrawSector(go.transform, go.transform.position, angle, radius);  
  57.                 break;  
  58.             case DrawType.DrawCircle:  
  59.                 DrawTool.DrawCircle(go.transform, go.transform.position, radius);  
  60.                 break;  
  61.             case DrawType.DrawRectangle:  
  62.                 DrawTool.DrawRectangle(go.transform, go.transform.position, length, width);  
  63.                 break;  
  64.             case DrawType.DrawRectangle2D:  
  65.                 DrawTool.DrawRectangle2D(go.transform, distance, length, width);  
  66.                 break;  
  67.             case DrawType.DrawSectorSolid:  
  68.                 DrawTool.DrawSectorSolid(go.transform, go.transform.position, angle, radius);  
  69.                 break;  
  70.             case DrawType.DrawCircleSolid:  
  71.                 DrawTool.DrawCircleSolid(go.transform, go.transform.position, radius);  
  72.                 break;  
  73.             case DrawType.DrawRectangleSolid:  
  74.                 DrawTool.DrawRectangleSolid(go.transform, go.transform.position, length, width);  
  75.                 break;  
  76.             case DrawType.DrawRectangleSolid2D:  
  77.                 DrawTool.DrawRectangleSolid2D(go.transform, distance, length, width);  
  78.                 break;  
  79.             default :  
  80.                 break;  
  81.         }  
  82.     }  
  83.   
  84. }  

[csharp]  view plain  copy
 
  1. using UnityEngine;  
  2. using System.Collections;  
  3. using UnityEditor;  
  4.   
  5. [CustomEditor(typeof(DebugDistanceAngle))]  
  6. [ExecuteInEditMode]  
  7. public class DebugDistanceAngleEditor : Editor {  
  8.   
  9.     private bool canGetDragEvent;  
  10.   
  11.     public override void OnInspectorGUI()  
  12.     {  
  13.         DebugDistanceAngle d = target as DebugDistanceAngle;  
  14.   
  15.         EditorGUILayout.LabelField("请把角色放在Resources文件夹中,点击Play之后将通过Resources进行加载");  
  16.         canGetDragEvent = EditorGUILayout.Toggle("通过拖拽获取角色路径", canGetDragEvent);  
  17.         EditorGUILayout.LabelField("角色路径");  
  18.         if (canGetDragEvent)  
  19.         {  
  20.             if (Event.current.type == EventType.DragExited)  
  21.             {  
  22.                 if (DragAndDrop.paths != null && DragAndDrop.paths.Length > 0)  
  23.                 {  
  24.                     string s = DragAndDrop.paths[0];  
  25.                     s = s.Substring(s.IndexOf("Resources/"));   
  26.                     s = s.Remove(0, "Resources/".Length);  
  27.                     s = s.Substring(0, s.IndexOf('.'));  
  28.                     d.modelName = s;  
  29.                 }  
  30.             }  
  31.         }  
  32.         d.modelName = EditorGUILayout.TextArea(d.modelName);  
  33.   
  34.         d.animationName = EditorGUILayout.TextField("动画名字", d.animationName);  
  35.   
  36.         EditorGUILayout.LabelField("播放进度");  
  37.         d.time = EditorGUILayout.Slider(d.time, 0, 1);  
  38.   
  39.         d.drawType = (DrawType)EditorGUILayout.EnumPopup("绘制类型" ,d.drawType);  
  40.         switch (d.drawType)  
  41.         {  
  42.             case DrawType.DrawSector:  
  43.                 EditorGUILayout.LabelField("绘制空心扇形");  
  44.                 EditorGUILayout.LabelField("角度");  
  45.                 d.angle = EditorGUILayout.Slider(d.angle, 0, 180);  
  46.                 EditorGUILayout.LabelField("半径");  
  47.                 d.radius = EditorGUILayout.Slider(d.radius, 0, 10);  
  48.                 break;  
  49.   
  50.   
  51.             case DrawType.DrawCircle:  
  52.                 EditorGUILayout.LabelField("绘制空心圆");  
  53.                 EditorGUILayout.LabelField("半径");  
  54.                 d.radius = EditorGUILayout.Slider(d.radius, 0, 10);  
  55.                 break;  
  56.   
  57.   
  58.             case DrawType.DrawRectangle:  
  59.                 EditorGUILayout.LabelField("绘制空心长方形");  
  60.                 EditorGUILayout.LabelField("长度");  
  61.                 d.length = EditorGUILayout.Slider(d.length, 0, 10);  
  62.                 EditorGUILayout.LabelField("宽度");  
  63.                 d.width = EditorGUILayout.Slider(d.width, 0, 10);  
  64.                 break;  
  65.   
  66.   
  67.             case DrawType.DrawRectangle2D:  
  68.                 EditorGUILayout.LabelField("绘制空心长方形2D");  
  69.                 EditorGUILayout.LabelField("距离");  
  70.                 d.distance = EditorGUILayout.Slider(d.distance, 0, 10);  
  71.                 EditorGUILayout.LabelField("长度");  
  72.                 d.length = EditorGUILayout.Slider(d.length, 0, 10);  
  73.                 EditorGUILayout.LabelField("宽度");  
  74.                 d.width = EditorGUILayout.Slider(d.width, 0, 10);  
  75.                 break;  
  76.   
  77.   
  78.             case DrawType.DrawSectorSolid:  
  79.                 EditorGUILayout.LabelField("绘制实心扇形");  
  80.                 EditorGUILayout.LabelField("角度");  
  81.                 d.angle = EditorGUILayout.Slider(d.angle, 0, 180);  
  82.                 EditorGUILayout.LabelField("半径");  
  83.                 d.radius = EditorGUILayout.Slider(d.radius, 0, 10);  
  84.                 break;  
  85.   
  86.   
  87.             case DrawType.DrawCircleSolid:  
  88.                 EditorGUILayout.LabelField("绘制实心圆");  
  89.                 EditorGUILayout.LabelField("半径");  
  90.                 d.radius = EditorGUILayout.Slider(d.radius, 0, 10);  
  91.                 break;  
  92.   
  93.   
  94.             case DrawType.DrawRectangleSolid:  
  95.                 EditorGUILayout.LabelField("绘制实心长方形");  
  96.                 EditorGUILayout.LabelField("长度");  
  97.                 d.length = EditorGUILayout.Slider(d.length, 0, 10);  
  98.                 EditorGUILayout.LabelField("宽度");  
  99.                 d.width = EditorGUILayout.Slider(d.width, 0, 10);  
  100.                 break;  
  101.   
  102.   
  103.             case DrawType.DrawRectangleSolid2D:  
  104.                 EditorGUILayout.LabelField("绘制实心长方形2D");  
  105.                 EditorGUILayout.LabelField("距离");  
  106.                 d.distance = EditorGUILayout.Slider(d.distance, 0, 10);  
  107.                 EditorGUILayout.LabelField("长度");  
  108.                 d.length = EditorGUILayout.Slider(d.length, 0, 10);  
  109.                 EditorGUILayout.LabelField("宽度");  
  110.                 d.width = EditorGUILayout.Slider(d.width, 0, 10);  
  111.                 break;  
  112.   
  113.   
  114.             default:  
  115.                 break;  
  116.         }  
  117.     }  
  118. }  



[csharp]  view plain  copy
 
  1. using UnityEngine;  
  2. using System.Collections;  
  3.   
  4. public class MathTool {  
  5.   
  6.     public static float piDivide180 = Mathf.PI / 180;  
  7.   
  8.     public static bool IsFacingRight(Transform t)  
  9.     {  
  10.         if (t.localEulerAngles.y > 0) return false;  
  11.         else return true;  
  12.     }  
  13.   
  14.     public static void FacingRight(Transform t)  
  15.     {  
  16.         t.localEulerAngles = new Vector3(0, 0, 0);  
  17.     }  
  18.   
  19.     public static void FacingLeft(Transform t)  
  20.     {  
  21.         t.localEulerAngles = new Vector3(0, 180, 0);  
  22.     }  
  23.   
  24.     public static Vector2 GetVector2(Vector3 a)  
  25.     {  
  26.         Vector2 posA = new Vector2(a.x, a.z);  
  27.         return posA;  
  28.     }  
  29.   
  30.     public static float GetDistance(Transform a, Transform b)  
  31.     {  
  32.         Vector2 posA = GetVector2(a.position);  
  33.         Vector2 posB = GetVector2(b.position);  
  34.         return Vector2.Distance(posA, posB);  
  35.     }  
  36.   
  37.     public static Vector2 GetDirection(Transform a, Transform b)  
  38.     {  
  39.         Vector2 posA = GetVector2(a.position);  
  40.         Vector2 posB = GetVector2(b.position);  
  41.         return posB - posA;  
  42.     }  
  43.   

你可能感兴趣的:([Unity实战]攻击范围的绘制)