Unity 实用方法 合集
- Unity 打字机效果
- 2D 坐标旋转计算
- 球面坐标求值
- 平滑移动
- 鼠标位置获取2D
- 屏幕坐标转世界坐标
- 物体朝向目标
- 多物体中心点生成
- 本地图片加载
- 画面线框显示
- 画面线框显示 搭载效果
- 贝塞尔曲线绘制
- 贝塞尔曲线绘制 搭载效果
- 网格弯曲
- 网格弯曲 搭载效果
- Delaunay 模型生成
代码很简单没有难度,都有注解,可以收藏一下方便后期使用。
Unity 打字机效果
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;/// <summary>
/// 打字机效果
/// </summary>
public class TextWriter_ZH : MonoBehaviour
{[Header("打字速度")]public float _Delay = 0.1f;[Header("完整的文字")]public string _FullText;// 当前显示的文字private string _CurrentText = "";// 计时器private float _Timer;// 当前字符索引private int _CurrentIndex = 0; void Start(){StartCoroutine(ShowText());}void Update(){if (Input.GetKeyDown(KeyCode.T)){// 获取当前时间,精确到秒级float _CurrentTime = Time.time;// 将秒级时间转换为毫秒级时间int _Milliseconds = (int)((_CurrentTime - Mathf.Floor(_CurrentTime)) * 1000); Debug.Log("Current Time: " + System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss." + _Milliseconds.ToString("000")));_FullText = "当前时间是: " + System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss." + _Milliseconds.ToString("000"));//初始化GetComponent<Text>().text = "";_CurrentIndex = 0;}}/// <summary>/// 文字显示/// </summary>/// <returns></returns>IEnumerator ShowText(){//字符长度判断while (_CurrentIndex < _FullText.Length){//时间累加_Timer += Time.deltaTime;if (_Timer >= _Delay){//文字输出_CurrentText += _FullText[_CurrentIndex];//显示GetComponent<Text>().text = _CurrentText;//步进_CurrentIndex++;_Timer = 0;}yield return null;}}
}
2D 坐标旋转计算
原理:以自身为原点,计算增加半径 R 并且旋转 指定角度后 圆上坐标
应用:应用方向有很多吧 比如旋转动量计算,等边三角形遍历等
/// <summary>/// 2D 坐标旋转计算/// </summary>public void AngleCalculation2D(){// 假设原坐标的 x 值为 3double _X = 3;// 假设原坐标的 y 值为 4double _Y = 4;// 假设半径为 5double _Radius = 5;// 假设旋转角度为 30 度double _Angle = 30;// 将角度转换为弧度double _Radian = _Angle * Math.PI / 180;// 计算旋转后的 X Y 坐标double _NewX = _X * Math.Cos(_Radian) - _Y * Math.Sin(_Radian);double _NewY = _X * Math.Sin(_Radian) + _Y * Math.Cos(_Radian);// 计算旋转后点的距离原点的半径double _NewRadius = Math.Sqrt(_NewX * _NewX + _NewY * _NewY);// 考虑半径对坐标的缩放double _FinalX = _NewX * _Radius / _NewRadius;double _FinalY = _NewY * _Radius / _NewRadius;Vector2 _Vector2 = new Vector2((float)_FinalX, (float)_FinalY);Console.WriteLine("旋转后的坐标:({0})", _Vector2);}
球面坐标求值
原理:根据给定的圆心坐标和目标坐标,得到圆心到目标位置的向量。根据要求的延长半径和旋转角度再把夹角转换为弧度之后得到目标点的球面坐标值 并返回
应用:球面计算和均匀分配
/// <summary>/// 3D 坐标旋转计算/// </summary>/// <param 圆心坐标="_Center"></param>/// <param 半径="_Radius"></param>/// <param 目标位置="_PointA"></param>/// <param 旋转角度="_Angle"></param>public void AngleCalculation3D(Vector3 _Center, float _Radius, Vector3 _PointA, float _Angle){ 假设圆心坐标为 (1, 2, 3)//Vector3 _Center = new Vector3(1, 2, 3); 假设半径为 5//float _Radius = 5; 假设三维坐标点 a 为 (4, 5, 6)//Vector3 _PointA = new Vector3(4, 5, 6); 假设旋转角度为 30 度//float _Angle = 30;//转换后球面坐标值Vector3 _RotatedPoint = RotatePoint(_Center, _PointA, _Radius, _Angle);Console.WriteLine("旋转后的球面坐标:");//magnitude 返回该向量的长度Console.WriteLine("半径:{0}", _RotatedPoint.magnitude);//Rad2Deg 弧度到度数的转换常数Console.WriteLine("纬度:{0}", Mathf.Rad2Deg * Mathf.Asin(_RotatedPoint.normalized.y));Console.WriteLine("经度:{0}", Mathf.Rad2Deg * Mathf.Atan2(_RotatedPoint.normalized.z, _RotatedPoint.normalized.x));}
/// <summary>/// 球面坐标求值/// </summary>/// <param 圆心坐标="_Center"></param>/// <param 目标位置="_Point"></param>/// <param 半径="_Radius"></param>/// <param 旋转角度="_Angle"></param>/// <returns></returns>public static Vector3 RotatePoint(Vector3 _Center, Vector3 _Point, float _Radius, float _Angle){// 统一坐标系Vector3 _ShiftedPoint = _Point - _Center;// 计算旋转后的坐标float _Radian = _Angle * Mathf.Deg2Rad;float _RotatedX = _ShiftedPoint.x * Mathf.Cos(_Radian) - _ShiftedPoint.z * Mathf.Sin(_Radian);float _RotatedY = _ShiftedPoint.y;float _RotatedZ = _ShiftedPoint.x * Mathf.Sin(_Radian) + _ShiftedPoint.z * Mathf.Cos(_Radian);// 计算旋转后的球面坐标Vector3 _RotatedPoint = new Vector3(_RotatedX, _RotatedY, _RotatedZ).normalized * _Radius;// 返回旋转后的点return _RotatedPoint;}
平滑移动
原理:Vector3.Lerp 插值计算 然后返回趋近值
应用:字面意思 平滑 可以应用到双曲线螺旋
/// <summary>/// 平滑移动/// </summary>/// <param name="_ObjectToMove"></param>/// <param name="_TargetPosition"></param>/// <param name="_Duration"></param>/// <returns></returns>public IEnumerator SmoothMoveObject(Transform _ObjectToMove, Vector3 _TargetPosition, float _Duration){float _ElapsedTime = 0f;Vector3 _StartingPosition = _ObjectToMove.position;while (_ElapsedTime < _Duration){_ObjectToMove.position = Vector3.Lerp(_StartingPosition, _TargetPosition, _ElapsedTime / _Duration);_ElapsedTime += Time.deltaTime;yield return null;}_ObjectToMove.position = _TargetPosition;}
鼠标位置获取2D
原理:Camera.main.ScreenToWorldPoint
应用:获取鼠标在2D空间中的位置,通常用于2D游戏的鼠标交互
/// <summary>/// 鼠标位置获取/// </summary>/// <returns></returns>public Vector2 GetMousePosition2D(){Vector3 _MousePosition = Input.mousePosition;_MousePosition.z = -Camera.main.transform.position.z;return Camera.main.ScreenToWorldPoint(_MousePosition);}
屏幕坐标转世界坐标
原理:Camera.main.ScreenToWorldPoint
应用:将屏幕坐标转换为世界坐标,通常用于将鼠标点击位置转换为游戏世界中的坐标
/// <summary>/// 屏幕坐标转世界坐标/// </summary>/// <param name="screenPosition"></param>/// <returns></returns>public Vector3 ScreenToWorldPoint(Vector3 _ScreenPosition){return Camera.main.ScreenToWorldPoint(_ScreenPosition);}
物体朝向目标
原理: Quaternion.LookRotation()
应用:使物体的正面朝向目标位置
/// <summary>/// 物体朝向目标/// </summary>/// <param 当前物体 ="_ObjectToRotate"></param>/// <param 朝向目标 ="_TargetPosition"></param>public void LookAtTarget(Transform _ObjectToRotate, Vector3 _TargetPosition){Vector3 _Direction = _TargetPosition - _ObjectToRotate.position;Quaternion _Rotation = Quaternion.LookRotation(_Direction);_ObjectToRotate.rotation = _Rotation;}
多物体中心点生成
原理:所有位置向量累加并除以数量得到平均值
应用:鱼群算法中心计算、多物体连线等
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 多物体中心点判定
/// </summary>
public class ObjectsCenterPoint_ZH : MonoBehaviour
{public List<GameObject> _GameObject; // 存储多个物体的数组private void Start(){// 计算中心点Vector3 _CenterPoint = CalculateCenterPoint();// 在场景中创建一个表示中心点的标记物体CreateCenterPointMarker(_CenterPoint);}/// <summary>/// 中心点坐标/// </summary>/// <returns></returns>Vector3 CalculateCenterPoint(){Vector3 _CenterPoint = Vector3.zero;// 累加所有物体的位置foreach (GameObject obj in _GameObject){_CenterPoint += obj.transform.position;}// 求取平均位置_CenterPoint /= _GameObject.Count;return _CenterPoint;}/// <summary>/// 中心点位置 物体生成/// </summary>/// <param 中心点位置="_CenterPoint"></param>void CreateCenterPointMarker(Vector3 _CenterPoint){// 在场景中创建一个标记物体表示中心点GameObject _Marker = GameObject.CreatePrimitive(PrimitiveType.Sphere);_Marker.transform.position = _CenterPoint;_Marker.transform.localScale = Vector3.one * 0.5f;_Marker.GetComponent<Renderer>().material.color = Color.red;}
}
本地图片加载
原理:IO流 读取
应用:场景加载界面或则动态变更图标
using UnityEngine;
using UnityEngine.UI;/// <summary>
/// 图片加载
/// </summary>
public class ImageLoader_ZH : MonoBehaviour
{public string _ImagePath;public RawImage _RawImage;private void Start(){// 加载本地图片Texture2D _Texture = LoadLocalImage(_ImagePath);if (_Texture != null){// 将纹理设置给RawImage组件进行显示_RawImage.texture = _Texture;}else{Debug.LogError("没有显示载体。");}}private Texture2D LoadLocalImage(string _Path){// 使用Unity的API加载本地图片// 创建一个空的Texture2D对象Texture2D _Texture = new Texture2D(2, 2);// 读取图片数据byte[] _ImageData = System.IO.File.ReadAllBytes(_Path);// 将图片数据加载到Texture2D对象中bool _Success = _Texture.LoadImage(_ImageData); if (_Success){return _Texture;}else{Destroy(_Texture); // 加载失败时销毁Texture2D对象return null;}}
}
画面线框显示
原理: 就是 GL 绘画应用变形
应用:画面标注、主题框选等
/// <summary>/// 在渲染后执行/// 屏幕框选/// </summary>private void OnPostRender(){//画线这种操作推荐在 OnPostRender()里进行 而不是直接放在Update,所以需要标志来开启if (_IsSelecting){//开始绘图位置var startMousePosition = MousePosition;//鼠标当前位置Vector3 _MouseEnd = Input.mousePosition;//保存摄像机变换矩阵GL.PushMatrix();//显示材质if (!_RectMat){return;} else{//生成画线的材质_RectMat = new Material(Shader.Find("UI/Default"));//GameObject(游戏对象)没有显示在层次结构中,没有保存到场景中,也没有被Resources.UnloadUnusedAssets卸载。_RectMat.hideFlags = HideFlags.HideAndDontSave;//Gameobject(游戏对象)没有显示在层次结构中,没有保存到场景中,也没有被Resources.UnloadUnusedAssets卸载_RectMat.shader.hideFlags = HideFlags.HideAndDontSave;}_RectMat.SetPass(0);//设置用屏幕坐标绘图GL.LoadPixelMatrix();GL.Begin(GL.QUADS);//设置颜色和透明度,方框内部透明GL.Color(new Color(_RectColor.r, _RectColor.g, _RectColor.b, 0.1f));GL.Vertex3(startMousePosition.x, startMousePosition.y, 0);GL.Vertex3(_MouseEnd.x, startMousePosition.y, 0);GL.Vertex3(_MouseEnd.x, _MouseEnd.y, 0);GL.Vertex3(startMousePosition.x, _MouseEnd.y, 0);GL.End();GL.Begin(GL.LINES);//设置方框的边框颜色 边框不透明GL.Color(_RectColor);GL.Vertex3(startMousePosition.x, startMousePosition.y, 0);GL.Vertex3(_MouseEnd.x, startMousePosition.y, 0);GL.Vertex3(_MouseEnd.x, startMousePosition.y, 0);GL.Vertex3(_MouseEnd.x, _MouseEnd.y, 0);GL.Vertex3(_MouseEnd.x, _MouseEnd.y, 0);GL.Vertex3(startMousePosition.x, _MouseEnd.y, 0);GL.Vertex3(startMousePosition.x, _MouseEnd.y, 0);GL.Vertex3(startMousePosition.x, startMousePosition.y, 0);GL.End();//恢复摄像机投影矩阵GL.PopMatrix();}}
画面线框显示 搭载效果
贝塞尔曲线绘制
原理:P(t) = (1 - t)^2 * P0 + 2 * (1 - t) * t * P1 + t^2 * P2曲线上的点可以通过参数t(取值范围为0到1)来表示。参数t表示曲线上某一点的位置,其中t=0表示起点,t=1表示终点。对于给定的t值,可以使用以下公式计算曲线上的点P(t)的坐标:其中,P0、P1和P2分别是起点、控制点和终点的坐标。
应用:物体弯曲,道路生成,画面扭曲等扩展:三次贝塞尔曲线:三次贝塞尔曲线由四个锚点(起点、终点和两个控制点)组成。P(t) = (1 - t)^3 * P0 + 3 * (1 - t)^2 * t * P1 + 3 * (1 - t) * t^2 * P2 + t^3 * P3P0、P1、P2和P3分别是起点、两个控制点和终点的坐标。通过调整控制点的位置,可以改变贝塞尔曲线的形状。控制点的位置决定了曲线的弯曲程度和方向。
using UnityEngine;
/// <summary>
/// 贝塞尔曲线绘制
/// </summary>
public class BezierCurve_ZH : MonoBehaviour
{[Header("开始位置")]public Transform _StartPoint;[Header("控制带你")]public Transform _ControlPoint;[Header("结束位置")]public Transform _EndPoint;[Header("精度")]//越高越平滑 性能消耗越大public int _Resolution = 10;private void OnDrawGizmos(){DrawBezierCurve();}/// <summary>/// 贝塞尔曲线绘制/// </summary>private void DrawBezierCurve(){//曲线数组Vector3[] _Points = new Vector3[_Resolution + 1];//数组变更for (int i = 0; i <= _Resolution; i++){float t = i / (float)_Resolution;_Points[i] = CalculatePointOnCurve(t);}//绘制颜色Gizmos.color = Color.cyan;//曲线绘制for (int i = 0; i < _Resolution; i++){Gizmos.DrawLine(_Points[i], _Points[i + 1]);}}/// <summary>/// 计算曲线上的点/// </summary>/// <param name="t"></param>/// <returns></returns>private Vector3 CalculatePointOnCurve(float t){float u = 1 - t;float tt = t * t;float uu = u * u;Vector3 point = uu * _StartPoint.position;point += 2 * u * t * _ControlPoint.position;point += tt * _EndPoint.position;return point;}
}
贝塞尔曲线绘制 搭载效果
网格弯曲
原理:使用 三次贝塞尔曲线 得到变形后的顶点,然后根据变形后的顶点进行网格重组
应用:物体弯曲,道路生成,画面扭曲等
using UnityEngine;/// <summary>
/// 网格弯曲
/// </summary>
public class ObjectBender_ZH : MonoBehaviour
{//起始点public Transform _StartPoint;//控制点 1public Transform _ControlPoint1;//控制点 2public Transform _ControlPoint2;//结束点public Transform _EndPoint;//精细程度public int _Eesolution = 10;//变形网格public MeshFilter _MeshFilter;//出十万个private Mesh _OriginalMesh;//变形网格private Mesh _BentMesh;private void Start(){//初始化//_MeshFilter = GetComponent<MeshFilter>();_OriginalMesh = _MeshFilter.mesh;_BentMesh = new Mesh();_MeshFilter.mesh = _BentMesh;BendObject();}private void Update(){BendObject();}/// <summary>/// 网格变形方法/// </summary>private void BendObject(){//顶点数组Vector3[] _Vertices = _OriginalMesh.vertices;//变形顶点数组Vector3[] _BentVertices = new Vector3[_Vertices.Length];//变形顶点 遍历赋值for (int i = 0; i < _Vertices.Length; i++){Vector3 vertex = _Vertices[i];Vector3 bentPosition = BendVertex(vertex);_BentVertices[i] = bentPosition;}//顶点 三角面 法线 设置_BentMesh.vertices = _BentVertices;_BentMesh.triangles = _OriginalMesh.triangles;_BentMesh.RecalculateNormals();}/// <summary>/// 顶点变形 重组/// </summary>/// <param name="_Vertex"></param>/// <returns></returns>private Vector3 BendVertex(Vector3 _Vertex){float t = _Vertex.x / (float)(_OriginalMesh.bounds.size.x);Vector3 _StartPointPosition = _StartPoint.position;Vector3 _ControlPoint1Position = _ControlPoint1.position;Vector3 _ControlPoint2Position = _ControlPoint2.position;Vector3 _EndPointPosition = _EndPoint.position;Vector3 _BentPosition = CalculatePointOnCurve(t, _StartPointPosition, _ControlPoint1Position, _ControlPoint2Position, _EndPointPosition);return _BentPosition;}/// <summary>/// 曲线计算/// 三次贝塞尔曲线/// </summary>/// <param 变形 t ="t"></param>/// <param 开始位置="_StartPoint"></param>/// <param 控制点01="_ControlPoint1"></param>/// <param 控制点02 ="_ControlPoint2"></param>/// <param 结束位置="_EndPoint"></param>/// <returns></returns>private Vector3 CalculatePointOnCurve(float t, Vector3 _StartPoint, Vector3 _ControlPoint1, Vector3 _ControlPoint2, Vector3 _EndPoint){float t2 = t * t;float t3 = t2 * t;Vector3 _Point =0.5f * ((2.0f * _ControlPoint1) +(-_StartPoint + _EndPoint) * t +(2.0f * _StartPoint - 5.0f * _ControlPoint1 + 4.0f * _ControlPoint2 - _EndPoint) * t2 +(-_StartPoint + 3.0f * _ControlPoint1 - 3.0f * _ControlPoint2 + _EndPoint) * t3);return _Point;}
}
网格弯曲 搭载效果
注意需要勾选导入模型的读写权限
变形前
变形后
Delaunay 模型生成
原理:就是使用 Delaunay 算法进行 外接圆判断
应用:模型生成、动态模型补面、最大面积计算等
有一点不完善,过两天抽时间单独研究研究,再出一篇看看。
填坑了哈,大家如果有兴趣可以去看看。
Delaunay 算法 的 解析 : Unity Delaunay三角剖分算法
using UnityEngine;
using System.Collections.Generic;/// <summary>
/// Delaunay 模型生成
/// </summary>
public class DelaunayAlgorithm : MonoBehaviour
{[Header("存储要生成 Delaunay 物体")]public List<Transform> _TraList = new List<Transform>();[Header("存储要生成 Delaunay 三角网格的点")]private List<Vector2> _Points = new List<Vector2>();// 存储生成的三角形private List<Triangle> _Triangles = new List<Triangle>(); private void Start(){for (int i = 0; i < _TraList.Count; i++){_Points.Add(new Vector2(_TraList[i].position.x, _TraList[i].position.z));}GenerateDelaunay();}/// <summary>/// Delaunay 三角形生成/// </summary>void GenerateDelaunay(){// 在点集中加入一个超级三角形float _MinX = float.MaxValue;float _MinY = float.MaxValue;float _MaxX = float.MinValue;float _MaxY = float.MinValue;//最大值最小值判定foreach (Vector2 _Point in _Points){if (_Point.x < _MinX) _MinX = _Point.x;if (_Point.y < _MinY) _MinY = _Point.y;if (_Point.x > _MaxX) _MaxX = _Point.x;if (_Point.y > _MaxY) _MaxY = _Point.y;}float _DeltaX = _MaxX - _MinX;float _DeltaY = _MaxY - _MinY;float _DeltaMax = Mathf.Max(_DeltaX, _DeltaY);float _MidX = (_MinX + _MaxX) / 2f;float _MidY = (_MinY + _MaxY) / 2f;Vector2 p1 = new Vector2(_MidX - 20 * _DeltaMax, _MidY - _DeltaMax);Vector2 p2 = new Vector2(_MidX, _MidY + 20 * _DeltaMax);Vector2 p3 = new Vector2(_MidX + 20 * _DeltaMax, _MidY - _DeltaMax);//三角形片元 添加_Triangles.Add(new Triangle(p1, p2, p3));// 逐个加入点并更新三角形foreach (Vector2 _Point in _Points){List<Edge> _Polygon = new List<Edge>();for (int i = _Triangles.Count - 1; i >= 0; i--){//如果是外接圆就证明 当前三角形是 Delaunay 三角形//如果有任何一个点在其他三角形的外接圆内,则该三角形不是Delaunay三角形。if (_Triangles[i].CircumcircleContains(_Point)){_Polygon.Add(_Triangles[i].e1);_Polygon.Add(_Triangles[i].e2);_Polygon.Add(_Triangles[i].e3);_Triangles.RemoveAt(i);}}//顶点移除for (int i = _Polygon.Count - 2; i >= 0; i--){for (int j = _Polygon.Count - 1; j >= i + 1; j--){if (_Polygon[i] == _Polygon[j]){_Polygon.RemoveAt(j);_Polygon.RemoveAt(i);j--;}}}//加入片元 数组foreach (Edge edge in _Polygon){_Triangles.Add(new Triangle(edge.p1, edge.p2, _Point));}}// 剔除超级三角形相关的三角形List<Triangle> _TrianglesToRemove = new List<Triangle>();foreach (Triangle _Triangle in _Triangles){if (_Triangle.ContainsAnyVertex(p1, p2, p3)){_TrianglesToRemove.Add(_Triangle);}}foreach (Triangle triangle in _TrianglesToRemove){_Triangles.Remove(triangle);}// 在 Unity 中绘制生成的三角形 Delaunayforeach (Triangle _Triangle in _Triangles){//if (_Triangle.e1.IsDelaunayEdge(_Triangles))//{// Debug.DrawLine(_Triangle.p1, _Triangle.p2, Color.green, 15f);//}//if (_Triangle.e2.IsDelaunayEdge(_Triangles))//{// Debug.DrawLine(_Triangle.p2, _Triangle.p3, Color.green, 15f);//}//if (_Triangle.e3.IsDelaunayEdge(_Triangles))//{// Debug.DrawLine(_Triangle.p3, _Triangle.p1, Color.green, 15f);//}Debug.DrawLine(_Triangle.p1, _Triangle.p2, Color.green, 15f);Debug.DrawLine(_Triangle.p2, _Triangle.p3, Color.green, 15f);Debug.DrawLine(_Triangle.p3, _Triangle.p1, Color.green, 15f);}}
}/// <summary>
/// 三角形数据类
/// </summary>
public class Triangle
{// 三角形的顶点public Vector2 p1, p2, p3;// 三角形的边public Edge e1, e2, e3;/// <summary>/// 三角形 片元/// </summary>/// <param 顶点="p1"></param>/// <param 顶点="p2"></param>/// <param 顶点="p3"></param>/// <returns></returns>public Triangle(Vector2 p1, Vector2 p2, Vector2 p3){this.p1 = p1;this.p2 = p2;this.p3 = p3;e1 = new Edge(p1, p2);e2 = new Edge(p2, p3);e3 = new Edge(p3, p1);}/// <summary>/// 检查三角形的外接圆是否包含指定的点/// 给定的点在三角形的外接圆内,返回true;否则,说明给定的点不在外接圆内,返回false/// </summary>/// <param 顶点="point"></param>/// <returns></returns>public bool CircumcircleContains(Vector2 point){//计算三角形的外接圆的圆心和半径float d1 = (p1.x - point.x) * (p1.x - point.x) + (p1.y - point.y) * (p1.y - point.y);float d2 = (p2.x - point.x) * (p2.x - point.x) + (p2.y - point.y) * (p2.y - point.y);float d3 = (p3.x - point.x) * (p3.x - point.x) + (p3.y - point.y) * (p3.y - point.y);float a = (p1.x * (p2.y - p3.y) + p2.x * (p3.y - p1.y) + p3.x * (p1.y - p2.y)) * 2f;if (Mathf.Abs(a) < 0.00001f){return false;}//检查指定点与圆心的距离是否小于或等于半径的平方float centerX = ((p1.x * p1.x + p1.y * p1.y) * (p2.y - p3.y) + (p2.x * p2.x + p2.y * p2.y) * (p3.y - p1.y) + (p3.x * p3.x + p3.y * p3.y) * (p1.y - p2.y)) / a;float centerY = ((p1.x * p1.x + p1.y * p1.y) * (p3.x - p2.x) + (p2.x * p2.x + p2.y * p2.y) * (p1.x - p3.x) + (p3.x * p3.x + p3.y * p3.y) * (p2.x - p1.x)) / a;float radius = Mathf.Sqrt((centerX - p1.x) * (centerX - p1.x) + (centerY - p1.y) * (centerY - p1.y));float dist = (point.x - centerX) * (point.x - centerX) + (point.y - centerY) * (point.y - centerY);return dist <= radius * radius;}/// <summary>/// 检查三角形是否包含指定的顶点/// 最大三角形判定/// </summary>/// <param name="v1"></param>/// <param name="v2"></param>/// <param name="v3"></param>/// <returns></returns>public bool ContainsAnyVertex(Vector2 v1, Vector2 v2, Vector2 v3){return p1 == v1 || p1 == v2 || p1 == v3 ||p2 == v1 || p2 == v2 || p2 == v3 ||p3 == v1 || p3 == v2 || p3 == v3;}/ <summary>/ Delaunay边 判定/ 确定是否绘制当前三角形的边/ </summary>/ <returns></returns>//public bool IsDelaunay()//{// // 检查三角形的每条边是否是Delaunay边// //return e1.IsDelaunayEdge() && e2.IsDelaunayEdge() && e3.IsDelaunayEdge();//}}/// <summary>
/// 三角边
/// 表示边的类
/// </summary>
public class Edge
{// 边的两个顶点public Vector2 p1, p2;public Edge(Vector2 p1, Vector2 p2){this.p1 = p1;this.p2 = p2;}/// <summary>/// 重写 Equals 方法,用于比较边的相等性/// </summary>/// <param name="obj"></param>/// <returns></returns>public override bool Equals(object obj){if (obj == null || GetType() != obj.GetType()){return false;}Edge other = (Edge)obj;return (p1 == other.p1 && p2 == other.p2) || (p1 == other.p2 && p2 == other.p1);}/// <summary>/// 重写 GetHashCode 方法,用于哈希表存储/// </summary>/// <returns></returns>public override int GetHashCode(){return p1.GetHashCode() ^ p2.GetHashCode();}/// <summary>/// Delaunay 三角边判断/// </summary>/// <param 三角片元数组="_Triangles"></param>/// <returns></returns>public bool IsDelaunayEdge(List<Triangle> _Triangles){// 检查当前边是否与其他三角形的外接圆相交foreach (Triangle _Triangle in _Triangles){if (_Triangle.CircumcircleContains(new Vector2(p1.x, p1.y)) || _Triangle.CircumcircleContains(new Vector2(p2.x, p2.y))){return false;}}return true;}
}
最大三角形
生成物体分布
生成网格 有点问题 需要后期修改
暂时先这样吧,如果有时间的话就会更新,实在看不明白就留言,看到我会回复的。
路漫漫其修远兮,与君共勉。