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

效果图:












代码如下:

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;
    }

}



  • 21
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值