fix:1、修改bug

This commit is contained in:
2026-06-18 09:27:38 +08:00
parent acf888d9be
commit cd258603ac
19 changed files with 28741 additions and 129 deletions
+137 -101
View File
@@ -19,12 +19,6 @@ namespace ChillConnect
// FGUI界面根容器
private GComponent _viewContainer;
#region FGUI
private ArrorPoint _dotTemplate;
private ArrowEnd _arrowTemplate;
private LineTile _lineUnitTemplate;
#endregion
// 关卡总配置数据
private LevelConfig _levelConfig;
@@ -70,7 +64,7 @@ namespace ChillConnect
// 当前正在提示的箭头
private ArrowConfig _currentTipArrow;
// 手指图标偏移(微调位置)
private readonly Vector2 _fingerOffset = new Vector2(-60, -60);
private readonly Vector2 _fingerOffset = new Vector2(-20, -20);
// 所有网格圆点实例列表,用于批量改色/清理
private List<ArrorPoint> _gridDotList = new List<ArrorPoint>();
@@ -154,14 +148,6 @@ namespace ChillConnect
HideFingerTip();
// 释放模板资源
if (_dotTemplate != null) _dotTemplate.Dispose();
if (_arrowTemplate != null) _arrowTemplate.Dispose();
if (_lineUnitTemplate != null) _lineUnitTemplate.Dispose();
_dotTemplate = null;
_arrowTemplate = null;
_lineUnitTemplate = null;
_levelConfig = null;
// 清空网格占用数据
@@ -185,47 +171,39 @@ namespace ChillConnect
public override void OnUpdate()
{
// if (_levelConfig == null) return;
// foreach (var arrow in _levelConfig.arrows)
// {
// UpdateArrowMove(arrow);
// }
//
// ========= 编辑器模拟触摸(仅编辑模式生效) =========
// ========== 编辑器鼠标拖拽 ==========
// 初始化未完成,直接跳过拖拽
if (!_initComplete)
return;
#if UNITY_EDITOR
float moveThreshold = 1f; // 移动阈值,大于这个值才算有效拖动
float moveThreshold = 1f;
// 鼠标按下:仅初始化状态和起点
// 鼠标按下:仅在拖拽区域内按下才开启拖拽
if (InputHelper.Instance.GetMouseButtonDown(0))
{
Vector2 unityPos = InputHelper.Instance.MousePosition;
_lastTouchPos = UnityMouseToFGUIPos(unityPos);
_isDraging = true;
Debug.Log("鼠标按下,开始拖拽");
return; // 本帧直接返回,不执行拖动逻辑
Vector2 fguiPos = UnityMouseToFGUIPos(unityPos);
if (IsInDragArea(fguiPos))
{
_lastTouchPos = fguiPos;
_isDraging = true;
Debug.Log("鼠标按下,在拖拽区域内,开始拖拽");
}
return;
}
// 拖拽中:按住左键 + 拖拽标记为true
// 拖拽中:原有逻辑不变
if (_isDraging && InputHelper.Instance.GetMouseButton(0))
{
Vector2 unityPos = InputHelper.Instance.MousePosition;
Vector2 curMousePos = UnityMouseToFGUIPos(unityPos);
Vector2 offset = curMousePos - _lastTouchPos;
Debug.Log($"curMousePos=={curMousePos} _lastTouchPos=={_lastTouchPos} offset=={offset}");
// 只有偏移超过阈值才移动 & 更新基准点
if (offset.magnitude > moveThreshold)
{
MoveContainer(offset);
_lastTouchPos = curMousePos; // 移动后再刷新起点
_lastTouchPos = curMousePos;
}
}
@@ -277,9 +255,13 @@ namespace ChillConnect
if (touch.phase == TouchPhase.Began)
{
_lastTouchPos = curTouchPos;
_isDraging = true;
_isTwoFingerTouch = false;
// 只有在拖拽区域内按下,才开启拖拽
if (IsInDragArea(curTouchPos))
{
_lastTouchPos = curTouchPos;
_isDraging = true;
_isTwoFingerTouch = false;
}
}
else if (touch.phase == TouchPhase.Moved && _isDraging)
{
@@ -304,11 +286,7 @@ namespace ChillConnect
{
//加载配置
InitAllLevelData();
_viewContainer = ui.view_container;
// 初始化FGUI模板
_dotTemplate = (ArrorPoint)UIPackage.CreateObject("Arrow_game", "ArrorPoint");
_arrowTemplate = (ArrowEnd)UIPackage.CreateObject("Arrow_game", "ArrowEnd");
_lineUnitTemplate = (LineTile)UIPackage.CreateObject("Arrow_game", "LineTile");
_viewContainer = ui.view_container_parent.panel;
LoadLevelConfig();
InitGridBounds();
@@ -345,7 +323,7 @@ namespace ChillConnect
GameDispatcher.Instance.AddListener(GameMsg.Update101, SetTopCurr);
GameDispatcher.Instance.AddListener(GameMsg.ThemeChange, SetModel);
GameDispatcher.Instance.AddListener(GameMsg.UpdateSpeed, SetSpeed);
GameDispatcher.Instance.AddListener(GameMsg.SetDelete, SetDeleteMode);
GameDispatcher.Instance.AddListener(GameMsg.UseProps, SetUserPorp);
}
@@ -356,7 +334,7 @@ namespace ChillConnect
GameDispatcher.Instance.RemoveListener(GameMsg.Update101, SetTopCurr);
GameDispatcher.Instance.RemoveListener(GameMsg.ThemeChange, SetModel);
GameDispatcher.Instance.RemoveListener(GameMsg.UpdateSpeed, SetSpeed);
GameDispatcher.Instance.RemoveListener(GameMsg.SetDelete, SetDeleteMode);
GameDispatcher.Instance.RemoveListener(GameMsg.UseProps, SetUserPorp);
@@ -384,9 +362,7 @@ namespace ChillConnect
}
_fingerTipObj = com_finger.CreateInstance();
_viewContainer.AddChild(_fingerTipObj);
_fingerTipObj.visible = false;
_currentTipArrow = null;
_zoomSlider = ui.com_bottom.zoomSlide;
@@ -412,8 +388,8 @@ namespace ChillConnect
// ========== 核心:把网格中心钉在屏幕中心 ==========
// _gridWorldCenter 是 DrawGridDots 里 CalculateGridCenter 算出的值
float screenCenterX = Screen.width * 0.5f;
float screenCenterY = Screen.height * 0.5f;
float screenCenterX = ui.view_container_parent.width * 0.5f;
float screenCenterY = ui.view_container_parent.height * 0.5f;
// 计算容器需要移动多少,才能让网格中心正好对准屏幕中心
float targetContainerX = screenCenterX - _gridWorldCenter.x;
@@ -435,6 +411,11 @@ namespace ChillConnect
SetModel();
SetTopCurr();
_fingerTipObj = com_finger.CreateInstance();
_viewContainer.AddChild(_fingerTipObj);
_fingerTipObj.visible = false;
_fingerTipObj.sortingOrder = 9999;
}
@@ -815,9 +796,6 @@ namespace ChillConnect
#region
private void DrawGridDots(LevelConfig cfg)
{
if (_dotTemplate == null || _viewContainer == null) return;
_dotTemplate.visible = false;
var rows = cfg.gridRows;
var cols = cfg.gridCols;
@@ -1023,16 +1001,31 @@ namespace ChillConnect
#region
private void SetDeleteMode(object a)
private void SetUserPorp(object a)
{
_isDeleteMode = !_isDeleteMode;
if (a != null)
{
var type = (int)a;
Debug.Log($"Set User Prop: {type}");
if (type == 0)
{
// 提示道具
ShowRandomArrowTip();
}
else if (type == 1)
{
_isDeleteMode = !_isDeleteMode;
}
}
}
/// <summary>点击删除道具,开启/关闭删除模式</summary>
private void OnClickDeleteItem()
{
// _isDeleteMode = !_isDeleteMode;
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.ArrowTipsUI_Open);
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.ArrowTipsUI_Open, 1);
// // 可选:加提示,区分状态
// if (_isDeleteMode)
@@ -1048,7 +1041,7 @@ namespace ChillConnect
private void OnClickHint()
{
ShowRandomArrowTip();
UICtrlDispatcher.Instance.Dispatch(UICtrlMsg.ArrowTipsUI_Open, 0);
}
/// <summary>随机选中有效箭头,显示静态手指提示(不跟随移动)</summary>
@@ -1063,22 +1056,26 @@ namespace ChillConnect
return;
}
// 筛选有效箭头
// 筛选条件:对象存在 + 未销毁 + 未在移动中 + 前方无阻挡可直接消除
List<ArrowConfig> validArrows = _levelConfig.arrows
.Where(arrow => arrow != null && arrow.arrowObj != null)
.Where(arrow =>
arrow != null &&
arrow.arrowObj != null &&
!arrow.isMoving &&
!IsArrowBlocked(arrow))
.ToList();
if (validArrows.Count == 0)
{
Debug.Log("没有有效箭头可提示");
Debug.Log("当前没有可直接消除的箭头,无法提示");
return;
}
// 随机选一个
// 从可消除箭头中随机选一个
int randomIndex = Random.Range(0, validArrows.Count);
_currentTipArrow = validArrows[randomIndex];
// 设置手指位置(仅初始化一次,不再刷新)
// 设置手指提示位置
float x = _currentTipArrow.arrowObj.x + _fingerOffset.x;
float y = _currentTipArrow.arrowObj.y + _fingerOffset.y;
_fingerTipObj.SetPosition(x, y, 0);
@@ -1099,6 +1096,24 @@ namespace ChillConnect
#region
/// <summary>
/// 判断FGUI全局坐标是否落在拖拽有效区域(view_container_parent)内
/// </summary>
private bool IsInDragArea(Vector2 fguiGlobalPos)
{
if (ui.view_container_parent == null)
return false;
// 全局坐标转成父容器本地坐标(左上角为原点)
Vector2 localPos = ui.view_container_parent.GlobalToLocal(fguiGlobalPos);
// 判断是否在容器矩形范围内
return localPos.x >= 0
&& localPos.x <= ui.view_container_parent.width
&& localPos.y >= 0
&& localPos.y <= ui.view_container_parent.height;
}
/// <summary>根据缩放值,计算滑动条 value(0~1)</summary>
private float GetSliderValueByScale(float scale)
{
@@ -1192,21 +1207,26 @@ namespace ChillConnect
MoveToDisappear(clickArrow);
}
}
// 基于网格行列的阻挡检测
private bool CheckBlockByGrid(ArrowConfig curArrow)
/// <summary>
/// 纯检测:箭头前方是否有阻挡(无副作用,不扣血、不改状态)
/// </summary>
/// <returns>true=前方有阻挡,false=可直接飞出消除</returns>
private bool IsArrowBlocked(ArrowConfig curArrow)
{
if (_gridOccupied == null || _levelConfig == null) return false;
if (_gridOccupied == null || _levelConfig == null)
return false;
// 当前箭头网格行列
// 获取箭头头部所在网格行列
Vector2 arrowPos = new Vector2(curArrow.arrowObj.x, curArrow.arrowObj.y);
int curPointId = GetPointIdByPos(arrowPos, _levelConfig);
PointIdToRowCol(curPointId, _levelConfig.gridCols, out int curRow, out int curCol);
// 超出网格直接判定无阻挡
// 箭头已超出网格判定无阻挡
if (curRow < 0 || curRow >= _levelConfig.gridRows || curCol < 0 || curCol >= _levelConfig.gridCols)
return false;
// 获取移动方向
// 获取最终射出方向
string moveDir;
if (curArrow.path != null && curArrow.path.Count > 0)
{
@@ -1221,63 +1241,58 @@ namespace ChillConnect
moveDir = "up";
}
bool isCollide = false;
// 沿方向遍历前方网格
// 沿射出方向遍历前方网格
switch (moveDir)
{
case "up":
for (int r = curRow - 1; r >= 0; r--)
{
if (_gridOccupied[r, curCol])
{
isCollide = true;
break;
}
return true;
}
break;
case "down":
for (int r = curRow + 1; r < _levelConfig.gridRows; r++)
{
if (_gridOccupied[r, curCol])
{
isCollide = true;
break;
}
return true;
}
break;
case "left":
for (int c = curCol - 1; c >= 0; c--)
{
if (_gridOccupied[curRow, c])
{
isCollide = true;
break;
}
return true;
}
break;
case "right":
for (int c = curCol + 1; c < _levelConfig.gridCols; c++)
{
if (_gridOccupied[curRow, c])
{
isCollide = true;
break;
}
return true;
}
break;
}
// ========== 新增:碰撞判重 + 扣爱心 ==========
return false;
}
// 基于网格行列的阻挡检测(带扣血逻辑,点击箭头时调用)
private bool CheckBlockByGrid(ArrowConfig curArrow)
{
bool isCollide = IsArrowBlocked(curArrow);
// ========== 碰撞判重 + 扣爱心 ==========
if (isCollide)
{
// 这条线第一次碰撞才扣血
// 同个箭头第一次碰撞才扣血
if (!_collidedArrows.Contains(curArrow))
{
_collidedArrows.Add(curArrow);
_heartCount--;
if (_heartCount > 0) ui.HeartsPanel.GetChild($"xin_{_heartCount+1}").visible = false;
if (_heartCount > 0)
ui.HeartsPanel.GetChild($"xin_{_heartCount + 1}").visible = false;
// 爱心归零 → 失败结算
if (_heartCount <= 0)
{
@@ -1389,48 +1404,70 @@ namespace ChillConnect
RunCoroutine(MoveAndResetCoroutine(arrow));
}
// 回弹速度单独配置,和移动速度分开
private float _bounceSpeed = 180f;
private IEnumerator MoveAndResetCoroutine(ArrowConfig arrow)
{
arrow.movedDistance = 0f;
arrow.finalMoveDir = GetFinalMoveDir(arrow);
// 向前移动的总距离(对应原逻辑2步=20px,可自行调整
// 向前移动的总距离(对应原逻辑2步=20px)
float forwardTotal = 20f;
float timer = 0f;
float duration = forwardTotal / _bounceSpeed;
float timer = 0f;
// 第一段:向前移动
// ========== 第一段:向前移动 ==========
while (timer < duration)
{
if (arrow == null || arrow.arrowObj == null) yield break;
timer += Time.deltaTime;
arrow.movedDistance = _bounceSpeed * timer;
// 钳制:保证前移距离不超过设定值,不会多走
arrow.movedDistance = Mathf.Min(_bounceSpeed * timer, forwardTotal);
UpdateAllElementsPosition(arrow);
yield return null;
}
// 第二段:回弹到初始位置
// 强制对齐前顶点,消除浮点误差
arrow.movedDistance = forwardTotal;
UpdateAllElementsPosition(arrow);
// ========== 第二段:回弹复位 ==========
timer = 0f;
float startDis = arrow.movedDistance;
while (timer < duration)
{
if (arrow == null || arrow.arrowObj == null) yield break;
timer += Time.deltaTime;
float t = timer / duration;
// 核心修复:钳制 t 在 0~1 之间,防止插值超出范围变成负数
float t = Mathf.Clamp01(timer / duration);
arrow.movedDistance = Mathf.Lerp(startDis, 0f, t);
UpdateAllElementsPosition(arrow);
yield return null;
}
// 强制复位到初始状态
// ========== 最终强制复位(双保险,绝对回到初始位置)==========
arrow.movedDistance = 0f;
UpdateAllElementsPosition(arrow);
// 兜底:直接用原始坐标校准,彻底消除距离计算的累计误差
if (arrow.arrowObj != null)
{
arrow.arrowObj.SetPosition(arrow.originalArrowPos.x, arrow.originalArrowPos.y, 0);
}
for (int i = 0; i < arrow.lineUnits.Count; i++)
{
if (arrow.lineUnits[i] != null && i < arrow.originalLinePos.Count)
{
arrow.lineUnits[i].SetPosition(
arrow.originalLinePos[i].x,
arrow.originalLinePos[i].y, 0);
}
}
arrow.isMoving = false;
}
@@ -1465,7 +1502,6 @@ namespace ChillConnect
// 新增:统一移动速度(像素/秒),数值越大移动越快,可自由修改
[SerializeField] private float _moveSpeed = 1500f;
private IEnumerator MoveAndDisappearCoroutine(ArrowConfig arrow)
{
arrow.movedDistance = 0f;