2015-01-27 21:00:03 feixiangdixiaoniao 阅读数 1364

 为了平滑游戏对象在 Unity 中的行进路线,我们经常会在 Unity 中使用 ITweenPath 插件,但有时候我们或许只会使用到通过 ITweenPath 绘制出来的点(比如把这些点放到配置文件中),并不希望加载 ITweenPath 插件或者通过自己的函数去实现游戏对象的移动,通过查看 ITweenPath 的代码,很容易就把 ITweenPath 绘制曲线点的方法给提取出来了,主函数并不多,只有三个方法,希望能给你带来帮助!


先来看看最终的 Demo 实现方式:






Demo 代码:

using UnityEngine;using System.Collections.Generic;
public class PointPath : MonoBehaviour {
        private Vector3[] pathList;
        public GameObject sphere;
        public GameObject path;
        void Awake()
        {
                Transform[] transformList = path.GetComponentsInChildren<Transform> ();
                int length = transformList.Length;
                pathList = new Vector3[length];

                for (int index = 0; index < length; index ++)
                 {
                        pathList[index] = transformList[index].transform.position;
                }                

Vector3[] resultList = PointController.PointList (this.pathList, 20);

                foreach (Vector3 point in resultList)
                 {                        

GameObject gameObject = (GameObject)Instantiate(sphere); 
                       gameObject.transform.localPosition = point; 
                       gameObject.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
                }
        }

PointController.cs


using UnityEngine;
using System;
using System.Collections;
public class PointController{

        /// <summary>        
/// 获取曲线上面的所有点

        /// </summary>

        /// <returns>The list.</returns>
        /// <param name="path">需要穿过的点列表</param>

        /// <param name="pointSize">两个点之间的节点数量</param>
        public static Vector3[] PointList(Vector3[] path, int pointSize)
        {

                Vector3[] controlPointList = PathControlPointGenerator(path); 
               int smoothAmount = path.Length * pointSize;

                Vector3[] pointList = new Vector3[smoothAmount]; 
               for (int index = 1; index <= smoothAmount; index++)
                 {

                        Vector3 currPt = Interp(controlPointList, (float) index / smoothAmount); 
                       pointList[index - 1] = currPt;


                }
                return pointList;


        }
                /// <summary>


        /// 获取控制点
        /// </summary>
        /// <returns>The control point generator.</returns>
        /// <param name="path">Path.</param>


        private static Vector3[] PathControlPointGenerator(Vector3[] path)
        {
                int offset = 2;


                Vector3[] suppliedPath = path;


                Vector3[] controlPoint = new Vector3[suppliedPath.Length + offset];


                Array.Copy(suppliedPath, 0, controlPoint, 1, suppliedPath.Length);


                controlPoint[0] = controlPoint[1] + (controlPoint[1] - controlPoint[2]);


                controlPoint[controlPoint.Length - 1] = controlPoint[controlPoint.Length - 2] + (controlPoint[controlPoint.Length - 2] - controlPoint[controlPoint.Length - 3]); 


               if(controlPoint[1] == controlPoint[controlPoint.Length - 2])
                {
                        Vector3[] tmpLoopSpline = new Vector3[controlPoint.Length];


                        Array.Copy(controlPoint, tmpLoopSpline, controlPoint.Length);


                        tmpLoopSpline[0] = tmpLoopSpline[tmpLoopSpline.Length - 3];


                        tmpLoopSpline[tmpLoopSpline.Length - 1] = tmpLoopSpline[2];


                        controlPoint = new Vector3[tmpLoopSpline.Length]; 


                       Array.Copy(tmpLoopSpline, controlPoint, tmpLoopSpline.Length);
                }
                                        return(controlPoint);
        }
        /// <summary>
        /// 根据 T 获取曲线上面的点位置
        /// </summary>


        /// <param name="pts">Pts.</param>
        /// <param name="t">T.</param>


        private static Vector3 Interp(Vector3[] pts, float t)
        {
                int numSections = pts.Length - 3;
                int currPt = Mathf.Min(Mathf.FloorToInt(t * (float) numSections), numSections - 1);


                float u = t * (float) numSections - (float) currPt;


                                Vector3 a = pts[currPt];


                Vector3 b = pts[currPt + 1];
                Vector3 c = pts[currPt + 2];
                Vector3 d = pts[currPt + 3];


                                return .5f * (                        (-a + 3f * b - 3f * c + d) * (u * u * u)                        + (2f * a - 5f * b + 4f * c - d) * (u * u)                        + (-a + c) * u                        + 2f * b                        );
        } 
       }


更多精彩关注狗刨学习网:http://www.gopedu.com/
2016-12-14 21:38:26 sinat_23079759 阅读数 6894

贝塞尔曲线是一种绘制曲线的方法,它的原理很简单:

以二阶贝塞尔曲线为例


如图,在p0,p1之间移动着一个点,我们先称之为a0,同样在p1,p2之间移动着一个点,我们称之为a1。他们需要满足的条件是这样的,在移动中,保证线段p0a0p0p1=p1a1p1p2=X

,这个比值X是从01逐渐变化的。

然后我们连接a0,a1,在线段a0a1上有一点b0,我们同样保证a0b0a0a1=X;最后X01变化的过程就是如图所显示的样子。这就是贝塞尔曲线。简单吧!

相对于更高阶的,原理一样,如果你有时间有耐心,函数很容易写出来的,这里只用二阶作为例子。

二阶函数点的位置可以这样计算

a0=p0+p1-p0*X

a1=p1+p2-p1*X

b0=a0+a1-a0*X

这样我们根据p0p1p2的坐标就求出b0的坐标,b0的运动轨迹就是贝塞尔曲线。

三个公式最后得出:

b0=X*X*(p0+p2-2*p1)+2*X*(p1-p0)+p0

知道原理,接下来我们用unity3d实现起来就容易了。

代码如下:将脚本赋予一个空gameobject,并将新建的三个cube分别拖入对应空缺物体,运行游戏拖动物体就能看到贝塞尔曲线的变化。注意:这里只能在场景中拖动,不能在游戏视图中拖动,因为

Debug.DrawLine方法是只能在场景中显示的。

using UnityEngine;
using System.Collections;

public class draw : MonoBehaviour {
   public GameObject v0, v1, a0;
    LineRenderer lineRenderer;
    //Vector3 v0, v1;//顶点
    //Vector3 a0;
    float jianxi = 0.05f;//绘制的0-1的间隙 越小曲线越接近曲线,

    // Use this for initialization
    void Start ()
    {
      
    }
	
	// Update is called once per frame
	void Update () {
        for(float i=0;i<1;i+=jianxi)
        {
            Debug.DrawLine(po(i, v0, v1, a0), po(i + jianxi, v0, v1, a0), Color.red);
            Debug.DrawLine(v0.transform.position,a0.transform.position, Color.green);
            Debug.DrawLine(a0.transform.position, v1.transform.position, Color.green);
        }
    }
       
    private Vector3 po(float t,GameObject v0, GameObject v1, GameObject a0)//根据当前时间t 返回路径  其中v0为起点 v1为终点 a为中间点 
    {
        Vector3 a;
        a.x = t * t * (v1.transform.position.x - 2 * a0.transform.position.x + v0.transform.position.x) + v0.transform.position.x + 2 * t * (a0.transform.position.x - v0.transform.position.x);//公式为B(t)=(1-t)^2*v0+2*t*(1-t)*a0+t*t*v1 其中v0为起点 v1为终点 a为中间点 
        a.y = t * t * (v1.transform.position.y - 2 * a0.transform.position.y + v0.transform.position.y) + v0.transform.position.y + 2 * t * (a0.transform.position.y - v0.transform.position.y);
        a.z = t * t * (v1.transform.position.z - 2 * a0.transform.position.z + v0.transform.position.z) + v0.transform.position.z + 2 * t * (a0.transform.position.z - v0.transform.position.z);
        return a;
    }
}


unity3d项目资源可以点击 这里 下载


2018-07-04 17:48:31 IT_yanghui 阅读数 1948

近日,项目需求:前提:三维空间

1.动态添加(删除)路径点,通过两个以上的路径点来绘制曲线,删除点之后不影响其他点绘制曲线;

2.每个路径点都可以被拖拽发生位移,可以通过锁定某个轴,使该轴不发生位移;

3.每个路径点处有两个可调节点(首尾只有一个调节点),可通过调节点来调节曲线切线(速度方向线)斜率,以达到平滑曲线;

4.使该曲线形成路径,隐藏曲线,Player沿曲线完成自动寻路。

先看效果,再贴代码。(使用贝塞尔曲线公式与LineRenderer绘制3D可调节曲线


代码如下:两个脚本。

1. DMDrawCurve.cs 挂载到任意对象即可

该脚本实现绘制曲线,动态添加(删除)点,发生位移时更新绘制曲线,以及隐藏该曲线。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace DM.Editor.View
{
    [RequireComponent(typeof(LineRenderer))]
    public class DMDrawCurve : MonoBehaviour
    {
        public List<Transform> m_allPoints;
        private GameObject m_anchorPoint;
        private GameObject m_controlPoint;
        private GameObject m_pointParent;
        private LineRenderer m_lineRenderer;
        
        private int m_curveCount = 0;
        private int SEGMENT_COUNT = 60;//曲线取点个数(取点越多这个长度越趋向于精确)

        private static DMDrawCurve m_instance;
        public static DMDrawCurve Instance
        {
            get {
                if (null == m_instance)
                    m_instance = new DMDrawCurve();
                return m_instance;
            }
        }
        void Awake()
        {
            if (null == m_instance)
                m_instance = this;
            SetLine();
            if (null == m_anchorPoint)
                m_anchorPoint = Resources.Load("Prefabs/AnchorPoint") as GameObject;
            if (null == m_controlPoint)
                m_controlPoint = Resources.Load("Prefabs/ControlPoint") as GameObject;
        }
        void SetLine()
        {
            if (null == m_lineRenderer)
                m_lineRenderer = GetComponent<LineRenderer>();
            m_lineRenderer.material = Resources.Load("Materials/Line") as Material;
            m_lineRenderer.startColor = Color.red;
            m_lineRenderer.endColor = Color.green;
            m_lineRenderer.widthMultiplier = 0.2f;
        }

        public void Init(GameObject player)
        {//初始化一个基准点(Player)
            if (player == null) return;
            GameObject anchorPoint = LoadPoint(m_anchorPoint, player.transform.position);
            m_allPoints.Add(anchorPoint.transform);
        }      
        public void AddPoint(Vector3 anchorPointPos)
        {
            //初始化时m_allPoints添加了一个player
            if (m_allPoints.Count == 0) return;
            Transform lastPoint = m_allPoints[m_allPoints.Count - 1];
            GameObject controlPoint2 = LoadPoint(m_controlPoint, lastPoint.position+new Vector3(0,0,-1));   
            GameObject controlPoint = LoadPoint(m_controlPoint, anchorPointPos + new Vector3(0, 0, 1));
            GameObject anchorPoint = LoadPoint(m_anchorPoint, anchorPointPos);

            anchorPoint.GetComponent<CurvePointControl>().m_controlObject = controlPoint;
            lastPoint.GetComponent<CurvePointControl>().m_controlObject2 = controlPoint2;

            m_allPoints.Add(controlPoint2.transform);
            m_allPoints.Add(controlPoint.transform);
            m_allPoints.Add(anchorPoint.transform);

            DrawCurve();
        }
        public void DeletePoint(GameObject anchorPoint)
        {
            if (anchorPoint == null) return;
            CurvePointControl curvePoint = anchorPoint.GetComponent<CurvePointControl>();
            if (curvePoint && anchorPoint.tag.Equals("AnchorPoint"))
            {
                if (curvePoint.m_controlObject)
                {
                    m_allPoints.Remove(curvePoint.m_controlObject.transform);
                    Destroy(curvePoint.m_controlObject);
                } 
                if (curvePoint.m_controlObject2)
                {
                    m_allPoints.Remove(curvePoint.m_controlObject2.transform);
                    Destroy(curvePoint.m_controlObject2);
                }
                if (m_allPoints.IndexOf(curvePoint.transform) == (m_allPoints.Count - 1))
                {//先判断删除的是最后一个元素再移除
                    m_allPoints.Remove(curvePoint.transform);
                    Transform lastPoint = m_allPoints[m_allPoints.Count - 2];
                    GameObject lastPointCtrObject = lastPoint.GetComponent<CurvePointControl>().m_controlObject2;
                    if (lastPointCtrObject)
                    {
                        m_allPoints.Remove(lastPointCtrObject.transform);
                        Destroy(lastPointCtrObject);
                        lastPoint.GetComponent<CurvePointControl>().m_controlObject2 = null;
                    }
                }
                else
                {
                    m_allPoints.Remove(curvePoint.transform);
                }
                Destroy(anchorPoint);
                if(m_allPoints.Count == 1)
                {
                    m_lineRenderer.positionCount = 0;
                }
            }

            DrawCurve();
        }
        public void UpdateLine(GameObject anchorPoint, Vector3 offsetPos1, Vector3 offsetPos2)
        {
            if (anchorPoint == null) return;
            if (anchorPoint.tag.Equals("AnchorPoint"))
            {
                CurvePointControl curvePoint = anchorPoint.GetComponent<CurvePointControl>();
                if (curvePoint)
                {
                    if (curvePoint.m_controlObject)
                        curvePoint.m_controlObject.transform.position = anchorPoint.transform.position + offsetPos1;
                    if (curvePoint.m_controlObject2)
                        curvePoint.m_controlObject2.transform.position = anchorPoint.transform.position + offsetPos2;
                }
            }
            DrawCurve();
        }
        public List<Vector3> HiddenLine(bool isHidden=false)
        {
            m_pointParent.SetActive(isHidden);
            m_lineRenderer.enabled = isHidden;
            List<Vector3> pathPoints = new List<Vector3>();
            if(!isHidden)
            {
                for(int i = 0; i < m_lineRenderer.positionCount; i++)
                {
                    pathPoints.Add(m_lineRenderer.GetPosition(i));
                }
            }
            return pathPoints;
        }

        private void DrawCurve()//画曲线
        {
            if (m_allPoints.Count < 4) return;
            m_curveCount = (int)m_allPoints.Count / 3;
            for (int j = 0; j < m_curveCount; j++)
            {
                for (int i = 1; i <= SEGMENT_COUNT; i++)
                {
                    float t = (float)i / (float)SEGMENT_COUNT;
                    int nodeIndex = j * 3;
                    Vector3 pixel = CalculateCubicBezierPoint(t, m_allPoints[nodeIndex].position, m_allPoints[nodeIndex + 1].position, m_allPoints[nodeIndex + 2].position, m_allPoints[nodeIndex + 3].position);
                    m_lineRenderer.positionCount = j * SEGMENT_COUNT + i;
                    m_lineRenderer.SetPosition((j * SEGMENT_COUNT) + (i - 1), pixel);
                }
            }
        }
        private GameObject LoadPoint(GameObject pointPrefab,Vector3 pos)
        {
            if (pointPrefab == null)
            {
                Debug.LogError("The Prefab is Null!");
                return null;
            }
            if (null == m_pointParent)
                m_pointParent = new GameObject("AllPoints");
            GameObject pointClone = Instantiate(pointPrefab);
            pointClone.name = pointClone.name.Replace("(Clone)", "");
            pointClone.transform.SetParent(m_pointParent.transform);
            pointClone.transform.position = pos;

            return pointClone;
        }

        //贝塞尔曲线公式:B(t)=P0*(1-t)^3 + 3*P1*t(1-t)^2 + 3*P2*t^2*(1-t) + P3*t^3 ,t属于[0,1].
        Vector3 CalculateCubicBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
        {
            float u = 1 - t;
            float tt = t * t;
            float uu = u * u;
            float uuu = uu * u;
            float ttt = tt * t;

            Vector3 p = uuu * p0;
            p += 3 * uu * t * p1;
            p += 3 * u * tt * p2;
            p += ttt * p3;

            return p;
        }
    }
}

2. CurvePointControl.cs (挂载到路径点与调节点上(两个预制体))

该脚本实现每个路径点对应的两个调节点,以及绘制调节点与路径点之间的切线。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


namespace DM.Editor.View
{
    public class CurvePointControl : MonoBehaviour
    {
        [Header("锁定X轴")]
        public bool m_isLockX = false;
        [Header("锁定Y轴")]
        public bool m_isLockY = true;
        [Header("锁定Z轴")]
        public bool m_isLockZ = false;
       
        [HideInInspector]
        public GameObject m_controlObject;
        [HideInInspector]
        public GameObject m_controlObject2;


        private Vector3 offsetPos1 = Vector3.zero;
        private Vector3 offsetPos2 = Vector3.zero;
        private LineRenderer lineRenderer;
        void Start()
        {
            if (gameObject.tag.Equals("AnchorPoint") && !lineRenderer)
                lineRenderer = gameObject.AddComponent<LineRenderer>();
            if (lineRenderer)
            {
                lineRenderer.sortingOrder = 1;
                lineRenderer.material = new Material(Shader.Find("Particles/Alpha Blended"));
                lineRenderer.startColor = lineRenderer.endColor = Color.yellow;
                lineRenderer.widthMultiplier = 0.03f;
                lineRenderer.positionCount = 0;
            }
        }
        void OnMouseDown()
        {
            if (!gameObject.tag.Equals("AnchorPoint")) return;
            OffsetPos();
        }
        public List<Vector3> OffsetPos()
        {
            List<Vector3> offsetPosList = new List<Vector3>();
            if (m_controlObject)
                offsetPos1 = m_controlObject.transform.position - transform.position;
            if (m_controlObject2)
                offsetPos2 = m_controlObject2.transform.position - transform.position;
            offsetPosList.Add(offsetPos1);
            offsetPosList.Add(offsetPos2);


            return offsetPosList;
        }
        void OnMouseDrag()
        {
            //if (gameObject.tag.Equals("AnchorPoint")) return;
            Vector3 pos0 = Camera.main.WorldToScreenPoint(transform.position);
            Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, pos0.z);
            Vector3 mousePosInWorld= Camera.main.ScreenToWorldPoint(mousePos);
            Vector3 thisPos = mousePosInWorld;
            if (m_isLockX)
                thisPos.x = transform.position.x;
            if (m_isLockY)
                thisPos.y = transform.position.y;
            if (m_isLockZ)
                thisPos.z = transform.position.z;
            transform.position = thisPos;
            DMDrawCurve.Instance.UpdateLine(gameObject, offsetPos1, offsetPos2);   
        }      
        private void DrawControlLine()
        {
            if (!gameObject.tag.Equals("AnchorPoint") || (!m_controlObject && !m_controlObject2)) return;
            if (lineRenderer)
            {
                lineRenderer.positionCount = (m_controlObject && m_controlObject2) ? 3 : 2;
                if (m_controlObject && !m_controlObject2)
                {
                    lineRenderer.SetPosition(0, m_controlObject.transform.position);
                    lineRenderer.SetPosition(1, transform.position);
                }
                if (m_controlObject2 && !m_controlObject)
                {
                    lineRenderer.SetPosition(0, transform.position);
                    lineRenderer.SetPosition(1, m_controlObject2.transform.position);
                }
                if (m_controlObject && m_controlObject2)
                {
                    lineRenderer.SetPosition(0, m_controlObject.transform.position);
                    lineRenderer.SetPosition(1, transform.position);
                    lineRenderer.SetPosition(2, m_controlObject2.transform.position);
                }
            }
        }
        void Update()
        {
            DrawControlLine();
        }
    }
}

对应Inspector,如图


3. Test.cs (任意挂载)

该脚本实现Player自动寻路。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace DM.Editor.View
{
    public class Test : MonoBehaviour
    {
        public GameObject m_player;
        public List<Vector3> m_pathPoints;
        void Start()
        {
            DMDrawCurve.Instance.Init(m_player);
        }

        IEnumerator Move()
        {
            if (m_pathPoints.Count == 0) yield break;
            int item = 1;
            while (true)
            {
                m_player.transform.LookAt(m_pathPoints[item]);
                m_player.transform.position = Vector3.Lerp(m_pathPoints[item - 1], m_pathPoints[item], 1f);
                item++;
                if (item >= m_pathPoints.Count)
                {
                    item = 1;
                    yield break;
                }
                yield return new WaitForEndOfFrame();
            }
        }
        void Update()
        {
            if (Input.GetKey(KeyCode.LeftControl) && (Input.GetMouseButtonUp(0) || Input.GetMouseButtonUp(1)))
            {
                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                RaycastHit hit;
                if (Physics.Raycast(ray, out hit))
                {
                    if (Input.GetMouseButtonUp(0) && hit.collider.tag.Equals("Terrain"))
                    {
                        Vector3 pointPos = new Vector3(hit.point.x, m_player.transform.position.y, hit.point.z);
                        DMDrawCurve.Instance.AddPoint(pointPos);
                    }
                    else if (Input.GetMouseButtonUp(1) && hit.collider.tag.Equals("AnchorPoint"))
                    {
                        DMDrawCurve.Instance.DeletePoint(hit.collider.gameObject);
                    }
                }
            }
            if (Input.GetKeyUp(KeyCode.A))
                m_pathPoints = DMDrawCurve.Instance.HiddenLine(false);
            else if (Input.GetKeyUp(KeyCode.Escape))
            {
                DMDrawCurve.Instance.HiddenLine(true);
                m_pathPoints.Clear();
            }
            if (Input.GetKeyUp(KeyCode.B))
            {
                StartCoroutine(Move());
            }
        }
    }
}

注意:需要添加两个Tag值(Terrain,AnchorPoint),也可动态添加,一个给场景地面,一个给路径点(AnchorPoint),调节点不需要Tag。

开发测试Demo以及.unitypackage的网盘链接如下,需要的自行下载:

链接:https://pan.baidu.com/s/1dwIOxcMB-Lhq_Tlxenb4fQ 密码:7g8y

以上就是近日开发结果,如有不足,请批评指正。如有疑问,请留言,看到自然回复。

如转载,请注明出处:IT_yanghui的博客

2017-04-11 12:09:14 daka2012 阅读数 1196

简介:新项目中需绘制可无限循环的2D多边形路面,于是写了个2D多边形生成器,包括Mesh绘制,添加阻挡及路面描边3个部分,代码如下

using UnityEngine;

public class PolyMesh2D : MonoBehaviour
{
    public Vector2[] toppoints { get; set; }
    public Vector2[] botpoints {get;set;}
    public Vector2[] roundpoints { get;set;}
    public Vector2 lastpoint
    {
        get
        {
            return toppoints[toppoints.Length - 1] + transform.position.IgnoreZAxis();
        }
    }
    public Vector3[] mvertices { get; set; }
    public int[] mtriangles { get; set; }
    public float wide
    {
        get
        {
            return lastpoint.x - toppoints[0].x;
        }
    }
    public int vectnum;
    public Color matcolor;
    
    public enum OutlingType
    {
        up,down,all,
    }
    private MeshFilter meshFilter;
    private MeshRenderer meshrender;
    private Mesh mesh;
    private LineRenderer myline;

    //初始化属性
    public void DefaultSet(int vectnum, Color matcolor)
    {
        this.vectnum = vectnum;
        this.matcolor = matcolor;
        toppoints = new Vector2[vectnum];
        botpoints = new Vector2[vectnum];
        roundpoints = new Vector2[vectnum * 2 + 1];
        mvertices = new Vector3[vectnum * 6 - 6];
        mtriangles = new int[mvertices.Length];
        meshFilter = transform.GetOrAddComponent();
        meshrender = transform.GetOrAddComponent();
        mesh = meshFilter.mesh as Mesh;
        meshrender.material = new Material(Shader.Find("Unlit/Color"));
        meshrender.material.color = matcolor;
    }

    //绘制Mesh
    public void MeshBound(int xmin, int xmax, int ymin, int ymax, float maxheight)
    {
        //计算出上方顶点\下方顶点
        botpoints[0] = toppoints[0] = Vector2.zero;
        botpoints[0].y = -maxheight;

        for (int i = 1; i < vectnum; i++)
        {
            if(i == vectnum - 2)
            {
                toppoints[i].x = toppoints[i - 1].x;
                toppoints[i].y = toppoints[0].y;
            }
            else if(i.isEven())
            {
                toppoints[i].x = toppoints[i - 1].x;
                toppoints[i].y = Random.Range(ymin, ymax);
            }
            else toppoints[i] = toppoints[i - 1] + Vector2.right * Random.Range(xmin, xmax);
            botpoints[i] = toppoints[i];
            botpoints[i].y = -maxheight;
        }

        //计算出包围盒顶点
        for (int i = 0; i < roundpoints.Length; i++)
        {
            if (i < toppoints.Length) roundpoints[i] = toppoints[i];
            else if (i == roundpoints.Length - 1) roundpoints[i] = toppoints[0];
            else roundpoints[i] = botpoints[botpoints.Length * 2 - i - 1];
        }

        //设置Mesh顶点
        for (int i = 0; i < vectnum; i++)
        {
            if (i * 6 > mvertices.Length - 6) break;
            mvertices[i * 6] = botpoints[i];
            mvertices[i * 6 + 1] = toppoints[i];
            mvertices[i * 6 + 2] = toppoints[i + 1];
            mvertices[i * 6 + 3] = botpoints[i];
            mvertices[i * 6 + 4] = toppoints[i + 1];
            mvertices[i * 6 + 5] = botpoints[i + 1];
        }

        //设置三角形
        //数值数量依然要和顶点的数量一样
        for (int nIndex = 0; nIndex < mvertices.Length; nIndex++)
        {
            mtriangles[nIndex] = nIndex;
        }

        //绘制mesh
        mesh.Clear();
        mesh.vertices = mvertices;
        mesh.triangles = mtriangles;
        mesh.RecalculateBounds();
    }

    //设置描边
    public void AddOutline(float linewide, Color linecolor, OutlingType ctype = OutlingType.up)
    {
        if(myline == null)
        {
            myline = gameObject.AddComponent();
            myline.material = new Material(Shader.Find("Particles/Alpha Blended"));
            myline.startWidth = myline.endWidth = linewide;
            myline.startColor = myline.endColor = linecolor;
            myline.useWorldSpace = false;
        }
        switch (ctype)
        {
            case OutlingType.up:
                myline.numPositions = toppoints.Length;
                for (int i = 0; i < myline.numPositions; i++)
                {
                    myline.SetPosition(i, toppoints[i]);
                }
                break;
            case OutlingType.down:
                myline.numPositions = botpoints.Length;
                for (int i = 0; i < myline.numPositions; i++)
                {
                    myline.SetPosition(i, botpoints[i]);
                }
                break;
            case OutlingType.all:
                myline.numPositions = roundpoints.Length;
                for (int i = 0; i < myline.numPositions; i++)
                {
                    myline.SetPosition(i, roundpoints[i]);
                }
                break;
        }
    }

    //添加阻挡块
    public void AddEdge2D()
    {
        EdgeCollider2D myedge = transform.GetOrAddComponent();
        myedge.points = roundpoints;
    }

    public Vector2[] WorldPoints(Vector2[] localpoints)
    {
        for(int i = 0; i < localpoints.Length; i++)
        {
            localpoints[i] += transform.position.IgnoreZAxis();
        }
        return localpoints;
    }
}
其中mesh绘制部分可根据具体需要酌情重写,我这里实现的是有高低起伏的平整路面

2015-01-20 11:45:47 xiao69 阅读数 4448
using UnityEngine;
using System.Collections;

public class DrawLines : MonoBehaviour {
    public Material mat;
    public Color col = Color.red;
    private Vector3 pos1, pos2;
    private bool IsReady = false;
    private ArrayList pointList;
    private ArrayList breakpointList;
    private int index = 0;
	// Use this for initialization
	void Start () {
        mat.color = col;
        pointList = new ArrayList();
        breakpointList = new ArrayList();
	}
	
	// Update is called once per frame
	void Update () {
	    if(Input.GetMouseButtonDown(0))
        {
            
            if(!IsReady)
            {
                pos1 = Input.mousePosition;
                pointList.Add(pos1);
            }
            
        }
        if(Input.GetMouseButtonUp(0))
        {
            pos2 = Input.mousePosition;
            IsReady = true;

            pointList.Add(pos2);
        }
        if(Input.GetMouseButtonUp(1))
        {
            breakpointList.Add(pointList.Count-1);
        }
	}
    void OnPostRender()
    {
        if(IsReady)
        {
            GL.PushMatrix();
            mat.SetPass(0);
            GL.LoadOrtho();
            for (int i = 0; i < pointList.Count-1; i++)
            {
                for (int j = 0; j < breakpointList.Count;j++ )
                {
                    if(i==(int)(breakpointList[j]))
                    {
                        i++;
                    }
                }
                GL.Begin(GL.LINES);
                GL.Color(col);
                GL.Vertex3(((Vector3)pointList[i]).x / Screen.width, ((Vector3)pointList[i]).y / Screen.height, ((Vector3)pointList[i]).z);
                GL.Vertex3(((Vector3)pointList[i+1]).x / Screen.width, ((Vector3)pointList[i+1]).y / Screen.height, ((Vector3)pointList[i+1]).z);
                GL.End();
            }              
            GL.PopMatrix();
        }
    }
}
</pre><pre code_snippet_id="584194" snippet_file_name="blog_20150120_3_1467451" name="code" class="csharp">如上代码所述,脚本绑定在camera上即可。可以绘制任意条直线,右键单击一下开始绘制下一组直线。留做自己参考。


Unity3d绘制饼状图

阅读数 6886

Unity绘制人物行走过的路线。

博文 来自: qq_39177482
没有更多推荐了,返回首页