切割功能

This commit is contained in:
2025-05-02 16:06:06 +08:00
parent 4f7dece3ca
commit 10179d5453
9 changed files with 178 additions and 135 deletions
@@ -2,7 +2,9 @@ using System;
using System.Collections.Generic;
using System.Linq;
using AibisDream.Framework;
using AibisDream.Kit;
using AibisDream.Utility;
using DG.Tweening;
using Newtonsoft.Json;
using UnityEngine;
@@ -129,13 +131,20 @@ namespace AibisDream.FixSystem
{
_cutLine.OnCuttingDown -= OnCuttingDown;
_cutting = false;
// TODO 播放切割动画
// 模块脱落
_cutLine.HideLine();
_bodyModuleSystem.RemoveModule(this);
ActionKit.Sequence()
.Delay(0.5f)
.DOTween(() => transform.DOMoveY(ConstRef.TweenEndY,
(transform.position.y - ConstRef.TweenEndY) / ConstRef.FallSpeed).SetEase(Ease.InQuad))
.Start(this, () => Destroy(gameObject));
}
private void ShowCutLine()
{
// 切割线不存在,就新建一个
if (_cutLine == null)
if (!_cutLine)
{
var prefab = ResourceKit.LoadAssetSync<GameObject>(ConstRef.CutLinePrefabName);
var cutLineObj = Instantiate(prefab, transform);
@@ -1,5 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using AibisDream.Framework;
using Cinemachine;
@@ -11,7 +12,7 @@ namespace AibisDream.FixSystem
{
#region
public BodyModule[] BodyModules { get; private set; }
public List<BodyModule> BodyModules { get; private set; }
private GameObject _bodyModuleGroup;
private GameObject _headModuleGroup;
@@ -200,10 +201,19 @@ namespace AibisDream.FixSystem
}
// 重新获取ModuleGroup
var root = moduleState == ModuleState.Body ? _bodyModuleGroup : _headModuleGroup;
BodyModules = root?.GetComponentsInChildren<BodyModule>();
BodyModules = root?.GetComponentsInChildren<BodyModule>().ToList();
// 更改data
_data.moduleState = moduleState;
}
/// <summary>
/// 从模块中清除
/// </summary>
/// <param name="module">将要被移除的模块</param>
public void RemoveModule(BodyModule module)
{
BodyModules.Remove(module);
}
}
[LoadIndex(2)]
@@ -12,7 +12,7 @@ namespace AibisDream
private static readonly int RangeCount = Shader.PropertyToID("_RangeCount");
#endregion
private LineRenderer _lineRenderer;
private Material _lineMaterial;
@@ -36,6 +36,8 @@ namespace AibisDream
_lineMaterial = _lineRenderer.materials[0];
}
_lineRenderer.gameObject.SetActive(true);
// 清除旧数据
ClearOldData();
// 生成归一化点
@@ -64,7 +66,7 @@ namespace AibisDream
// 设置Shader
_lineMaterial.SetFloat(TotalLength, _totalLength);
_lineMaterial.SetInt(RangeCount, 1);
_lineMaterial.SetVectorArray(Ranges, new List<Vector4> {Vector4.zero} );
_lineMaterial.SetVectorArray(Ranges, new List<Vector4> { Vector4.zero });
}
private void UpdateMaterial()
@@ -73,7 +75,7 @@ namespace AibisDream
{
return;
}
// 将Range组装成Shader可以读取的格式
var ranges = new List<Vector4>();
@@ -97,7 +99,7 @@ namespace AibisDream
_linePoints = shapePoints
.Select(item => new Vector2(item.x, item.y))
.ToArray();
var segmentLengths = new List<float>();
// 计算总长度和各段长度
@@ -159,7 +161,7 @@ namespace AibisDream
// 如果未覆盖直接计算下一段
continue;
}
// 将线段范围转成整体范围
var normalizedStart = _normalizedLinePoints[i - 1];
var normalizedEnd = _normalizedLinePoints[i];
@@ -177,7 +179,7 @@ namespace AibisDream
// 合并所有重叠区间
MergeRanges();
// 判断当前切割有没有割到95%
if (CalcTotalRange() >= 0.95)
{
@@ -193,8 +195,9 @@ namespace AibisDream
{
log += $"{range.x:F2}-{range.y:F2}; ";
}
Debug.Log(log);
UpdateMaterial();
}
@@ -204,7 +207,7 @@ namespace AibisDream
// 计算线段方向向量和长度
Vector2 lineDir = lineEnd - lineStart;
float lineLength = lineDir.magnitude;
// 如果线段长度为零(两个端点重合)
if (Mathf.Approximately(lineLength, 0f))
{
@@ -213,7 +216,7 @@ namespace AibisDream
rawRange = distance <= radius ? new Vector2(0f, 1f) : default;
return distance <= radius;
}
// 计算点到线段所在直线距离
Vector2 lineDirNormalized = lineDir / lineLength; // 归一化方向向量
Vector2 pointToStart = point - lineStart; // 计算点到线段起点的向量
@@ -221,23 +224,24 @@ namespace AibisDream
float closestT = Mathf.Clamp01(projection / lineLength); // 计算实际最近点在线段上的比例位置
Vector2 closestPoint = lineStart + closestT * lineDir; // 计算最近点坐标
float distanceToLine = Vector2.Distance(point, closestPoint); // 计算点到最近点的距离
// 如果距离大于半径,完全没有覆盖
if (distanceToLine > radius)
{
rawRange = default;
return false;
}
// 计算覆盖范围
float halfCoveredLength = Mathf.Sqrt(radius * radius - distanceToLine * distanceToLine); // 计算实际覆盖的线段长度(勾股定理)
float halfCoveredLength =
Mathf.Sqrt(radius * radius - distanceToLine * distanceToLine); // 计算实际覆盖的线段长度(勾股定理)
float startCoverage = (projection - halfCoveredLength) / lineLength;
float endCoverage = (projection + halfCoveredLength) / lineLength; // 计算覆盖的起点和终点比例
startCoverage = Mathf.Clamp01(startCoverage);
endCoverage = Mathf.Clamp01(endCoverage); // 限制在0-1范围内
// 如果起点和终点相同,表示只覆盖了一个点
if (Mathf.Approximately(startCoverage, endCoverage))
{
@@ -287,7 +291,12 @@ namespace AibisDream
#endregion
// 获取当前所有记录的范围(0-1之间的值)
public void HideLine()
{
gameObject.SetActive(false);
}
// 获取当前所有记录的范围(0-1之间的值)
public List<Vector2> GetRecordedRanges()
{
return new List<Vector2>(_recordedRanges);