fix(fix): 调整对话气泡加载时机与销售态槽位优先级

Enter 中先 LoadBubbles 再 SwitchCamera,避免 me: 释放log 时找不到 Player 槽位。
SalesState 中优先使用 salesManager.bubbleSlotGroup,缺失时回退 ScreenSystem。

Made-with: Cursor
This commit is contained in:
2026-03-12 15:24:46 +08:00
parent faa14386f5
commit 0bcdcba8a1
3 changed files with 102 additions and 4 deletions
@@ -42,6 +42,13 @@ namespace AibisDream.MiniGame.HuoShan
[Tooltip("发条开始拖拽时触发")]
public UnityEvent onCrankStartDrag;
[Header("逆时针转圈表现")]
[Tooltip("逆时针转一圈的动画时长(秒)")]
[SerializeField] private float spinOnceDuration = 1f;
[Tooltip("逆时针转一圈完成后触发")]
public UnityEvent onSpinOnceComplete;
[Header("圆环/中心配置")]
[Tooltip("环中心(内环旋转中心),配置后发条将沿环轨道移动;不填则原地旋转")]
[SerializeField] private Transform ringCenter;
@@ -82,6 +89,9 @@ namespace AibisDream.MiniGame.HuoShan
private Vector3 _initialScale;
private Tweener _scaleTween;
private Tweener _returnTween;
private Tweener _spinTween;
private float _spinAngleOffset; // 逆时针转圈时的附加角度(0~360)
private bool _isSpinning; // 正在播放逆时针转圈
private float _effectiveRadius; // 实际使用的环半径
private bool _isReturning;
private float _returnSpeedPerSec; // 回位时的度/秒,匀速
@@ -298,7 +308,7 @@ namespace AibisDream.MiniGame.HuoShan
// 顺时针为正时,视觉上角度取反(数学角度逆时针为正)
float visualAngle = clockwisePositive ? -angle : angle;
float positionAngle = startAngleOffset + visualAngle;
float positionAngle = startAngleOffset + visualAngle + _spinAngleOffset;
if (ringCenter != null && _effectiveRadius > 0f)
{
@@ -320,7 +330,8 @@ namespace AibisDream.MiniGame.HuoShan
}
else
{
crankTransform.localRotation = Quaternion.Euler(0f, 0f, -visualAngle);
// 原地旋转:-visualAngle 为基础朝向,+_spinAngleOffset 为逆时针转圈叠加
crankTransform.localRotation = Quaternion.Euler(0f, 0f, -visualAngle + _spinAngleOffset);
}
}
@@ -353,6 +364,13 @@ namespace AibisDream.MiniGame.HuoShan
_returnTween.Kill();
_returnTween = null;
}
if (_spinTween != null)
{
_spinTween.Kill();
_spinTween = null;
_spinAngleOffset = 0f;
_isSpinning = false;
}
_isReturning = false;
// 拖拽缩放效果
@@ -435,7 +453,7 @@ namespace AibisDream.MiniGame.HuoShan
private void HandleReturn()
{
if (!_isDragging && autoReturn && _currentRotation > 0f && !_isReturning)
if (!_isDragging && autoReturn && _currentRotation > 0f && !_isReturning && !_isSpinning)
{
_isReturning = true;
_returnSpeedPerSec = maxRotationAngle / Mathf.Max(0.01f, returnDuration);
@@ -467,6 +485,13 @@ namespace AibisDream.MiniGame.HuoShan
_returnTween.Kill();
_returnTween = null;
}
if (_spinTween != null)
{
_spinTween.Kill();
_spinTween = null;
}
_spinAngleOffset = 0f;
_isSpinning = false;
_isReturning = false;
_isDragging = false;
@@ -480,6 +505,43 @@ namespace AibisDream.MiniGame.HuoShan
}
}
/// <summary>
/// 逆时针转一圈的表现(可被 Yarn 命令、事件等触发)
/// </summary>
/// <param name="duration">动画时长,不传则使用 spinOnceDuration</param>
public void PlaySpinCounterClockwise(float? duration = null)
{
float d = duration ?? spinOnceDuration;
if (d <= 0f) d = 0.5f;
if (_spinTween != null)
{
_spinTween.Kill();
_spinTween = null;
}
_spinAngleOffset = 0f;
_isSpinning = true;
_spinTween = DOTween.To(
() => _spinAngleOffset,
value =>
{
_spinAngleOffset = value;
ApplyCrankTransform(_currentRotation);
},
360f,
d
).SetEase(Ease.Linear).OnComplete(() =>
{
_spinAngleOffset = 0f;
_spinTween = null;
_isSpinning = false;
ApplyCrankTransform(_currentRotation);
onSpinOnceComplete?.Invoke();
});
}
/// <summary>
/// 手动旋转到指定角度(用于动画或程序化控制)
/// </summary>
@@ -532,6 +594,11 @@ namespace AibisDream.MiniGame.HuoShan
/// </summary>
public bool HasTriggered => _hasTriggered;
/// <summary>
/// 是否正在播放逆时针转圈
/// </summary>
public bool IsSpinning => _isSpinning;
/// <summary>
/// 回位时长(秒),供滑片等配合使用
/// </summary>
@@ -86,6 +86,32 @@ namespace AibisDream.MiniGame.HuoShan
Debug.Log("[SalesYarnCommand] 发条完成");
}
/// <summary>
/// 发条逆时针转一圈的表现
/// 用法: <<spin_crank>> 或 <<spin_crank 0.8>>
/// </summary>
/// <param name="duration">动画时长(秒),0 或不传则使用 CrankController 配置值</param>
[YarnCommand("spin_crank")]
public static IEnumerator SpinCrank(float duration = 0f)
{
var crankController = GetSalesManager()?.CrankController;
if (crankController == null)
{
Debug.LogWarning("[SalesYarnCommand] 未找到CrankController");
yield break;
}
crankController.PlaySpinCounterClockwise(duration > 0f ? duration : null);
// 等待转圈完成
while (crankController.IsSpinning)
{
yield return null;
}
Debug.Log("[SalesYarnCommand] 发条逆时针转圈完成");
}
#endregion
#region
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
@@ -55,6 +55,11 @@ namespace AibisDream
.Select(item => _bubbleFactory.Create(item))
.GroupBy(item => item.Role)
.ToDictionary(group => group.Key, group => group.ToArray());
#if UNITY_EDITOR
var roleSummary = string.Join(", ", _bubbleDict.Select(kv => $"{kv.Key}({kv.Value.Length})"));
Debug.Log($"[BubbleGroup] 已加载 {groupData.dialogViewType}: {roleSummary}", this);
#endif
}
#endregion