2015-01-27 21:00:03 feixiangdixiaoniao 阅读数 1364
• ###### 深入浅出Unity3D——第一篇

Unity3D基础知识、游戏算法一网打尽。

74816 人正在学习 去看看 何韬

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

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

unity3d 绘制点绘制线 相关内容

2016-12-14 21:38:26 sinat_23079759 阅读数 6894
• ###### 深入浅出Unity3D——第一篇

Unity3D基础知识、游戏算法一网打尽。

74816 人正在学习 去看看 何韬

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

a0=p0+p1-p0*X

a1=p1+p2-p1*X

b0=a0+a1-a0*X

b0=X*X*（p0+p2-2*p1）+2*X*（p1-p0）+p0

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项目资源可以点击 这里 下载

unity3d 绘制点绘制线 相关内容

2018-07-04 17:48:31 IT_yanghui 阅读数 1948
• ###### 深入浅出Unity3D——第一篇

Unity3D基础知识、游戏算法一网打尽。

74816 人正在学习 去看看 何韬

1.动态添加（删除）路径点，通过两个以上的路径点来绘制曲线，删除点之后不影响其他点绘制曲线；

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

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

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

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)
if (null == m_controlPoint)
}
void SetLine()
{
if (null == m_lineRenderer)
m_lineRenderer = GetComponent<LineRenderer>();
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;
}
{
//初始化时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));

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

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++)
{
}
}
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);
}
}
}
{
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
{
public bool m_isLockX = false;
public bool m_isLockY = true;
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)
if (lineRenderer)
{
lineRenderer.sortingOrder = 1;
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;

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();
}
}
}```

3. Test.cs （任意挂载）

```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);
}
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());
}
}
}
}```

unity3d 绘制点绘制线 相关内容

2017-04-11 12:09:14 daka2012 阅读数 1196
• ###### 深入浅出Unity3D——第一篇

Unity3D基础知识、游戏算法一网打尽。

74816 人正在学习 去看看 何韬

```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
{
}
}
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];
mesh = meshFilter.mesh as Mesh;
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.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;
}
}

//添加阻挡块
{
myedge.points = roundpoints;
}

public Vector2[] WorldPoints(Vector2[] localpoints)
{
for(int i = 0; i < localpoints.Length; i++)
{
localpoints[i] += transform.position.IgnoreZAxis();
}
return localpoints;
}
}```

unity3d 绘制点绘制线 相关内容

2015-01-20 11:45:47 xiao69 阅读数 4448
• ###### 深入浅出Unity3D——第一篇

Unity3D基础知识、游戏算法一网打尽。

74816 人正在学习 去看看 何韬
```using UnityEngine;
using System.Collections;

public class DrawLines : MonoBehaviour {
public Material mat;
public Color col = Color.red;
private Vector3 pos1, pos2;
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))
{

{
pos1 = Input.mousePosition;
}

}
if(Input.GetMouseButtonUp(0))
{
pos2 = Input.mousePosition;

}
if(Input.GetMouseButtonUp(1))
{
}
}
void OnPostRender()
{
{
GL.PushMatrix();
mat.SetPass(0);
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 绘制点绘制线 相关内容