Files
5.24BuYu/Assets/MyGame/Scripts/Characters/Monster/MonsterMoveLine.cs
T

498 lines
15 KiB
C#
Raw Normal View History

2026-03-31 18:30:49 +08:00
#region AI优化
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-03-31 18:30:49 +08:00
using Unity.Collections;
using Unity.Jobs;
using Unity.Burst;
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-03-31 18:30:49 +08:00
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-03-31 18:30:49 +08:00
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))
dic_BezierCurveDatas.Add(curve.name, 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-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;
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-03-31 18:30:49 +08:00
/// 使用 Job 计算 B样条点
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-04-24 22:51:34 +08:00
if (t>moveTime)
{
t=moveTime;
}
2025-12-26 11:15:56 +08:00
t = t / moveTime;
2026-03-31 18:30:49 +08:00
List<Vector2> pts = new List<Vector2>();
pts.Add(bezierCurveData.start);
pts.AddRange(bezierCurveData.controlPoints);
pts.Add(bezierCurveData.end);
2025-12-26 11:15:56 +08:00
2026-03-31 18:30:49 +08:00
var controlPoints = new NativeArray<Vector2>(pts.ToArray(), Allocator.TempJob);
var result = new NativeArray<Vector2>(1, Allocator.TempJob);
var job = new BSplineJob
2025-12-26 11:15:56 +08:00
{
2026-03-31 18:30:49 +08:00
controlPoints = controlPoints,
2026-04-24 22:51:34 +08:00
t = t,
2026-03-31 18:30:49 +08:00
result = result
};
JobHandle handle = job.Schedule();
handle.Complete();
Vector2 worldPos = CoordinateTransformation.CanvasToWorld(result[0],
UIManager.Instance.uiRoot.GetComponent<RectTransform>(), Camera.main);
controlPoints.Dispose();
result.Dispose();
return worldPos;
}
// Job 结构体
[BurstCompile]
public struct BSplineJob : IJob
{
[ReadOnly] public NativeArray<Vector2> controlPoints;
public float t;
public NativeArray<Vector2> result;
public void Execute()
{
var temp = new NativeArray<Vector2>(controlPoints.Length, Allocator.Temp);
controlPoints.CopyTo(temp);
int count = temp.Length;
while (count > 1)
2025-12-26 11:15:56 +08:00
{
2026-03-31 18:30:49 +08:00
for (int i = 0; i < count - 1; i++)
{
temp[i] = Vector2.Lerp(temp[i], temp[i + 1], t);
}
count--;
2025-12-26 11:15:56 +08:00
}
2026-03-31 18:30:49 +08:00
result[0] = temp[0];
temp.Dispose();
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