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

157 lines
4.8 KiB
C#
Raw Normal View History

2025-12-26 11:15:56 +08:00
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;
}
/// <summary>
/// 读取数据 游戏开始时在awake调用aa包
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static async Task LoadBezierTxtAsync(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];
// 最后一个点是 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);
}
}
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;
}
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(points, t%1);
}
private Vector2 DeCasteljau(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 CanvasToWorld( points[0],UIManager.Instance.uiRoot.GetComponent<RectTransform>(),Camera.main);
}
public static Vector3 CanvasToWorld(Vector2 canvasPos, RectTransform canvas, Camera cam)
{
// 1. 获取 Canvas 实际像素尺寸(自动适配所有设备)
float canvasWidth = canvas.rect.width;
float canvasHeight = canvas.rect.height;
// 2. 正交相机的世界高度
float worldHeight = cam.orthographicSize * 2f;
// 3. 世界宽度 = 世界高度 * 屏幕宽高比
float worldWidth = worldHeight * cam.aspect;
// 4. 画布单位 → 世界单位比例(横竖一致)
float scaleX = worldWidth / canvasWidth;
float scaleY = worldHeight / canvasHeight;
// 5. 你的 canvasPos 是以中心为原点的坐标
float worldX = canvasPos.x * scaleX;
float worldY = canvasPos.y * scaleY;
// 6. 映射到世界 z = 0 平面
return new Vector3(worldX, worldY, 0f);
}
public static Vector2 AnchoredPos_ToCanvas(RectTransform target, Canvas canvas)
{
// 1. 先把 anchoredPosition(父坐标)转换成世界坐标
Vector3 worldPos = target.TransformPoint(target.anchoredPosition);
// 2. 再把世界坐标转换成 Canvas 的局部坐标(等价于 Canvas 下的 anchoredPosition)
RectTransform canvasRT = canvas.GetComponent<RectTransform>();
Vector2 canvasLocalPos;
RectTransformUtility.ScreenPointToLocalPointInRectangle(
canvasRT,
RectTransformUtility.WorldToScreenPoint(canvas.worldCamera, worldPos),
canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : canvas.worldCamera,
out canvasLocalPos
);
return canvasLocalPos;
}
}