效果图:
代码如下:
using UnityEngine;
using System.Collections.Generic;
public class DrawTool : MonoBehaviour {
private static LineRenderer GetLineRenderer(Transform t)
{
LineRenderer lr = t.GetComponent<LineRenderer>();
if (lr == null)
{
lr = t.gameObject.AddComponent<LineRenderer>();
}
lr.SetWidth(0.1f, 0.1f);
return lr;
}
public static void DrawLine(Transform t, Vector3 start, Vector3 end)
{
LineRenderer lr = GetLineRenderer(t);
lr.SetVertexCount(2);
lr.SetPosition(0, start);
lr.SetPosition(1, end);
}
//绘制空心扇形
public static void DrawSector(Transform t, Vector3 center, float angle, float radius)
{
LineRenderer lr = GetLineRenderer(t);
int pointAmount = 100;//点的数目,值越大曲线越平滑
float eachAngle = angle / pointAmount;
Vector3 forward = t.forward;
lr.SetVertexCount(pointAmount);
lr.SetPosition(0, center);
lr.SetPosition(pointAmount - 1, center);
for (int i = 1; i < pointAmount - 1; i++)
{
Vector3 pos = Quaternion.Euler(0f, -angle / 2 + eachAngle * (i - 1), 0f) * forward * radius + center;
lr.SetPosition(i, pos);
}
}
//绘制空心圆
public static void DrawCircle(Transform t, Vector3 center, float radius)
{
LineRenderer lr = GetLineRenderer(t);
int pointAmount = 100;//点的数目,值越大曲线越平滑
float eachAngle = 360f / pointAmount;
Vector3 forward = t.forward;
lr.SetVertexCount(pointAmount + 1);
for (int i = 0; i <= pointAmount; i++)
{
Vector3 pos = Quaternion.Euler(0f, eachAngle * i, 0f) * forward * radius + center;
lr.SetPosition(i, pos);
}
}
//绘制空心长方形
//以长方形的底边中点为攻击方位置(从俯视角度来看)
public static void DrawRectangle(Transform t, Vector3 bottomMiddle, float length, float width)
{
LineRenderer lr = GetLineRenderer(t);
lr.SetVertexCount(5);
lr.SetPosition(0, bottomMiddle - t.right * (width / 2));
lr.SetPosition(1, bottomMiddle - t.right * (width / 2) + t.forward * length);
lr.SetPosition(2, bottomMiddle + t.right * (width / 2) + t.forward * length);
lr.SetPosition(3, bottomMiddle + t.right * (width / 2));
lr.SetPosition(4, bottomMiddle - t.right * (width / 2));
}
//绘制空心长方形2D
//distance指的是这个长方形与Transform t的中心点的距离
public static void DrawRectangle2D(Transform t, float distance, float length, float width)
{
LineRenderer lr = GetLineRenderer(t);
lr.SetVertexCount(5);
if (MathTool.IsFacingRight(t))
{
Vector2 forwardMiddle = new Vector2(t.position.x + distance, t.position.y);
lr.SetPosition(0, forwardMiddle + new Vector2(0, width / 2));
lr.SetPosition(1, forwardMiddle + new Vector2(length, width / 2));
lr.SetPosition(2, forwardMiddle + new Vector2(length, -width / 2));
lr.SetPosition(3, forwardMiddle + new Vector2(0, -width / 2));
lr.SetPosition(4, forwardMiddle + new Vector2(0, width / 2));
}
else
{
Vector2 forwardMiddle = new Vector2(t.position.x - distance, t.position.y);
lr.SetPosition(0, forwardMiddle + new Vector2(0, width / 2));
lr.SetPosition(1, forwardMiddle + new Vector2(-length, width / 2));
lr.SetPosition(2, forwardMiddle + new Vector2(-length, -width / 2));
lr.SetPosition(3, forwardMiddle + new Vector2(0, -width / 2));
lr.SetPosition(4, forwardMiddle + new Vector2(0, width / 2));
}
}
public static GameObject go;
public static MeshFilter mf;
public static MeshRenderer mr;
public static Shader shader;
private static GameObject CreateMesh(List<Vector3> vertices)
{
int[] triangles;
Mesh mesh = new Mesh();
int triangleAmount = vertices.Count - 2;
triangles = new int[3 * triangleAmount];
//根据三角形的个数,来计算绘制三角形的顶点顺序(索引)
//顺序必须为顺时针或者逆时针
for (int i = 0; i < triangleAmount; i++)
{
triangles[3 * i] = 0;//固定第一个点
triangles[3 * i + 1] = i + 1;
triangles[3 * i + 2] = i + 2;
}
if (go == null)
{
go = new GameObject("mesh");
go.transform.position = new Vector3(0, 0.1f, 0);//让绘制的图形上升一点,防止被地面遮挡
mf = go.AddComponent<MeshFilter>();
mr = go.AddComponent<MeshRenderer>();
shader = Shader.Find("Unlit/Color");
}
mesh.vertices = vertices.ToArray();
mesh.triangles = triangles;
mf.mesh = mesh;
mr.material.shader = shader;
mr.material.color = Color.red;
return go;
}
//绘制实心扇形
public static void DrawSectorSolid(Transform t, Vector3 center, float angle, float radius)
{
int pointAmount = 100;//点的数目,值越大曲线越平滑
float eachAngle = angle / pointAmount;
Vector3 forward = t.forward;
List<Vector3> vertices = new List<Vector3>();
vertices.Add(center);
for (int i = 1; i < pointAmount - 1; i++)
{
Vector3 pos = Quaternion.Euler(0f, -angle / 2 + eachAngle * (i - 1), 0f) * forward * radius + center;
vertices.Add(pos);
}
CreateMesh(vertices);
}
//绘制实心圆
public static void DrawCircleSolid(Transform t, Vector3 center, float radius)
{
int pointAmount = 100;//点的数目,值越大曲线越平滑
float eachAngle = 360f / pointAmount;
Vector3 forward = t.forward;
List<Vector3> vertices = new List<Vector3>();
for (int i = 0; i <= pointAmount; i++)
{
Vector3 pos = Quaternion.Euler(0f, eachAngle * i, 0f) * forward * radius + center;
vertices.Add(pos);
}
CreateMesh(vertices);
}
//绘制实心长方形
//以长方形的底边中点为攻击方位置(从俯视角度来看)
public static void DrawRectangleSolid(Transform t, Vector3 bottomMiddle, float length, float width)
{
List<Vector3> vertices = new List<Vector3>();
vertices.Add(bottomMiddle - t.right * (width / 2));
vertices.Add(bottomMiddle - t.right * (width / 2) + t.forward * length);
vertices.Add(bottomMiddle + t.right * (width / 2) + t.forward * length);
vertices.Add(bottomMiddle + t.right * (width / 2));
CreateMesh(vertices);
}
//绘制实心长方形2D
//distance指的是这个长方形与Transform t的中心点的距离
public static void DrawRectangleSolid2D(Transform t, float distance, float length, float width)
{
List<Vector3> vertices = new List<Vector3>();
if (MathTool.IsFacingRight(t))
{
Vector3 forwardMiddle = new Vector3(t.position.x + distance, t.position.y);
vertices.Add(forwardMiddle + new Vector3(0, width / 2));
vertices.Add(forwardMiddle + new Vector3(length, width / 2));
vertices.Add(forwardMiddle + new Vector3(length, -width / 2));
vertices.Add(forwardMiddle + new Vector3(0, -width / 2));
}
else
{
//看不到颜色但点击mesh可以看到形状
Vector3 forwardMiddle = new Vector3(t.position.x - distance, t.position.y);
vertices.Add(forwardMiddle + new Vector3(0, width / 2));
vertices.Add(forwardMiddle + new Vector3(-length, width / 2));
vertices.Add(forwardMiddle + new Vector3(-length, -width / 2));
vertices.Add(forwardMiddle + new Vector3(0, -width / 2));
}
CreateMesh(vertices);
}
}
测试:
using UnityEngine;
using System.Collections;
public class TestDraw : MonoBehaviour {
void Start ()
{
//DrawTool.DrawSector(transform, transform.localPosition, 60, 3);
//DrawTool.DrawCircle(transform, transform.localPosition, 3);
//DrawTool.DrawRectangle(transform, transform.localPosition, 5, 2);
//DrawTool.DrawSectorSolid(transform, transform.localPosition, 60, 3);
//DrawTool.DrawCircleSolid(transform, transform.localPosition, 3);
DrawTool.DrawRectangleSolid(transform, transform.localPosition, 5, 2);
}
}
然后,为了更好地测试数据,应该要有这样一个东西:
using UnityEngine;
using System.Collections;
public enum DrawType
{
DrawSector, //绘制空心扇形
DrawCircle, //绘制空心圆
DrawRectangle, //绘制空心长方形
DrawRectangle2D, //绘制空心长方形2D
DrawSectorSolid, //绘制实心扇形
DrawCircleSolid, //绘制实心圆
DrawRectangleSolid, //绘制实心长方形
DrawRectangleSolid2D, //绘制实心长方形2D
}
/// <summary>
/// 要把动画上的脚本(继承StateMachineBehaviour)取消勾选
/// </summary>
public class DebugDistanceAngle : MonoBehaviour {
private GameObject go;
private Animator animator;
public string modelName;//角色路径
public string animationName;//动画名字,即Animator窗口看到的动画名字
public float time;//播放进度
public DrawType drawType;
public float distance;
public float angle;
public float radius;
public float length;
public float width;
void Start ()
{
if (modelName.Length > 0)
{
go = Instantiate(Resources.Load<GameObject>(modelName));
go.transform.localPosition = Vector3.zero;
animator = go.GetComponent<Animator>();
}
}
void Update ()
{
if ((go != null) && (time != 0))
{
animator.Play(animationName, 0, time);
}
switch (drawType)
{
case DrawType.DrawSector :
DrawTool.DrawSector(go.transform, go.transform.position, angle, radius);
break;
case DrawType.DrawCircle:
DrawTool.DrawCircle(go.transform, go.transform.position, radius);
break;
case DrawType.DrawRectangle:
DrawTool.DrawRectangle(go.transform, go.transform.position, length, width);
break;
case DrawType.DrawRectangle2D:
DrawTool.DrawRectangle2D(go.transform, distance, length, width);
break;
case DrawType.DrawSectorSolid:
DrawTool.DrawSectorSolid(go.transform, go.transform.position, angle, radius);
break;
case DrawType.DrawCircleSolid:
DrawTool.DrawCircleSolid(go.transform, go.transform.position, radius);
break;
case DrawType.DrawRectangleSolid:
DrawTool.DrawRectangleSolid(go.transform, go.transform.position, length, width);
break;
case DrawType.DrawRectangleSolid2D:
DrawTool.DrawRectangleSolid2D(go.transform, distance, length, width);
break;
default :
break;
}
}
}
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(DebugDistanceAngle))]
[ExecuteInEditMode]
public class DebugDistanceAngleEditor : Editor {
private bool canGetDragEvent;
public override void OnInspectorGUI()
{
DebugDistanceAngle d = target as DebugDistanceAngle;
EditorGUILayout.LabelField("请把角色放在Resources文件夹中,点击Play之后将通过Resources进行加载");
canGetDragEvent = EditorGUILayout.Toggle("通过拖拽获取角色路径", canGetDragEvent);
EditorGUILayout.LabelField("角色路径");
if (canGetDragEvent)
{
if (Event.current.type == EventType.DragExited)
{
if (DragAndDrop.paths != null && DragAndDrop.paths.Length > 0)
{
string s = DragAndDrop.paths[0];
s = s.Substring(s.IndexOf("Resources/"));
s = s.Remove(0, "Resources/".Length);
s = s.Substring(0, s.IndexOf('.'));
d.modelName = s;
}
}
}
d.modelName = EditorGUILayout.TextArea(d.modelName);
d.animationName = EditorGUILayout.TextField("动画名字", d.animationName);
EditorGUILayout.LabelField("播放进度");
d.time = EditorGUILayout.Slider(d.time, 0, 1);
d.drawType = (DrawType)EditorGUILayout.EnumPopup("绘制类型" ,d.drawType);
switch (d.drawType)
{
case DrawType.DrawSector:
EditorGUILayout.LabelField("绘制空心扇形");
EditorGUILayout.LabelField("角度");
d.angle = EditorGUILayout.Slider(d.angle, 0, 180);
EditorGUILayout.LabelField("半径");
d.radius = EditorGUILayout.Slider(d.radius, 0, 10);
break;
case DrawType.DrawCircle:
EditorGUILayout.LabelField("绘制空心圆");
EditorGUILayout.LabelField("半径");
d.radius = EditorGUILayout.Slider(d.radius, 0, 10);
break;
case DrawType.DrawRectangle:
EditorGUILayout.LabelField("绘制空心长方形");
EditorGUILayout.LabelField("长度");
d.length = EditorGUILayout.Slider(d.length, 0, 10);
EditorGUILayout.LabelField("宽度");
d.width = EditorGUILayout.Slider(d.width, 0, 10);
break;
case DrawType.DrawRectangle2D:
EditorGUILayout.LabelField("绘制空心长方形2D");
EditorGUILayout.LabelField("距离");
d.distance = EditorGUILayout.Slider(d.distance, 0, 10);
EditorGUILayout.LabelField("长度");
d.length = EditorGUILayout.Slider(d.length, 0, 10);
EditorGUILayout.LabelField("宽度");
d.width = EditorGUILayout.Slider(d.width, 0, 10);
break;
case DrawType.DrawSectorSolid:
EditorGUILayout.LabelField("绘制实心扇形");
EditorGUILayout.LabelField("角度");
d.angle = EditorGUILayout.Slider(d.angle, 0, 180);
EditorGUILayout.LabelField("半径");
d.radius = EditorGUILayout.Slider(d.radius, 0, 10);
break;
case DrawType.DrawCircleSolid:
EditorGUILayout.LabelField("绘制实心圆");
EditorGUILayout.LabelField("半径");
d.radius = EditorGUILayout.Slider(d.radius, 0, 10);
break;
case DrawType.DrawRectangleSolid:
EditorGUILayout.LabelField("绘制实心长方形");
EditorGUILayout.LabelField("长度");
d.length = EditorGUILayout.Slider(d.length, 0, 10);
EditorGUILayout.LabelField("宽度");
d.width = EditorGUILayout.Slider(d.width, 0, 10);
break;
case DrawType.DrawRectangleSolid2D:
EditorGUILayout.LabelField("绘制实心长方形2D");
EditorGUILayout.LabelField("距离");
d.distance = EditorGUILayout.Slider(d.distance, 0, 10);
EditorGUILayout.LabelField("长度");
d.length = EditorGUILayout.Slider(d.length, 0, 10);
EditorGUILayout.LabelField("宽度");
d.width = EditorGUILayout.Slider(d.width, 0, 10);
break;
default:
break;
}
}
}
using UnityEngine;
using System.Collections;
public class MathTool {
public static float piDivide180 = Mathf.PI / 180;
public static bool IsFacingRight(Transform t)
{
if (t.localEulerAngles.y > 0) return false;
else return true;
}
public static void FacingRight(Transform t)
{
t.localEulerAngles = new Vector3(0, 0, 0);
}
public static void FacingLeft(Transform t)
{
t.localEulerAngles = new Vector3(0, 180, 0);
}
public static Vector2 GetVector2(Vector3 a)
{
Vector2 posA = new Vector2(a.x, a.z);
return posA;
}
public static float GetDistance(Transform a, Transform b)
{
Vector2 posA = GetVector2(a.position);
Vector2 posB = GetVector2(b.position);
return Vector2.Distance(posA, posB);
}
public static Vector2 GetDirection(Transform a, Transform b)
{
Vector2 posA = GetVector2(a.position);
Vector2 posB = GetVector2(b.position);
return posB - posA;
}
}