diff --git a/ArrowBeatTap-Gp.sln.DotSettings.user b/ArrowBeatTap-Gp.sln.DotSettings.user index 6e39860..526b660 100644 --- a/ArrowBeatTap-Gp.sln.DotSettings.user +++ b/ArrowBeatTap-Gp.sln.DotSettings.user @@ -8,4 +8,5 @@ ForceIncluded ForceIncluded ForceIncluded - ForceIncluded \ No newline at end of file + ForceIncluded + ForceIncluded \ No newline at end of file diff --git a/Assets/ChillConnect/FGUI/package/Arrow_game/Arrow_gameBinder.cs b/Assets/ChillConnect/FGUI/package/Arrow_game/Arrow_gameBinder.cs index 511cc1d..8d5a146 100644 --- a/Assets/ChillConnect/FGUI/package/Arrow_game/Arrow_gameBinder.cs +++ b/Assets/ChillConnect/FGUI/package/Arrow_game/Arrow_gameBinder.cs @@ -13,6 +13,7 @@ namespace FGUI.Arrow_game UIObjectFactory.SetPackageItemExtension(LineTile.URL, typeof(LineTile)); UIObjectFactory.SetPackageItemExtension(ArrorPoint.URL, typeof(ArrorPoint)); UIObjectFactory.SetPackageItemExtension(HeartsPanel.URL, typeof(HeartsPanel)); + UIObjectFactory.SetPackageItemExtension(com_finger.URL, typeof(com_finger)); } } } \ No newline at end of file diff --git a/Assets/ChillConnect/FGUI/package/Arrow_game/com_arrow_game.cs b/Assets/ChillConnect/FGUI/package/Arrow_game/com_arrow_game.cs index 52af3dd..d9fee3c 100644 --- a/Assets/ChillConnect/FGUI/package/Arrow_game/com_arrow_game.cs +++ b/Assets/ChillConnect/FGUI/package/Arrow_game/com_arrow_game.cs @@ -14,6 +14,9 @@ namespace FGUI.Arrow_game public ArrorPoint point; public GButton btn_close; public HeartsPanel HeartsPanel; + public GButton btn_clear; + public GButton btn_hint; + public com_finger com_finger; public const string URL = "ui://sjl9teijrsd40"; public static com_arrow_game CreateInstance() @@ -32,6 +35,9 @@ namespace FGUI.Arrow_game point = (ArrorPoint)GetChildAt(4); btn_close = (GButton)GetChildAt(6); HeartsPanel = (HeartsPanel)GetChildAt(7); + btn_clear = (GButton)GetChildAt(9); + btn_hint = (GButton)GetChildAt(10); + com_finger = (com_finger)GetChildAt(11); } } } \ No newline at end of file diff --git a/Assets/ChillConnect/FGUI/package/Arrow_game/com_finger.cs b/Assets/ChillConnect/FGUI/package/Arrow_game/com_finger.cs new file mode 100644 index 0000000..6140f12 --- /dev/null +++ b/Assets/ChillConnect/FGUI/package/Arrow_game/com_finger.cs @@ -0,0 +1,27 @@ +/** This is an automatically generated class by FairyGUI. Please do not modify it. **/ + +using FairyGUI; +using FairyGUI.Utils; + +namespace FGUI.Arrow_game +{ + public partial class com_finger : GComponent + { + public GImage finger; + public Transition t0; + public const string URL = "ui://sjl9teijrsd4f"; + + public static com_finger CreateInstance() + { + return (com_finger)UIPackage.CreateObject("Arrow_game", "com_finger"); + } + + public override void ConstructFromXML(XML xml) + { + base.ConstructFromXML(xml); + + finger = (GImage)GetChildAt(0); + t0 = GetTransitionAt(0); + } + } +} \ No newline at end of file diff --git a/Assets/ChillConnect/FGUI/package/Arrow_game/com_finger.cs.meta b/Assets/ChillConnect/FGUI/package/Arrow_game/com_finger.cs.meta new file mode 100644 index 0000000..1677c84 --- /dev/null +++ b/Assets/ChillConnect/FGUI/package/Arrow_game/com_finger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d110f1d5f9c887b4d9194e2f3ca1c58c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/ChillConnectAssets/FGUI/Arrow_game_atlas0.png b/Assets/Resources/ChillConnectAssets/FGUI/Arrow_game_atlas0.png index 9e86b35..d17798f 100644 Binary files a/Assets/Resources/ChillConnectAssets/FGUI/Arrow_game_atlas0.png and b/Assets/Resources/ChillConnectAssets/FGUI/Arrow_game_atlas0.png differ diff --git a/Assets/Resources/ChillConnectAssets/FGUI/Arrow_game_fui.bytes b/Assets/Resources/ChillConnectAssets/FGUI/Arrow_game_fui.bytes index 15908b1..1d028d0 100644 Binary files a/Assets/Resources/ChillConnectAssets/FGUI/Arrow_game_fui.bytes and b/Assets/Resources/ChillConnectAssets/FGUI/Arrow_game_fui.bytes differ diff --git a/Assets/Scripts/ModuleUI/ArrowGame/ArrowGameUI.cs b/Assets/Scripts/ModuleUI/ArrowGame/ArrowGameUI.cs index 7ce3121..b611cf3 100644 --- a/Assets/Scripts/ModuleUI/ArrowGame/ArrowGameUI.cs +++ b/Assets/Scripts/ModuleUI/ArrowGame/ArrowGameUI.cs @@ -54,8 +54,11 @@ namespace ChillConnect // 统计场上还存在的箭头总数(用于判断全部移除=通关) private int _remainArrowCount = 0; - // 结算界面UI引用(根据你FGUI包名/组件名自行修改) - // private ResultPanel _resultPanel; + // 记录当前UI所有由 CrazyAsyKit 启动的协程,用于统一停止 + private List _activeCoroutines = new List(); + + // 是否开启删除道具模式 + private bool _isDeleteMode = false; public ArrowGameUI(ArrowGameUICtrl ctrl) : base(ctrl) { @@ -80,6 +83,26 @@ namespace ChillConnect protected override void OnClose() { + // ========= 第一步:统一停止所有协程(核心修复) ========= + foreach (var co in _activeCoroutines) + { + if (co != null) + { + CrazyAsyKit.StopCoroutine(co); + } + } + // 清空列表 + _activeCoroutines.Clear(); + + // 保险========= 强制停止所有移动,终止对应协程 ========= + if (_levelConfig != null) + { + foreach (var arrow in _levelConfig.arrows) + { + arrow.isMoving = false; + } + } + // 销毁所有动态FGUI对象 ClearAllDynamicObj(); @@ -152,6 +175,8 @@ namespace ChillConnect { // 关闭按钮 ui.btn_close.SetClick(() => { CtrlCloseUI(); }); + ui.btn_clear.SetClick(OnClickDeleteItem); + if (_levelConfig == null) return; @@ -410,6 +435,8 @@ namespace ChillConnect arrow.finalMoveDir = GetDirByRotation(arrow.arrowObj.rotation); // ========= 修复2:强制记录原始坐标(关键!)========= arrow.originalArrowPos = new Vector2(arrow.arrowObj.x, arrow.arrowObj.y); + // 优化:给单点箭头填充一个轨迹点,和有线箭头逻辑完全一致 + arrow.totalTrack.Add(pathPoints[0]); return; } @@ -467,10 +494,21 @@ namespace ChillConnect private void OnPathClick(ArrowConfig clickArrow) { if (clickArrow.isMoving) + { + Debug.Log($"[arrow] {clickArrow.id}正在移动,请勿点击其他箭头"); return; + } + + // ========= 删除模式:直接删除箭头,不走移动逻辑 ========= + if (_isDeleteMode) + { + DeleteArrowCompletely(clickArrow); + return; + } clickArrow.isMoving = true; bool hasBlock = CheckBlockByGrid(clickArrow); + Debug.Log("[arrow] 点击箭头:" + clickArrow.id +$"hasBlock==={hasBlock}"); if (hasBlock) { MoveThenReset(clickArrow); @@ -480,6 +518,23 @@ namespace ChillConnect MoveToDisappear(clickArrow); } } + + /// 点击删除道具,开启/关闭删除模式 + public void OnClickDeleteItem() + { + _isDeleteMode = !_isDeleteMode; + + // 可选:加提示,区分状态 + if (_isDeleteMode) + { + Debug.Log("已开启删除模式,点击箭头即可删除"); + // 可加UI提示:如图标高亮、文字提示 + } + else + { + Debug.Log("已关闭删除模式"); + } + } // 基于网格行列的阻挡检测 private bool CheckBlockByGrid(ArrowConfig curArrow) @@ -577,6 +632,58 @@ namespace ChillConnect return isCollide; } + + /// 彻底删除指定箭头:销毁UI+清数据+停逻辑+移除列表 + private void DeleteArrowCompletely(ArrowConfig arrow) + { + if (arrow == null) return; + + // 1. 停止移动标记,拦截Update和协程 + arrow.isMoving = false; + + // 2. 销毁箭头中所有线条UI + if (arrow.lineUnits != null) + { + foreach (var line in arrow.lineUnits) + { + if (line != null) + { + _viewContainer.RemoveChild(line); + line.Dispose(); + } + } + arrow.lineUnits.Clear(); + } + + // 3. 销毁箭头本体UI + if (arrow.arrowObj != null) + { + _viewContainer.RemoveChild(arrow.arrowObj); + arrow.arrowObj.Dispose(); + arrow.arrowObj = null; + } + + // 4. 释放网格占用数据(和飞出边界逻辑保持一致) + ReleaseArrowOccupied(arrow); + + // 5. 存活箭头计数-1 + _remainArrowCount--; + + // 6. 从总列表移除该箭头(核心:删除数据源) + if (_levelConfig != null && _levelConfig.arrows != null) + { + _levelConfig.arrows.Remove(arrow); + } + + // 7. 可选:判断是否全部删除完成,触发结算(按需开启) + if (_remainArrowCount <= 0) + { + ShowResult(true); + } + // 8. 退出删除模式 + _isDeleteMode = false; + Debug.Log("[arrow] 箭头已彻底删除"); + } // 创建箭头 + 绑定点击 private void CreateArrowOnly(ArrowConfig arrow, Vector2 arrowPos) @@ -611,7 +718,7 @@ namespace ChillConnect // 移动后复位动画(回弹,不释放占用) private void MoveThenReset(ArrowConfig arrow) { - CrazyAsyKit.StartCoroutine(MoveAndResetCoroutine(arrow)); + RunCoroutine(MoveAndResetCoroutine(arrow)); } private IEnumerator MoveAndResetCoroutine(ArrowConfig arrow) @@ -638,6 +745,13 @@ namespace ChillConnect while (moved < stepCount) { + // 新增空对象防护 + if (arrow == null || arrow.arrowObj == null) + { + Debug.Log($"[arrow] MoveAndResetCoroutine arrow 为空, 协程结束"); + yield break; + } + for (int i = 0; i < arrow.lineUnits.Count; i++) { int curIdx = arrow.lineTrackIndex[i]; @@ -693,8 +807,10 @@ namespace ChillConnect arrow.lineUnits[i].SetPosition(arrow.originalLinePos[i].x, arrow.originalLinePos[i].y, 0); arrow.lineTrackIndex[i] = i; } - // 单点/多点箭头统一读取原始坐标复位 - arrow.arrowObj.SetPosition(arrow.originalArrowPos.x, arrow.originalArrowPos.y, 0); + if(arrow.arrowObj != null) + { + arrow.arrowObj.SetPosition(arrow.originalArrowPos.x, arrow.originalArrowPos.y, 0); + } arrow.arrowTrackIndex = arrow.totalTrack.Count - 1; arrow.isMoving = false; @@ -702,13 +818,14 @@ namespace ChillConnect private void MoveToDisappear(ArrowConfig arrow) { - CrazyAsyKit.StartCoroutine(MoveAndDisappearCoroutine(arrow)); + RunCoroutine(MoveAndDisappearCoroutine(arrow)); } private IEnumerator MoveAndDisappearCoroutine(ArrowConfig arrow) { + Debug.Log($"[arrow] arrow.totalTrack.Count =={arrow.totalTrack.Count}"); float frameDelay = 0.01f; - int trackMaxIndex = arrow.totalTrack.Count - 1; + int trackMaxIndex = arrow.totalTrack != null ? arrow.totalTrack.Count - 1 : 0; string dir; if (arrow.path != null && arrow.path.Count > 0) @@ -727,6 +844,14 @@ namespace ChillConnect while (true) { + // 兜底:对象已销毁,直接退出 + if (arrow == null || arrow.arrowObj == null) + { + Debug.Log($"arrow 为空, 协程结束"); + + yield break; + } + // 线条移动 for (int i = 0; i < arrow.lineUnits.Count; i++) { @@ -774,38 +899,75 @@ namespace ChillConnect arrow.arrowObj.y += dy; } - // 边界判断 - float curX = arrow.arrowObj.x; - float curY = arrow.arrowObj.y; + // ========= 边界判断:有线箭头取尾部轨迹,单点箭头取自身 ========= + // 直接取箭头实时坐标,不再使用totalTrack静态点位 bool isOut = false; + float checkX = 0; + float checkY = 0; + + // 线段从起点生成,第 0 个元素才是尾巴 + if (arrow.lineUnits != null && arrow.lineUnits.Count > 0) + { + var tailLine = arrow.lineUnits[0]; + checkX = tailLine.x; + checkY = tailLine.y; + } + else if (arrow.arrowObj != null) + { + // 纯单点箭头,使用自身坐标 + checkX = arrow.arrowObj.x; + checkY = arrow.arrowObj.y; + } + + Debug.Log($"[arrow] arrow.finalMoveDir =={arrow.finalMoveDir}"); + switch (arrow.finalMoveDir) { case "right": - if (curX > gridRight + outOffset) isOut = true; + Debug.Log($"[arrow] checkX={checkX} | gridRight={gridRight} | gridRight + outOffset={gridRight + outOffset}"); + if (checkX > gridRight + outOffset) isOut = true; break; case "left": - if (curX < gridLeft - outOffset) isOut = true; + Debug.Log($"[arrow] checkX={checkX} | gridLeft={gridLeft} | gridLeft - outOffset={gridLeft - outOffset}"); + if (checkX < gridLeft - outOffset) isOut = true; break; case "down": - if (curY > gridBottom + outOffset) isOut = true; + Debug.Log($"[arrow] checkY={checkY} | gridBottom={gridBottom} | gridBottom + outOffset={gridBottom + outOffset}"); + if (checkY > gridBottom + outOffset) isOut = true; break; case "up": - if (curY < gridTop - outOffset) isOut = true; + Debug.Log($"[arrow] checkY={checkY} | gridTop={gridTop} | gridTop - outOffset={gridTop - outOffset}"); + if (checkY < gridTop - outOffset) isOut = true; break; } + // ========= 超出边界:隐藏 + 计数 + 终止协程 ========= + Debug.Log($"[arrow] isOut =={isOut}"); if (isOut) { - // 箭头移出屏幕,释放网格占用 ReleaseArrowOccupied(arrow); - // 隐藏视图 + // 销毁线条 foreach (var line in arrow.lineUnits) - line.visible = false; - arrow.arrowObj.visible = false; + { + if(line != null) + { + _viewContainer.RemoveChild(line); + line.Dispose(); + } + } + arrow.lineUnits.Clear(); + + // 销毁箭头 + if(arrow.arrowObj != null) + { + _viewContainer.RemoveChild(arrow.arrowObj); + arrow.arrowObj.Dispose(); + arrow.arrowObj = null; + } + arrow.isMoving = false; - - // ========== 新增:存活箭头-1,判断全部移除 ========== + _remainArrowCount--; if (_remainArrowCount <= 0) { @@ -818,33 +980,6 @@ namespace ChillConnect yield return new WaitForSeconds(frameDelay); } } - - private void CreateLineUnitBetweenTwoPoint(Vector2 pStart, Vector2 pEnd, Color lineColor, List lineList) - { - if (_lineUnitTemplate == null) return; - float offsetX = 0f; - float offsetY = 0f; - - if (Mathf.Abs(pEnd.x - pStart.x) > 1f) - offsetX = 10f; - else - offsetY = 10f; - - Vector2 curPos = pStart; - for (int i = 0; i < 6; i++) - { - LineTile unit = LineTile.CreateInstance(); - unit.SetPosition(curPos.x, curPos.y, 0); - unit.GetChild("line").asGraph.color = lineColor; - unit.visible = true; - - _viewContainer.AddChild(unit); - lineList.Add(unit); - - curPos.x += offsetX; - curPos.y += offsetY; - } - } #endregion #region 点击 & 移动逻辑 @@ -856,6 +991,10 @@ namespace ChillConnect private void UpdateArrowMove(ArrowConfig arrow) { + // 关键拦截:不允许移动 / 对象已销毁 → 直接退出 + if (!arrow.isMoving || arrow.arrowObj == null) + return; + if (!arrow.isMoving) return; List path = arrow.pathPointList; @@ -903,6 +1042,19 @@ namespace ChillConnect #endregion #region 资源清理 + + /// 全局启动协程 + 自动记录,关闭界面时统一停止 + private Coroutine RunCoroutine(IEnumerator cor) + { + if (cor == null) return null; + Coroutine co = CrazyAsyKit.StartCoroutine(cor); + if (co != null) + { + _activeCoroutines.Add(co); + } + return co; + } + private void ClearAllDynamicObj() { if (_levelConfig == null || _viewContainer == null) return; diff --git a/Assets/StreamingAssets/level_1001.json b/Assets/StreamingAssets/level_1001.json index 436367c..bff258a 100644 --- a/Assets/StreamingAssets/level_1001.json +++ b/Assets/StreamingAssets/level_1001.json @@ -8,42 +8,41 @@ { "id": 1, "startPoint": 0, - "endPoint": 25, + "endPoint": 17, "color": "#FFFFFF", "path": [ "right", "right", "right", "right", - "right", "down", - "down" - ] - }, - { - "id": 2, - "startPoint": 30, - "endPoint": 37, - "color": "#FFFFFF", - "path": [ - "right", - "right", - "right", - "right", "right", "right", "right" ] }, { - "id": 3, - "startPoint": 50, - "endPoint": 46, - "color": "#FFFFFF", + "id": 2, + "startPoint": 18, + "endPoint": 23, + "color": "#FFCC00", + "path": [ + "down", + "left", + "left", + "left", + "left", + "down", + "left", + "up" + ] + }, + { + "id": 3, + "startPoint": 36, + "endPoint": 29, + "color": "#33FF00", "path": [ - "right", - "right", - "right", "right", "right", "right", @@ -52,44 +51,26 @@ }, { "id": 4, - "startPoint": 60, - "endPoint": 66, - "color": "#FFFFFF", - "path": [ - "right", - "right", - "right", - "right", - "right", - "right" - ] + "startPoint": 88, + "endPoint": 88, + "color": "#FFFF00", + "path": [] }, { "id": 5, - "startPoint": 93, - "endPoint": 73, + "startPoint": 92, + "endPoint": 84, "color": "#FFFFFF", "path": [ "up", - "up" - ] - }, - { - "id": 6, - "startPoint": 9, - "endPoint": 89, - "color": "#FFFFFF", - "path": [ - "down", - "down", - "down", - "down", - "down", "left", - "down", - "down", + "left", + "up", "right", - "down" + "right", + "right", + "down", + "right" ] } ]