refactor(huoshan): SliderController 移除波形联动、修正顺时针逻辑、添加 Gizmo
Made-with: Cursor
This commit is contained in:
@@ -6,11 +6,11 @@ using DG.Tweening;
|
||||
namespace AibisDream.MiniGame.HuoShan
|
||||
{
|
||||
/// <summary>
|
||||
/// 滑片控制器 - 实现滑片沿圆环滑动以及与波形联动
|
||||
/// 滑片控制器 - 实现滑片沿圆环滑动
|
||||
/// 功能:
|
||||
/// - 仅通过Yarn指令控制移动,不接受玩家直接交互
|
||||
/// - 滑片角度/弧度驱动波形参数
|
||||
/// - 等离子体发光段:从起始位置到当前位置显示等离子体进度指示
|
||||
/// - 位置变化通过 onSliderPositionChanged 通知(EmotionWaveManager 等可订阅)
|
||||
/// </summary>
|
||||
public class SliderController : MonoBehaviour
|
||||
{
|
||||
@@ -75,17 +75,6 @@ namespace AibisDream.MiniGame.HuoShan
|
||||
[Tooltip("粒子渲染 Sorting Order")]
|
||||
[SerializeField] private int plasmaSortingOrder = 51;
|
||||
|
||||
[Header("兼容旧版 LineRenderer(可留空)")]
|
||||
[Tooltip("若存在则禁用,改用 ParticleSystem")]
|
||||
[SerializeField] private LineRenderer plasmaLineRenderer;
|
||||
|
||||
[Header("波形联动")]
|
||||
[Tooltip("波形检测器引用")]
|
||||
[SerializeField] private WaveformDetector waveformDetector;
|
||||
|
||||
[Tooltip("等离子体发光影响波形参数")]
|
||||
[SerializeField] private bool plasmaAffectsWaveform = true;
|
||||
|
||||
[Header("事件")]
|
||||
[Tooltip("滑片位置改变时触发(参数:标准化位置0-1)")]
|
||||
public UnityEvent<float> onSliderPositionChanged;
|
||||
@@ -103,7 +92,7 @@ namespace AibisDream.MiniGame.HuoShan
|
||||
public UnityEvent onSlideComplete;
|
||||
|
||||
[Header("调试测试")]
|
||||
[Tooltip("勾选后,拖拽下方滑块可直接测试滑片与弧线(Play 模式下生效);有程序控制滑动时会自动跳过")]
|
||||
[Tooltip("勾选后,拖拽下方滑块可直接测试滑片与弧线(Play 模式下生效,优先于程序控制)")]
|
||||
[SerializeField] private bool useTestSlider;
|
||||
|
||||
[Tooltip("测试用滑块:0=起始位置,1=终点位置")]
|
||||
@@ -111,7 +100,6 @@ namespace AibisDream.MiniGame.HuoShan
|
||||
|
||||
private float _currentAngle = 0f;
|
||||
private float _targetAngle = 0f;
|
||||
private WaveformRenderer _waveformRenderer;
|
||||
private bool _phaseSemanticFired;
|
||||
private bool _phaseReviewFired;
|
||||
private bool _phaseStyleFired;
|
||||
@@ -132,20 +120,8 @@ namespace AibisDream.MiniGame.HuoShan
|
||||
sliderTransform = transform;
|
||||
}
|
||||
|
||||
// 禁用旧版 LineRenderer(改用 ParticleSystem)
|
||||
if (plasmaLineRenderer != null)
|
||||
{
|
||||
plasmaLineRenderer.enabled = false;
|
||||
}
|
||||
|
||||
// 初始化等离子体粒子系统
|
||||
EnsurePlasmaParticleSystem();
|
||||
|
||||
// 获取波形渲染器
|
||||
if (waveformDetector != null && waveformDetector.IsShown)
|
||||
{
|
||||
_waveformRenderer = waveformDetector.GetComponentInChildren<WaveformRenderer>();
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
@@ -166,22 +142,16 @@ namespace AibisDream.MiniGame.HuoShan
|
||||
|
||||
#region 位置更新
|
||||
|
||||
private void UpdateSliderPosition()
|
||||
/// <summary>
|
||||
/// 根据角度应用滑片位置与旋转(顺时针移动:角度取负)
|
||||
/// </summary>
|
||||
/// <returns>滑片世界坐标</returns>
|
||||
private Vector3 ApplyAngleToTransform(float angle)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// 调试模式:Inspector 滑块直接驱动滑片(有程序控制的滑动时跳过,避免覆盖 crank 驱动)
|
||||
if (useTestSlider && Application.isPlaying && (_moveTween == null || !_moveTween.IsActive()))
|
||||
{
|
||||
_targetAngle = testSliderPosition * slideAngleRange;
|
||||
}
|
||||
#endif
|
||||
if (ringCenter == null || sliderTransform == null) return _lastValidPosition;
|
||||
|
||||
// 匀速移动到目标角度(避免 Lerp 导致的越接近越慢、卡顿感)
|
||||
float maxDelta = slideSpeed * Time.deltaTime;
|
||||
_currentAngle = Mathf.MoveTowards(_currentAngle, _targetAngle, maxDelta);
|
||||
|
||||
// 计算滑片在世界空间的位置
|
||||
float radian = (_currentAngle + startAngleOffset) * Mathf.Deg2Rad;
|
||||
// 顺时针:标准数学角度增加为逆时针,取负则为顺时针
|
||||
float radian = -(angle + startAngleOffset) * Mathf.Deg2Rad;
|
||||
Vector3 position = ringCenter.position + new Vector3(
|
||||
Mathf.Cos(radian) * outerRadius,
|
||||
Mathf.Sin(radian) * outerRadius,
|
||||
@@ -190,12 +160,39 @@ namespace AibisDream.MiniGame.HuoShan
|
||||
|
||||
sliderTransform.position = position;
|
||||
|
||||
// 滑片沿轨道顺时针方向(切线方向,与逆时针相反)
|
||||
// 滑片沿轨道顺时针方向(切线方向)
|
||||
Vector3 direction = position - ringCenter.position;
|
||||
float radialAngle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
|
||||
float tangentAngle = radialAngle - 90f; // 顺时针切线
|
||||
sliderTransform.rotation = Quaternion.Euler(0f, 0f, tangentAngle);
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
private void UpdateSliderPosition()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// 调试模式:Inspector 滑块直接驱动滑片,勾选后始终优先(覆盖程序控制)
|
||||
if (useTestSlider && Application.isPlaying)
|
||||
{
|
||||
if (_moveTween != null && _moveTween.IsActive())
|
||||
{
|
||||
_moveTween.Kill();
|
||||
_moveTween = null;
|
||||
}
|
||||
_targetAngle = testSliderPosition * slideAngleRange;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 匀速移动到目标角度(避免 Lerp 导致的越接近越慢、卡顿感)
|
||||
float maxDelta = slideSpeed * Time.deltaTime;
|
||||
_currentAngle = Mathf.MoveTowards(_currentAngle, _targetAngle, maxDelta);
|
||||
|
||||
if (ringCenter == null || sliderTransform == null) return;
|
||||
|
||||
// 计算滑片在世界空间的位置(顺时针:角度取负)
|
||||
Vector3 position = ApplyAngleToTransform(_currentAngle);
|
||||
|
||||
// 夹子不跟随滑片移动,保持原位
|
||||
|
||||
// 触发位置改变事件
|
||||
@@ -203,7 +200,6 @@ namespace AibisDream.MiniGame.HuoShan
|
||||
if (Vector3.Distance(position, _lastValidPosition) > 0.01f)
|
||||
{
|
||||
onSliderPositionChanged?.Invoke(normalizedPosition);
|
||||
UpdateWaveform(normalizedPosition);
|
||||
_lastValidPosition = position;
|
||||
|
||||
// 阶段阈值事件:1/3 语义组织, 2/3 审查, 1 风格
|
||||
@@ -360,8 +356,9 @@ namespace AibisDream.MiniGame.HuoShan
|
||||
return;
|
||||
}
|
||||
|
||||
float startRad = startAngleOffset * Mathf.Deg2Rad;
|
||||
float endRad = (startAngleOffset + _currentAngle) * Mathf.Deg2Rad;
|
||||
// 顺时针:弧线从 startAngleOffset 向负角度延伸
|
||||
float startRad = -startAngleOffset * Mathf.Deg2Rad;
|
||||
float endRad = -(startAngleOffset + _currentAngle) * Mathf.Deg2Rad;
|
||||
float arcSpan = endRad - startRad;
|
||||
|
||||
float z = sliderTransform != null ? sliderTransform.position.z : ringCenter.position.z;
|
||||
@@ -405,34 +402,90 @@ namespace AibisDream.MiniGame.HuoShan
|
||||
|
||||
#endregion
|
||||
|
||||
#region 波形联动
|
||||
#region Gizmo 与编辑器
|
||||
|
||||
private void UpdateWaveform(float normalizedPosition)
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
if (!plasmaAffectsWaveform || waveformDetector == null) return;
|
||||
var center = ringCenter != null ? ringCenter.position : transform.position;
|
||||
float z = sliderTransform != null ? sliderTransform.position.z : center.z;
|
||||
|
||||
// 将滑片位置映射到波形参数
|
||||
float waveformPosition = normalizedPosition;
|
||||
// 外环
|
||||
Gizmos.color = new Color(0.2f, 0.8f, 1f, 0.6f);
|
||||
DrawCircleGizmo(center, outerRadius, z, 64);
|
||||
|
||||
// 更新波形检测器的扫描位置
|
||||
if (waveformDetector.IsScanMode)
|
||||
// 内环(等离子体弧线)
|
||||
Gizmos.color = new Color(0.3f, 0.9f, 0.55f, 0.5f);
|
||||
DrawCircleGizmo(center, innerRadius, z, 64);
|
||||
|
||||
// 起始位置标记(绿色)
|
||||
float startRad = -(0f + startAngleOffset) * Mathf.Deg2Rad;
|
||||
Vector3 startPos = center + new Vector3(Mathf.Cos(startRad) * outerRadius, Mathf.Sin(startRad) * outerRadius, 0f);
|
||||
Gizmos.color = Color.green;
|
||||
Gizmos.DrawWireSphere(startPos, outerRadius * 0.05f);
|
||||
|
||||
// 终点位置标记(黄色)
|
||||
float endRad = -(slideAngleRange + startAngleOffset) * Mathf.Deg2Rad;
|
||||
Vector3 endPos = center + new Vector3(Mathf.Cos(endRad) * outerRadius, Mathf.Sin(endRad) * outerRadius, 0f);
|
||||
Gizmos.color = Color.yellow;
|
||||
Gizmos.DrawWireSphere(endPos, outerRadius * 0.05f);
|
||||
|
||||
// 段分割线
|
||||
Gizmos.color = new Color(1f, 1f, 0.5f, 0.3f);
|
||||
float segAngle = slideAngleRange / Mathf.Max(1, segmentCount);
|
||||
for (int i = 1; i < segmentCount; i++)
|
||||
{
|
||||
// 如果处于扫描模式,更新扫描滑块
|
||||
// 这会是集成的一部分,具体实现需要根据游戏流程调整
|
||||
float rad = -(i * segAngle + startAngleOffset) * Mathf.Deg2Rad;
|
||||
Vector3 segPos = center + new Vector3(Mathf.Cos(rad) * outerRadius, Mathf.Sin(rad) * outerRadius, 0f);
|
||||
Gizmos.DrawLine(center, segPos);
|
||||
}
|
||||
|
||||
// 更新波形渲染器
|
||||
if (_waveformRenderer != null)
|
||||
// 当前滑片位置(红色,仅 Play 模式有值)
|
||||
#if UNITY_EDITOR
|
||||
if (Application.isPlaying)
|
||||
#endif
|
||||
{
|
||||
// 根据滑片位置调整波形清晰度
|
||||
float clarity = Mathf.Lerp(0f, 1f, normalizedPosition);
|
||||
_waveformRenderer.SetClarity(clarity);
|
||||
|
||||
// 根据滑片位置调整波形位置
|
||||
_waveformRenderer.SetClarityPosition(normalizedPosition);
|
||||
float curRad = -(_currentAngle + startAngleOffset) * Mathf.Deg2Rad;
|
||||
Vector3 curPos = center + new Vector3(Mathf.Cos(curRad) * outerRadius, Mathf.Sin(curRad) * outerRadius, 0f);
|
||||
Gizmos.color = Color.red;
|
||||
Gizmos.DrawWireSphere(curPos, outerRadius * 0.08f);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCircleGizmo(Vector3 center, float radius, float z, int segments)
|
||||
{
|
||||
Vector3 prev = center + new Vector3(radius, 0f, 0f);
|
||||
for (int i = 1; i <= segments; i++)
|
||||
{
|
||||
float rad = (float)i / segments * Mathf.PI * 2f;
|
||||
Vector3 next = center + new Vector3(Mathf.Cos(rad) * radius, Mathf.Sin(rad) * radius, 0f);
|
||||
Gizmos.DrawLine(prev, next);
|
||||
prev = next;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在编辑器中一键将滑片重置到初始状态
|
||||
/// </summary>
|
||||
[ContextMenu("重置到初始状态")]
|
||||
private void ResetToInitialStateInEditor()
|
||||
{
|
||||
_targetAngle = 0f;
|
||||
_currentAngle = 0f;
|
||||
ResetPhaseFlags();
|
||||
if (_moveTween != null && _moveTween.IsActive())
|
||||
{
|
||||
_moveTween.Kill();
|
||||
_moveTween = null;
|
||||
}
|
||||
if (ringCenter != null && sliderTransform != null)
|
||||
ApplyAngleToTransform(0f);
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorUtility.SetDirty(this);
|
||||
if (gameObject.scene.IsValid())
|
||||
UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(gameObject.scene);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 公共方法
|
||||
|
||||
Reference in New Issue
Block a user