using System.Collections; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; public class MonsterMoveLine { public static Dictionary dic_BezierCurveDatas=new Dictionary(); public static List curves = new List(); public class BezierCurveData { public string name; public Vector2 start; public List controlPoints = new List(); public Vector2 end; } public static async void LoadBezier() { await LoadBezierTxtAsync("MoveLine"); } /// /// 读取曲线数据 读取单个 /// /// /// public static async Task LoadSingleBezierTxtAsync(string path) { AsyncOperationHandle handle = Addressables.LoadAssetAsync(path); await handle.Task; var lines = handle.Result.text.Split('\n'); foreach (var line in lines) { if (string.IsNullOrWhiteSpace(line)) continue; var parts = line.Split(';'); BezierCurveData curve = new BezierCurveData(); // 第一个是曲线名 curve.name = parts[0]; // 后面所有都是点 List points = new List(); for (int i = 1; i < parts.Length; i++) { points.Add(ParseVector(parts[i])); } // 第一个点是 start curve.start = points[0]; if (points.Count > 1) { // 最后一个点是 end curve.end = points[points.Count - 1]; } // 中间的都是 controlPoints for (int i = 1; i < points.Count - 1; i++) { curve.controlPoints.Add(points[i]); } curves.Add(curve); dic_BezierCurveDatas.Add(curve.name, curve); } } /// /// 读取曲线数据 游戏开始时在awake调用aa包 /// /// /// public static async Task LoadBezierTxtAsync(string path) { List keys=new List(); keys.Add(path); keys.Add(GameManager.Instance.gameData.currGameType.ToString()); AsyncOperationHandle> handles = Addressables.LoadAssetsAsync(keys, null,Addressables.MergeMode.Intersection); await handles.Task; foreach (var text in handles.Result) { var lines = text.text.Split('\n'); foreach (var line in lines) { if (string.IsNullOrWhiteSpace(line)) continue; var parts = line.Split(';'); BezierCurveData curve = new BezierCurveData(); // 第一个是曲线名 curve.name = parts[0]; // 后面所有都是点 List points = new List(); for (int i = 1; i < parts.Length; i++) { points.Add(ParseVector(parts[i])); } // 第一个点是 start curve.start = points[0]; if (points.Count > 1) { // 最后一个点是 end curve.end = points[points.Count - 1]; } // 中间的都是 controlPoints for (int i = 1; i < points.Count - 1; i++) { curve.controlPoints.Add(points[i]); } curves.Add(curve); dic_BezierCurveDatas.Add(curve.name, curve); } } Debug.Log("曲线读取完成共" + dic_BezierCurveDatas.Count + "条"); } private static Vector2 ParseVector(string s) { var xy = s.Split(','); return new Vector2(float.Parse(xy[0]), float.Parse(xy[1])); } public BezierCurveData bezierCurveData; public float moveTime; public float moveSpeed; public void Init(BezierCurveData bezierCurveData, float Time) { this.bezierCurveData = bezierCurveData; this.moveTime = Time; Debug.Log($"初始化曲线 {this.bezierCurveData.name} ,移动时间 {moveTime}"); } /// /// 获取曲线上的点 /// /// /// public Vector2 GetBezierPoint(float t) { t = t / moveTime; BezierCurveData curve=bezierCurveData; List points = new List(); points.Add(curve.start); points.AddRange(curve.controlPoints); points.Add(curve.end); return DeCasteljau_BY(points, t%1); } /// /// 贝塞尔 /// /// /// /// private Vector2 DeCasteljau_BSE(List points, float t) { while (points.Count > 1) { List next = new List(); for (int i = 0; i < points.Count - 1; i++) { next.Add(Vector2.Lerp(points[i], points[i + 1], t)); } points = next; } return CoordinateTransformation.CanvasToWorld( points[0],UIManager.Instance.uiRoot.GetComponent(),Camera.main); } /// /// B样 /// /// /// /// private Vector2 DeCasteljau_BY(List points, float t) { // 方法A:保持德卡斯特里奥算法(推荐,数值更稳定) while (points.Count > 1) { List next = new List(); for (int i = 0; i < points.Count - 1; i++) { next.Add(Vector2.Lerp(points[i], points[i + 1], t)); } points = next; } return CoordinateTransformation.CanvasToWorld(points[0], UIManager.Instance.uiRoot.GetComponent(), Camera.main); /* 方法B:伯恩斯坦多项式形式(标准贝塞尔公式)- 如果要用这个替换上面的循环 int n = points.Count - 1; Vector2 result = Vector2.zero; for (int i = 0; i <= n; i++) { float bernstein = BinomialCoefficient(n, i) * Mathf.Pow(t, i) * Mathf.Pow(1 - t, n - i); result += points[i] * bernstein; } return CoordinateTransformation.CanvasToWorld(result, UIManager.Instance.uiRoot.GetComponent(), Camera.main); */ } // 计算二项式系数 private float BinomialCoefficient(int n, int k) { float result = 1f; for (int i = 1; i <= k; i++) { result *= (float)(n - k + i) / i; } return result; } }