2026-07-28 10:59:08 +08:00
|
|
|
|
#region AI优化
|
2026-03-31 18:30:49 +08:00
|
|
|
|
using System.Collections;
|
2025-12-26 11:15:56 +08:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using UnityEngine.AddressableAssets;
|
|
|
|
|
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
2026-07-05 16:07:22 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
[Serializable]
|
2025-12-26 11:15:56 +08:00
|
|
|
|
public class MonsterMoveLine
|
|
|
|
|
|
{
|
2026-03-31 18:30:49 +08:00
|
|
|
|
public static Dictionary<string, BezierCurveData> dic_BezierCurveDatas = new Dictionary<string, BezierCurveData>();
|
2025-12-26 11:15:56 +08:00
|
|
|
|
public static List<BezierCurveData> curves = new List<BezierCurveData>();
|
2026-08-04 14:52:22 +08:00
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
|
|
// ⭐ 性能优化:曲线点数组静态缓存
|
|
|
|
|
|
// 每条曲线的 [start, controlPoints..., end] 预组装成 Vector2[],
|
|
|
|
|
|
// 所有鱼共享同一份数组,避免每帧每鱼 new List + ToArray 的 GC 分配。
|
|
|
|
|
|
// 加载时构建,卸载时清理。
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
|
|
private static readonly Dictionary<string, Vector2[]> _curvePointsArrays
|
|
|
|
|
|
= new Dictionary<string, Vector2[]>();
|
2026-07-05 16:07:22 +08:00
|
|
|
|
[Serializable]
|
2025-12-26 11:15:56 +08:00
|
|
|
|
public class BezierCurveData
|
|
|
|
|
|
{
|
|
|
|
|
|
public string name;
|
|
|
|
|
|
public Vector2 start;
|
|
|
|
|
|
public List<Vector2> controlPoints = new List<Vector2>();
|
|
|
|
|
|
public Vector2 end;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-01 06:26:50 +08:00
|
|
|
|
public static async Task LoadBezier()
|
2026-02-03 11:35:19 +08:00
|
|
|
|
{
|
|
|
|
|
|
await LoadBezierTxtAsync("MoveLine");
|
|
|
|
|
|
}
|
2026-05-01 06:26:50 +08:00
|
|
|
|
public static async Task UnLoadBezier()
|
|
|
|
|
|
{
|
|
|
|
|
|
await UnLoadBezierTxtAsync("MoveLine");
|
|
|
|
|
|
}
|
2026-03-31 18:30:49 +08:00
|
|
|
|
|
2026-02-03 11:35:19 +08:00
|
|
|
|
public static async Task LoadSingleBezierTxtAsync(string path)
|
2025-12-26 11:15:56 +08:00
|
|
|
|
{
|
|
|
|
|
|
AsyncOperationHandle<TextAsset> handle = Addressables.LoadAssetAsync<TextAsset>(path);
|
|
|
|
|
|
await handle.Task;
|
|
|
|
|
|
var lines = handle.Result.text.Split('\n');
|
2026-02-03 11:35:19 +08:00
|
|
|
|
|
2025-12-26 11:15:56 +08:00
|
|
|
|
foreach (var line in lines)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(line)) continue;
|
|
|
|
|
|
|
|
|
|
|
|
var parts = line.Split(';');
|
|
|
|
|
|
BezierCurveData curve = new BezierCurveData();
|
|
|
|
|
|
curve.name = parts[0];
|
|
|
|
|
|
|
|
|
|
|
|
List<Vector2> points = new List<Vector2>();
|
|
|
|
|
|
for (int i = 1; i < parts.Length; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
points.Add(ParseVector(parts[i]));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
curve.start = points[0];
|
2026-02-03 11:35:19 +08:00
|
|
|
|
if (points.Count > 1)
|
|
|
|
|
|
curve.end = points[points.Count - 1];
|
2025-12-26 11:15:56 +08:00
|
|
|
|
|
|
|
|
|
|
for (int i = 1; i < points.Count - 1; i++)
|
|
|
|
|
|
curve.controlPoints.Add(points[i]);
|
|
|
|
|
|
|
|
|
|
|
|
curves.Add(curve);
|
2026-02-03 11:35:19 +08:00
|
|
|
|
dic_BezierCurveDatas.Add(curve.name, curve);
|
2026-08-04 14:52:22 +08:00
|
|
|
|
// ⭐ 同步构建点数组缓存(单条加载路径)
|
|
|
|
|
|
BuildCurvePointsArray(curve);
|
2026-02-03 11:35:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-31 18:30:49 +08:00
|
|
|
|
|
2026-08-04 14:52:22 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// ⭐ 将曲线的 [start, controlPoints..., end] 组装成 Vector2[] 并缓存。
|
|
|
|
|
|
/// 所有引用此曲线的鱼共享同一份数组,避免每帧每鱼 new List + ToArray 的 GC。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private static void BuildCurvePointsArray(BezierCurveData curve)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_curvePointsArrays.ContainsKey(curve.name)) return;
|
|
|
|
|
|
|
|
|
|
|
|
int total = 2 + curve.controlPoints.Count; // start + controls + end
|
|
|
|
|
|
Vector2[] arr = new Vector2[total];
|
|
|
|
|
|
arr[0] = curve.start;
|
|
|
|
|
|
for (int i = 0; i < curve.controlPoints.Count; i++)
|
|
|
|
|
|
arr[1 + i] = curve.controlPoints[i];
|
|
|
|
|
|
arr[total - 1] = curve.end;
|
|
|
|
|
|
|
|
|
|
|
|
_curvePointsArrays[curve.name] = arr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-03 11:35:19 +08:00
|
|
|
|
public static async Task LoadBezierTxtAsync(string path)
|
|
|
|
|
|
{
|
2026-03-31 18:30:49 +08:00
|
|
|
|
List<string> keys = new List<string>();
|
2026-03-27 15:18:35 +08:00
|
|
|
|
keys.Add(path);
|
|
|
|
|
|
keys.Add(GameManager.Instance.gameData.currGameType.ToString());
|
2026-05-01 06:26:50 +08:00
|
|
|
|
|
|
|
|
|
|
AsyncOperationHandle<IList<TextAsset>> handles = Addressables.LoadAssetsAsync<TextAsset>(
|
|
|
|
|
|
keys, null, Addressables.MergeMode.Intersection);
|
2026-02-03 11:35:19 +08:00
|
|
|
|
await handles.Task;
|
2026-03-31 18:30:49 +08:00
|
|
|
|
|
2026-05-07 03:46:03 +08:00
|
|
|
|
// ⭐ 没有资源 → 直接跳出,不报错
|
|
|
|
|
|
if (handles.Result == null || handles.Result.Count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning($"Bezier 曲线加载跳过:未找到标签 {path} + {GameManager.Instance.gameData.currGameType}");
|
|
|
|
|
|
Addressables.Release(handles);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-03 11:35:19 +08:00
|
|
|
|
foreach (var text in handles.Result)
|
|
|
|
|
|
{
|
2026-03-31 18:30:49 +08:00
|
|
|
|
var lines = text.text.Split('\n');
|
2026-02-03 11:35:19 +08:00
|
|
|
|
foreach (var line in lines)
|
|
|
|
|
|
{
|
2026-05-07 03:46:03 +08:00
|
|
|
|
if (string.IsNullOrWhiteSpace(line))
|
|
|
|
|
|
continue;
|
2026-02-03 11:35:19 +08:00
|
|
|
|
|
|
|
|
|
|
var parts = line.Split(';');
|
2026-05-07 03:46:03 +08:00
|
|
|
|
if (parts.Length < 2)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
2026-02-03 11:35:19 +08:00
|
|
|
|
BezierCurveData curve = new BezierCurveData();
|
|
|
|
|
|
curve.name = parts[0];
|
|
|
|
|
|
|
|
|
|
|
|
List<Vector2> points = new List<Vector2>();
|
|
|
|
|
|
for (int i = 1; i < parts.Length; i++)
|
|
|
|
|
|
{
|
2026-05-07 03:46:03 +08:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(parts[i]))
|
|
|
|
|
|
points.Add(ParseVector(parts[i]));
|
2026-02-03 11:35:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-07 03:46:03 +08:00
|
|
|
|
if (points.Count == 0)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
2026-02-03 11:35:19 +08:00
|
|
|
|
curve.start = points[0];
|
|
|
|
|
|
if (points.Count > 1)
|
|
|
|
|
|
curve.end = points[points.Count - 1];
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 1; i < points.Count - 1; i++)
|
|
|
|
|
|
curve.controlPoints.Add(points[i]);
|
|
|
|
|
|
|
|
|
|
|
|
curves.Add(curve);
|
2026-05-01 06:26:50 +08:00
|
|
|
|
|
2026-05-07 03:46:03 +08:00
|
|
|
|
// 不覆盖旧数据
|
|
|
|
|
|
if (!dic_BezierCurveDatas.ContainsKey(curve.name))
|
2026-08-04 14:52:22 +08:00
|
|
|
|
{
|
2026-05-07 03:46:03 +08:00
|
|
|
|
dic_BezierCurveDatas.Add(curve.name, curve);
|
2026-08-04 14:52:22 +08:00
|
|
|
|
// ⭐ 同步构建点数组缓存(批量加载路径)
|
|
|
|
|
|
BuildCurvePointsArray(curve);
|
|
|
|
|
|
}
|
2026-02-03 11:35:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-07 03:46:03 +08:00
|
|
|
|
Addressables.Release(handles);
|
2026-03-31 18:30:49 +08:00
|
|
|
|
Debug.Log("曲线读取完成共" + dic_BezierCurveDatas.Count + "条");
|
2025-12-26 11:15:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-01 06:26:50 +08:00
|
|
|
|
public static async Task UnLoadBezierTxtAsync(string path)
|
|
|
|
|
|
{
|
|
|
|
|
|
List<string> keys = new List<string>();
|
|
|
|
|
|
keys.Add(path);
|
|
|
|
|
|
keys.Add(GameManager.Instance.gameData.currGameType.ToString());
|
|
|
|
|
|
|
2026-05-07 03:46:03 +08:00
|
|
|
|
AsyncOperationHandle<IList<TextAsset>> handles = Addressables.LoadAssetsAsync<TextAsset>(
|
|
|
|
|
|
keys, null, Addressables.MergeMode.Intersection);
|
2026-05-01 06:26:50 +08:00
|
|
|
|
await handles.Task;
|
|
|
|
|
|
|
2026-05-07 03:46:03 +08:00
|
|
|
|
// ⭐ 没有资源 → 直接跳出,不报错
|
|
|
|
|
|
if (handles.Result == null || handles.Result.Count == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning($"Bezier 曲线卸载跳过:未找到标签 {path} + {GameManager.Instance.gameData.currGameType}");
|
|
|
|
|
|
Addressables.Release(handles);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-01 06:26:50 +08:00
|
|
|
|
foreach (var text in handles.Result)
|
|
|
|
|
|
{
|
|
|
|
|
|
var lines = text.text.Split('\n');
|
|
|
|
|
|
foreach (var line in lines)
|
|
|
|
|
|
{
|
2026-05-07 03:46:03 +08:00
|
|
|
|
if (string.IsNullOrWhiteSpace(line))
|
|
|
|
|
|
continue;
|
2026-05-01 06:26:50 +08:00
|
|
|
|
|
|
|
|
|
|
var parts = line.Split(';');
|
2026-05-07 03:46:03 +08:00
|
|
|
|
if (parts.Length == 0)
|
|
|
|
|
|
continue;
|
2026-05-01 06:26:50 +08:00
|
|
|
|
|
2026-05-07 03:46:03 +08:00
|
|
|
|
string curveName = parts[0];
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(curveName))
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
// 字典存在才移除
|
2026-05-01 06:26:50 +08:00
|
|
|
|
if (dic_BezierCurveDatas.ContainsKey(curveName))
|
|
|
|
|
|
{
|
|
|
|
|
|
dic_BezierCurveDatas.Remove(curveName);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-04 14:52:22 +08:00
|
|
|
|
// ⭐ 同步清理点数组缓存
|
|
|
|
|
|
_curvePointsArrays.Remove(curveName);
|
|
|
|
|
|
|
2026-05-07 03:46:03 +08:00
|
|
|
|
// 列表移除所有同名曲线
|
2026-05-01 06:26:50 +08:00
|
|
|
|
curves.RemoveAll(c => c.name == curveName);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Addressables.Release(handles);
|
|
|
|
|
|
|
|
|
|
|
|
Debug.Log("曲线卸载完成,剩余曲线数量:" + dic_BezierCurveDatas.Count);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-26 11:15:56 +08:00
|
|
|
|
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;
|
|
|
|
|
|
|
2026-08-04 14:52:22 +08:00
|
|
|
|
// ⭐ 缓存相机和 UI 根 RectTransform,避免每帧每鱼调用
|
|
|
|
|
|
// UIManager.Instance.uiRoot.GetComponent<RectTransform>() 和 Camera.main
|
|
|
|
|
|
// 由 MonsterContral.OnEnable 同步赋值
|
|
|
|
|
|
public Camera cachedCamera;
|
|
|
|
|
|
public RectTransform cachedUirootRect;
|
|
|
|
|
|
|
2025-12-26 11:15:56 +08:00
|
|
|
|
public void Init(BezierCurveData bezierCurveData, float Time)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.bezierCurveData = bezierCurveData;
|
|
|
|
|
|
this.moveTime = Time;
|
2026-02-03 11:35:19 +08:00
|
|
|
|
Debug.Log($"初始化曲线 {this.bezierCurveData.name} ,移动时间 {moveTime}");
|
2025-12-26 11:15:56 +08:00
|
|
|
|
}
|
2026-03-31 18:30:49 +08:00
|
|
|
|
|
2026-02-03 11:35:19 +08:00
|
|
|
|
/// <summary>
|
2026-08-04 14:52:22 +08:00
|
|
|
|
/// 主线程零分配计算贝塞尔曲线点(De Casteljau 算法)。
|
|
|
|
|
|
/// ⭐ 优化说明(原 Job 方案的负优化问题):
|
|
|
|
|
|
/// 1. 原 GetBezierPointJob 每次调用 new List + 2 个 NativeArray(TempJob) + ToArray,
|
|
|
|
|
|
/// 每条鱼每帧产生 3 次堆分配,N 条鱼 = 3N 次 GC 分配/帧
|
|
|
|
|
|
/// 2. 原 Job.Schedule() 后立即 Complete(),Job 实际单线程执行,
|
|
|
|
|
|
/// 调度开销 > 计算收益(4-7 个控制点的计算量极小)
|
|
|
|
|
|
/// 3. 现方案:曲线点数组静态缓存(共享),主线程直接 Lerp 计算,零 GC 分配
|
|
|
|
|
|
/// 4. Camera/RectTransform 由调用方缓存,避免每帧每鱼重复获取
|
2026-02-03 11:35:19 +08:00
|
|
|
|
/// </summary>
|
2026-03-31 18:30:49 +08:00
|
|
|
|
public Vector2 GetBezierPointJob(float t)
|
2025-12-26 11:15:56 +08:00
|
|
|
|
{
|
2026-07-28 10:59:08 +08:00
|
|
|
|
// ⭐ 防止除零:moveTime<=0 时直接返回起点,避免 NaN
|
|
|
|
|
|
if (moveTime <= 0f)
|
|
|
|
|
|
return bezierCurveData.start;
|
|
|
|
|
|
|
2026-08-04 14:52:22 +08:00
|
|
|
|
if (t > moveTime)
|
|
|
|
|
|
t = moveTime;
|
2025-12-26 11:15:56 +08:00
|
|
|
|
t = t / moveTime;
|
|
|
|
|
|
|
2026-08-04 14:52:22 +08:00
|
|
|
|
// ⭐ 取静态缓存的曲线点数组(所有鱼共享,零分配)
|
|
|
|
|
|
if (!_curvePointsArrays.TryGetValue(bezierCurveData.name, out var pts))
|
2025-12-26 11:15:56 +08:00
|
|
|
|
{
|
2026-08-04 14:52:22 +08:00
|
|
|
|
// 兜底:缓存未命中时实时构建(理论上不应发生,加载时已构建)
|
|
|
|
|
|
BuildCurvePointsArray(bezierCurveData);
|
|
|
|
|
|
pts = _curvePointsArrays[bezierCurveData.name];
|
2025-12-26 11:15:56 +08:00
|
|
|
|
}
|
2026-08-04 14:52:22 +08:00
|
|
|
|
|
|
|
|
|
|
// ⭐ 复用线程静态缓冲区(主线程单线程执行,安全复用)
|
|
|
|
|
|
if (_tempPoints == null || _tempPoints.Length < pts.Length)
|
|
|
|
|
|
_tempPoints = new Vector2[pts.Length];
|
|
|
|
|
|
Array.Copy(pts, _tempPoints, pts.Length);
|
|
|
|
|
|
|
|
|
|
|
|
// De Casteljau 算法:逐层 Lerp 直到剩一个点
|
|
|
|
|
|
int count = pts.Length;
|
|
|
|
|
|
while (count > 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = 0; i < count - 1; i++)
|
|
|
|
|
|
_tempPoints[i] = Vector2.Lerp(_tempPoints[i], _tempPoints[i + 1], t);
|
|
|
|
|
|
count--;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Vector2 canvasPos = _tempPoints[0];
|
|
|
|
|
|
|
|
|
|
|
|
// ⭐ 用缓存的 Camera/RectTransform,避免每帧每鱼查询
|
|
|
|
|
|
var cam = cachedCamera != null ? cachedCamera : Camera.main;
|
|
|
|
|
|
var rect = cachedUirootRect != null
|
|
|
|
|
|
? cachedUirootRect
|
|
|
|
|
|
: UIManager.Instance.uiRoot.GetComponent<RectTransform>();
|
|
|
|
|
|
|
|
|
|
|
|
return CoordinateTransformation.CanvasToWorld(canvasPos, rect, cam);
|
2025-12-26 11:15:56 +08:00
|
|
|
|
}
|
2026-08-04 14:52:22 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>主线程复用的临时计算缓冲(避免每帧每鱼 new 数组)</summary>
|
|
|
|
|
|
[ThreadStatic]
|
|
|
|
|
|
private static Vector2[] _tempPoints;
|
2025-12-26 11:15:56 +08:00
|
|
|
|
}
|
2026-03-31 18:30:49 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region zijixie
|
|
|
|
|
|
|
|
|
|
|
|
//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<string, BezierCurveData> dic_BezierCurveDatas = new Dictionary<string, BezierCurveData>();
|
|
|
|
|
|
// public static List<BezierCurveData> curves = new List<BezierCurveData>();
|
|
|
|
|
|
// public class BezierCurveData
|
|
|
|
|
|
// {
|
|
|
|
|
|
// public string name;
|
|
|
|
|
|
// public Vector2 start;
|
|
|
|
|
|
// public List<Vector2> controlPoints = new List<Vector2>();
|
|
|
|
|
|
// public Vector2 end;
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// public static async void LoadBezier()
|
|
|
|
|
|
// {
|
|
|
|
|
|
// await LoadBezierTxtAsync("MoveLine");
|
|
|
|
|
|
// }
|
|
|
|
|
|
// /// <summary>
|
|
|
|
|
|
// /// 读取曲线数据 读取单个
|
|
|
|
|
|
// /// </summary>
|
|
|
|
|
|
// /// <param name="path"></param>
|
|
|
|
|
|
// /// <returns></returns>
|
|
|
|
|
|
// public static async Task LoadSingleBezierTxtAsync(string path)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// AsyncOperationHandle<TextAsset> handle = Addressables.LoadAssetAsync<TextAsset>(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<Vector2> points = new List<Vector2>();
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
// /// <summary>
|
|
|
|
|
|
// /// 读取曲线数据 游戏开始时在awake调用aa包
|
|
|
|
|
|
// /// </summary>
|
|
|
|
|
|
// /// <param name="path"></param>
|
|
|
|
|
|
// /// <returns></returns>
|
|
|
|
|
|
// public static async Task LoadBezierTxtAsync(string path)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// List<string> keys = new List<string>();
|
|
|
|
|
|
// keys.Add(path);
|
|
|
|
|
|
// keys.Add(GameManager.Instance.gameData.currGameType.ToString());
|
|
|
|
|
|
// AsyncOperationHandle<IList<TextAsset>> handles = Addressables.LoadAssetsAsync<TextAsset>(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<Vector2> points = new List<Vector2>();
|
|
|
|
|
|
// 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}");
|
|
|
|
|
|
// }
|
|
|
|
|
|
// /// <summary>
|
|
|
|
|
|
// /// 获取曲线上的点
|
|
|
|
|
|
// /// </summary>
|
|
|
|
|
|
// /// <param name="t"></param>
|
|
|
|
|
|
// /// <returns></returns>
|
|
|
|
|
|
// public Vector2 GetBezierPoint(float t)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// t = t / moveTime;
|
|
|
|
|
|
// BezierCurveData curve = bezierCurveData;
|
|
|
|
|
|
// List<Vector2> points = new List<Vector2>();
|
|
|
|
|
|
// points.Add(curve.start);
|
|
|
|
|
|
// points.AddRange(curve.controlPoints);
|
|
|
|
|
|
// points.Add(curve.end);
|
|
|
|
|
|
|
|
|
|
|
|
// return DeCasteljau_BY(points, t % 1);
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// /// <summary>
|
|
|
|
|
|
// /// 贝塞尔
|
|
|
|
|
|
// /// </summary>
|
|
|
|
|
|
// /// <param name="points"></param>
|
|
|
|
|
|
// /// <param name="t"></param>
|
|
|
|
|
|
// /// <returns></returns>
|
|
|
|
|
|
// private Vector2 DeCasteljau_BSE(List<Vector2> points, float t)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// while (points.Count > 1)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// List<Vector2> next = new List<Vector2>();
|
|
|
|
|
|
// 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<RectTransform>(), Camera.main);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// /// <summary>
|
|
|
|
|
|
// /// B样
|
|
|
|
|
|
// /// </summary>
|
|
|
|
|
|
// /// <param name="points"></param>
|
|
|
|
|
|
// /// <param name="t"></param>
|
|
|
|
|
|
// /// <returns></returns>
|
|
|
|
|
|
// private Vector2 DeCasteljau_BY(List<Vector2> points, float t)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// // 方法A:保持德卡斯特里奥算法(推荐,数值更稳定)
|
|
|
|
|
|
// while (points.Count > 1)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// List<Vector2> next = new List<Vector2>();
|
|
|
|
|
|
// 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<RectTransform>(), 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<RectTransform>(), 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;
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//}
|
|
|
|
|
|
#endregion
|