diff --git a/Assets/Scripts/MiniGame/HuoShan/SalesSystem/GlowTubeEffect.cs b/Assets/Scripts/MiniGame/HuoShan/SalesSystem/GlowTubeEffect.cs
index fad3bd3d4..b5972ec10 100644
--- a/Assets/Scripts/MiniGame/HuoShan/SalesSystem/GlowTubeEffect.cs
+++ b/Assets/Scripts/MiniGame/HuoShan/SalesSystem/GlowTubeEffect.cs
@@ -4,10 +4,10 @@ using UnityEngine.Serialization;
namespace AibisDream.MiniGame.HuoShan
{
///
- /// 笑话发生器 · 像素噪点云效果 — 逐像素写 Texture2D,量化色阶呈现粗颗粒像素风
- /// 由 KnobController 通过 SetIntensity / TriggerPulse 驱动
- /// 表现:满强度时噪点云活跃跳动(笑声节奏),随强度降低逐步被压制变稀变暗,
- /// 但反抗脉冲会不断把云重新炸亮 —— 读作"抑制在进行,但没能成功"
+ /// 笑话发生器 · 像素火花管 — 逐像素写 Texture2D,量化色阶呈现粗颗粒像素风
+ /// 由 KnobController 通过 SetFill / SetIntensity / TriggerPulse 驱动
+ /// 表现:管体兼作进度条,右端随抑制推进往左退;管内每格独立跳动并不断迸出火花,
+ /// 抑制越深越稀越暗,但反抗脉冲会把整管重新炸亮 —— 读作"抑制在进行,但没能成功"
///
public class GlowTubeEffect : MonoBehaviour
{
@@ -33,15 +33,47 @@ namespace AibisDream.MiniGame.HuoShan
[SerializeField] private Color midColor = new Color(1f, 0.47f, 0.31f, 1f);
[SerializeField] private Color highColor = new Color(1f, 0.78f, 0.67f, 1f);
+ [Header("进度条(管体长度 = 剩余量)")]
+ [Tooltip("剩余量跟随速度:越大越跟手")]
+ [SerializeField] private float fillLerpSpeed = 16f;
+
+ [Tooltip("前沿热区宽度(占全管比例):越大前端亮带越长")]
+ [SerializeField] private float edgeHotWidth = 0.1f;
+
+ [Tooltip("前沿抖动幅度(占全管比例):让右端边界像火焰一样翻腾而不是一刀切")]
+ [SerializeField] private float edgeBoil = 0.025f;
+
[Header("笑声节奏")]
[Tooltip("笑声脉冲串的基础频率(次/秒),强度越高笑得越快")]
[SerializeField] private float laughRate = 2.2f;
[Tooltip("笑声包络对亮度/密度的影响强度")]
- [SerializeField] private float laughAmplitude = 0.6f;
+ [SerializeField] private float laughAmplitude = 0.85f;
[Header("噪声流动")]
[SerializeField] private float noiseScale = 3f;
- [SerializeField] private float noiseSpeed = 1.2f;
+ [SerializeField] private float noiseSpeed = 2.6f;
+
+ [Header("逐格跳动")]
+ [Tooltip("每格独立闪烁的基础速率(次/秒),越大越躁")]
+ [SerializeField] private float twinkleRate = 11f;
+
+ [Tooltip("跳动锐度:越大越接近整格啪嗒开关,越小越像呼吸")]
+ [Range(1f, 6f)]
+ [SerializeField] private float twinkleSharpness = 2.4f;
+
+ [Header("火花")]
+ [Tooltip("同屏最大火花数")]
+ [SerializeField] private int maxSparks = 96;
+
+ [Tooltip("满强度时每秒生成的火花数")]
+ [SerializeField] private float sparkRate = 45f;
+
+ [Tooltip("火花基础存活时长 (秒)")]
+ [SerializeField] private float sparkLife = 0.32f;
+
+ [Tooltip("火花从前沿迸出的比例(其余散布在整段管体内)")]
+ [Range(0f, 1f)]
+ [SerializeField] private float sparkEdgeBias = 0.55f;
[Header("闪烁")]
[SerializeField] private float flickerRate = 8f;
@@ -70,11 +102,34 @@ namespace AibisDream.MiniGame.HuoShan
private float _seedY;
private float _laughSeed;
+ private float _fillTarget = 1f;
+ private float _fill = 1f;
+
+ private float _activity = 1f;
+ private float _laugh;
+
+ private Spark[] _sparks;
+ private int _sparkCount;
+ private float _sparkAccumulator;
+
private Vector2 _areaHalfSize = new Vector2(0.5f, 0.25f);
+ private struct Spark
+ {
+ public float X;
+ public float Y;
+ public float VX;
+ public float VY;
+ public float Life;
+ public float MaxLife;
+ }
+
/// 当前显示强度(含脉冲)
public float DisplayIntensity { get; private set; }
+ /// 当前管体剩余长度(0-1),已平滑
+ public float Fill => _fill;
+
#region Lifecycle
private void Awake()
@@ -82,6 +137,7 @@ namespace AibisDream.MiniGame.HuoShan
_seedX = Random.Range(0f, 1000f);
_seedY = Random.Range(0f, 1000f);
_laughSeed = Random.Range(0f, 1000f);
+ _sparks = new Spark[Mathf.Max(1, maxSparks)];
CacheAreaBounds();
EnsurePixelRenderer();
}
@@ -98,6 +154,8 @@ namespace AibisDream.MiniGame.HuoShan
float dt = Time.deltaTime;
_time += dt;
UpdateResistancePulse(dt);
+ _fill += (_fillTarget - _fill) * Mathf.Min(1f, dt * fillLerpSpeed);
+ UpdateSparks(dt);
RenderPixels();
}
@@ -111,10 +169,26 @@ namespace AibisDream.MiniGame.HuoShan
_intensity = Mathf.Max(0f, value);
}
+ ///
+ /// 设置管体剩余长度(1=满管,0=空管)。管体从右端往左退,兼作旋钮进度条。
+ ///
+ public void SetFill(float value)
+ {
+ _fillTarget = Mathf.Clamp01(value);
+ }
+
+ /// 立即把管长设为指定值(重置用,不做平滑)
+ public void SetFillImmediate(float value)
+ {
+ _fillTarget = Mathf.Clamp01(value);
+ _fill = _fillTarget;
+ }
+
/// 触发一次反抗脉冲爆亮
public void TriggerPulse(float strength = 0.5f)
{
_resistancePulse = Mathf.Max(_resistancePulse, Mathf.Clamp01(strength));
+ BurstSparks(Mathf.RoundToInt(strength * 24f));
}
#endregion
@@ -212,6 +286,110 @@ namespace AibisDream.MiniGame.HuoShan
return Mathf.Clamp01(burst) * activity;
}
+ #endregion
+
+ #region Sparks
+
+ private void UpdateSparks(float dt)
+ {
+ if (_sparks == null || _sparks.Length != Mathf.Max(1, maxSparks))
+ {
+ _sparks = new Spark[Mathf.Max(1, maxSparks)];
+ _sparkCount = 0;
+ }
+
+ // 存活推进
+ int write = 0;
+ for (int i = 0; i < _sparkCount; i++)
+ {
+ var s = _sparks[i];
+ s.Life -= dt;
+ if (s.Life <= 0f) continue;
+
+ s.X += s.VX * dt;
+ s.Y += s.VY * dt;
+ s.VY *= 1f - Mathf.Min(0.9f, dt * 2.2f); // 轻微空气阻力,火花往外冲后停住
+ if (s.X < -0.05f || s.X > 1.05f || s.Y < -0.4f || s.Y > 1.4f) continue;
+
+ _sparks[write++] = s;
+ }
+ _sparkCount = write;
+
+ if (_fill <= 0.02f) return;
+
+ float spawnPerSec = sparkRate * (0.2f + _activity * 1.1f) * (1f + _laugh * 2.5f + _resistancePulse * 3f);
+ _sparkAccumulator += dt * spawnPerSec;
+ int budget = 24;
+ while (_sparkAccumulator >= 1f && budget-- > 0)
+ {
+ _sparkAccumulator -= 1f;
+ SpawnSpark();
+ }
+ if (_sparkAccumulator > 4f) _sparkAccumulator = 4f;
+ }
+
+ private void BurstSparks(int count)
+ {
+ for (int i = 0; i < count; i++) SpawnSpark();
+ }
+
+ private void SpawnSpark()
+ {
+ if (_sparks == null || _sparkCount >= _sparks.Length) return;
+
+ float x = Random.value < sparkEdgeBias
+ ? Mathf.Max(0f, _fill - Random.value * edgeHotWidth * 0.8f) // 前沿迸溅
+ : Random.value * _fill;
+ float y = 0.5f + (Random.value - 0.5f) * 0.75f;
+
+ float outward = y >= 0.5f ? 1f : -1f;
+ float life = Mathf.Max(0.05f, sparkLife * (0.55f + Random.value * 0.9f));
+
+ _sparks[_sparkCount++] = new Spark
+ {
+ X = x,
+ Y = y,
+ // 略偏左:被抑制的方向
+ VX = (Random.value - 0.5f) * 0.55f - 0.12f,
+ VY = outward * (0.3f + Random.value * 1.1f),
+ Life = life,
+ MaxLife = life
+ };
+ }
+
+ private void DrawSparks()
+ {
+ int w = _texWidth;
+ int h = _texHeight;
+
+ for (int i = 0; i < _sparkCount; i++)
+ {
+ var s = _sparks[i];
+ int px = Mathf.RoundToInt(s.X * (w - 1));
+ int py = Mathf.RoundToInt(s.Y * (h - 1));
+ if (px < 0 || px >= w || py < 0 || py >= h) continue;
+
+ float t = s.MaxLife > 0f ? Mathf.Clamp01(s.Life / s.MaxLife) : 0f;
+ Color c = t > 0.5f ? highColor : Color.Lerp(midColor, highColor, t * 2f);
+ c.a = 1f;
+ _pixels[py * w + px] = c;
+
+ // 拖尾一格,让火花有方向感
+ int tx = px - (s.VX >= 0f ? 1 : -1);
+ int ty = py - (s.VY >= 0f ? 1 : -1);
+ if (t < 0.75f && tx >= 0 && tx < w && ty >= 0 && ty < h)
+ {
+ var tc = midColor;
+ tc.a = 1f;
+ _pixels[ty * w + tx] = tc;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Render
+
private void RenderPixels()
{
if (_tex == null) return;
@@ -220,95 +398,96 @@ namespace AibisDream.MiniGame.HuoShan
DisplayIntensity = di;
// 活动度:强度越高越活跃,且用陡峭曲线让压制过程变化明显
- float activity = Mathf.Pow(Mathf.Clamp01(_intensity), 1.8f);
- float laugh = GetLaughEnvelope(activity);
+ _activity = Mathf.Pow(Mathf.Clamp01(_intensity), 1.8f);
+ _laugh = GetLaughEnvelope(_activity);
float baseFlicker = 1f + Mathf.Sin(_time * flickerRate) * flickerAmplitude * di;
- float laughBoost = 1f + laugh * laughAmplitude;
+ float laughBoost = 1f + _laugh * laughAmplitude;
float totalBoost = baseFlicker * laughBoost;
- // 点亮密度随活动度收缩:功率越低,能被点亮的格子越少(云变稀);满功率时基本全亮
- float densityGate = 0.3f + activity * 0.75f + _resistancePulse * 0.6f;
+ // 点亮密度随活动度收缩:功率越低,同一时刻亮着的格子越少(云变稀、跳得越碎)
+ float density = Mathf.Clamp01(0.28f + _activity * 0.72f + _resistancePulse * 0.6f + _laugh * 0.35f);
+ float gate = 1f - density;
int w = _texWidth;
int h = _texHeight;
- if (di < 0.01f)
+ var clear = new Color32(0, 0, 0, 0);
+ for (int i = 0; i < _pixels.Length; i++) _pixels[i] = clear;
+
+ if (di < 0.01f || _fill < 0.005f)
{
- var clear = new Color32(0, 0, 0, 0);
- for (int i = 0; i < _pixels.Length; i++) _pixels[i] = clear;
_tex.SetPixels32(_pixels);
_tex.Apply(false);
return;
}
float nt = _time * noiseSpeed;
+ float invW = 1f / Mathf.Max(1, w - 1);
+ float invH = 1f / Mathf.Max(1, h - 1);
for (int py = 0; py < h; py++)
{
- float cy = (py / (float)(h - 1) - 0.5f) * 2f;
+ float cy = (py * invH - 0.5f) * 2f;
+
+ // 每行前沿单独抖动:右端像火焰一样翻腾,而不是一条硬边
+ float boilN = Mathf.PerlinNoise(py * 0.35f + _seedY, _time * 6f) - 0.5f;
+ float fillEdge = _fill + boilN * edgeBoil * 2f;
+
for (int px = 0; px < w; px++)
{
int idx = py * w + px;
- float cx = (px / (float)(w - 1) - 0.5f) * 2f;
+ float u = px * invW;
+
+ // 管体只画到前沿为止 —— 抑制推进时整条管从右往左变短
+ float behindEdge = fillEdge - u;
+ if (behindEdge < 0f) continue;
+
+ float cx = (u - 0.5f) * 2f;
// 超椭圆遮罩:只裁掉四角,让噪点云基本铺满整个管体
float cx2 = cx * cx;
float cy2 = cy * cy;
float super = cx2 * cx2 * cx2 + cy2 * cy2 * cy2;
- if (super > 1f)
- {
- _pixels[idx] = new Color32(0, 0, 0, 0);
- continue;
- }
+ if (super > 1f) continue;
float edgeFade = 1f - super * super;
- float nx = px * (noiseScale / w) + _seedX;
- float ny = py * (noiseScale / w) + _seedY;
+ // 前沿热区:越靠近右端越亮,读作"还在往回顶的火头"
+ float edgeHot = Mathf.Exp(-behindEdge / Mathf.Max(0.01f, edgeHotWidth));
+
+ float nx = px * (noiseScale * invW) + _seedX;
+ float ny = py * (noiseScale * invW) + _seedY;
float n = Mathf.PerlinNoise(nx + nt, ny - nt * 0.6f);
- // 每格固定 hash 抖动,避免整片同步开合,形成噪点云颗粒感
- float hash = Frac(Mathf.Sin((px * 12.9898f + py * 78.233f) + _seedX) * 43758.5453f);
+ // 每格固定 hash 决定自己的闪烁相位与速率 → 逐格独立跳动,不再像一张静态贴图
+ float hash = Frac(Mathf.Sin(px * 12.9898f + py * 78.233f + _seedX) * 43758.5453f);
+ float twinkle = 0.5f + 0.5f * Mathf.Sin(_time * twinkleRate * (0.45f + hash * 1.7f) + hash * 63f);
+ twinkle = Mathf.Pow(twinkle, twinkleSharpness);
- // 基线抬高:满强度时整管基本填满,靠色阶档位区分明暗
- float val = (0.35f + n * 0.75f) * edgeFade * totalBoost * di;
- val *= Mathf.Lerp(0.7f, 1.15f, hash);
+ float alive = twinkle * Mathf.Lerp(0.7f, 1.35f, hash)
+ + edgeHot * 0.7f
+ + _resistancePulse * 0.5f
+ + _laugh * 0.35f;
+ if (alive < gate) continue;
- bool lit = hash < densityGate;
- if (!lit)
- {
- _pixels[idx] = new Color32(0, 0, 0, 0);
- continue;
- }
+ float val = (0.22f + n * 0.7f + twinkle * 0.4f) * edgeFade * totalBoost * di;
+ val *= 1f + edgeHot * 1.2f;
Color32 c;
- if (val < thresholdLow)
- {
- _pixels[idx] = new Color32(0, 0, 0, 0);
- continue;
- }
- else if (val < thresholdMid)
- {
- c = lowColor;
- }
- else if (val < thresholdHigh)
- {
- c = midColor;
- }
- else
- {
- c = highColor;
- }
+ if (val < thresholdLow) continue;
+ if (val < thresholdMid) c = lowColor;
+ else if (val < thresholdHigh) c = midColor;
+ else c = highColor;
- if (_resistancePulse > 0.05f && hash > 1f - _resistancePulse)
- {
+ if (edgeHot > 0.65f || (_resistancePulse > 0.05f && hash > 1f - _resistancePulse))
c = highColor;
- }
_pixels[idx] = c;
}
}
+ DrawSparks();
+
_tex.SetPixels32(_pixels);
_tex.Apply(false);
}
diff --git a/Assets/Scripts/MiniGame/HuoShan/SalesSystem/KnobController.cs b/Assets/Scripts/MiniGame/HuoShan/SalesSystem/KnobController.cs
index 149025ce2..62753efd8 100644
--- a/Assets/Scripts/MiniGame/HuoShan/SalesSystem/KnobController.cs
+++ b/Assets/Scripts/MiniGame/HuoShan/SalesSystem/KnobController.cs
@@ -53,6 +53,9 @@ namespace AibisDream.MiniGame.HuoShan
[Tooltip("辉光管粒子效果(不填则从 SaleView 下查找)")]
[SerializeField] private GlowTubeEffect glowTubeEffect;
+ [Tooltip("辉光管兼作进度条:勾选则以「失败阈值」为满量程,旋钮一转管体就明显变短;不勾选按整圈量程")]
+ [SerializeField] private bool glowFillUsesFailThreshold = true;
+
[Header("信息面板")]
[SerializeField] private GameObject infoPanel;
[SerializeField] private UnityEngine.UI.Text infoText;
@@ -95,26 +98,6 @@ namespace AibisDream.MiniGame.HuoShan
[Tooltip("开始拖拽旋钮时是否退出激活态(回到展开)")]
[SerializeField] private bool clearHighlightWhenDragStarts = true;
- [Header("环形进度条")]
- [Tooltip("灯带进度条 SpriteRenderer;不填则尝试自动查找")]
- [SerializeField] private SpriteRenderer ringProgressRenderer;
-
- [Tooltip("自动查找的灯带节点名")]
- [SerializeField] private string ringProgressChildName = "灯带进度条";
-
- [Tooltip("环形填充起始角度,0=右,90=上")]
- [SerializeField] private float ringProgressStartAngle = 90f;
-
- [Tooltip("勾选则按顺时针方向填充")]
- [SerializeField] private bool ringProgressClockwise = true;
-
- [Tooltip("灯带进度条着色")]
- [SerializeField] private Color ringProgressTint = new Color(1f, 0.72f, 0.25f);
-
- [Tooltip("着色强度:0=保留贴图本色,1=完全按上方颜色重新上色(贴图只保留明暗)")]
- [Range(0f, 1f)]
- [SerializeField] private float ringProgressRecolor = 1f;
-
[Header("事件")]
public UnityEvent onPowerAdjustmentStart;
public UnityEvent onPowerChanged;
@@ -169,20 +152,11 @@ namespace AibisDream.MiniGame.HuoShan
private EventTriggerEx _eventTrigger;
private bool _useEventTrigger;
- private Material _ringProgressMaterial;
-
- private const string RingProgressShaderName = "AibisDream/SpriteRadialProgress";
- private const string RingProgressShaderResourcePath = "Shader/SpriteRadialProgress";
private const string CollapsedSpriteName = "旋钮收起";
private const string ExpandedSpriteName = "旋钮展开";
private const string ActiveSpriteName = "旋钮激活状态";
- private static readonly int MainTexId = Shader.PropertyToID("_MainTex");
- private static readonly int ProgressId = Shader.PropertyToID("_Progress");
- private static readonly int StartAngleId = Shader.PropertyToID("_StartAngle");
- private static readonly int FillClockwiseId = Shader.PropertyToID("_FillClockwise");
+ private const string LegacyRingProgressName = "灯带进度条";
private static readonly int ShineFadeId = Shader.PropertyToID("_ShineFade");
- private static readonly int ColorId = Shader.PropertyToID("_Color");
- private static readonly int RecolorStrengthId = Shader.PropertyToID("_RecolorStrength");
private SpriteRenderer _shineHighlightSprite;
private bool _isLidOpen;
@@ -240,7 +214,8 @@ namespace AibisDream.MiniGame.HuoShan
DisableLegacyKnobLid();
ApplyKnobAppearance(KnobAppearance.Collapsed, force: true);
- EnsureRingProgress();
+ DisableLegacyRingProgress();
+ EnsureGlowTubeEffect();
EnsureInteractionHighlightSprite();
SetInteractionHighlightVisible(false);
@@ -374,65 +349,44 @@ namespace AibisDream.MiniGame.HuoShan
knobVisual.sprite = target;
}
- private void EnsureRingProgress()
+ ///
+ /// 旧版环形灯带进度条已废弃(进度改由辉光管长度承担),场景里残留的节点直接隐藏。
+ ///
+ private void DisableLegacyRingProgress()
{
- if (ringProgressRenderer == null && knobTransform != null && !string.IsNullOrEmpty(ringProgressChildName))
- {
- var ring = knobTransform.Find(ringProgressChildName);
- if (ring == null && knobTransform.parent != null)
- ring = knobTransform.parent.Find(ringProgressChildName);
- if (ring != null)
- ringProgressRenderer = ring.GetComponent();
- }
+ if (knobTransform == null) return;
- if (ringProgressRenderer == null)
- return;
-
- Shader shader = Resources.Load(RingProgressShaderResourcePath);
- if (shader == null)
- shader = Shader.Find(RingProgressShaderName);
-
- if (shader == null)
- {
-#if UNITY_EDITOR
- Debug.LogWarning($"[KnobController] 未找到环形进度条 Shader:{RingProgressShaderName}", this);
-#endif
- return;
- }
-
- _ringProgressMaterial = new Material(shader)
- {
- name = $"{ringProgressRenderer.gameObject.name}_RingProgress_Mat"
- };
-
- if (ringProgressRenderer.sprite != null)
- _ringProgressMaterial.SetTexture(MainTexId, ringProgressRenderer.sprite.texture);
-
- ringProgressRenderer.material = _ringProgressMaterial;
- ApplyRingProgressMaterialProperties();
- UpdateRingProgress(_knobValue);
+ var ring = knobTransform.Find(LegacyRingProgressName);
+ if (ring == null && knobTransform.parent != null)
+ ring = knobTransform.parent.Find(LegacyRingProgressName);
+ if (ring != null)
+ ring.gameObject.SetActive(false);
}
- private void ApplyRingProgressMaterialProperties()
+ private void EnsureGlowTubeEffect()
{
- if (_ringProgressMaterial == null)
- return;
+ if (glowTubeEffect != null) return;
- _ringProgressMaterial.SetFloat(StartAngleId, ringProgressStartAngle);
- _ringProgressMaterial.SetFloat(FillClockwiseId, ringProgressClockwise ? 1f : 0f);
- _ringProgressMaterial.SetColor(ColorId, ringProgressTint);
- _ringProgressMaterial.SetFloat(RecolorStrengthId, ringProgressRecolor);
+ var t = transform;
+ while (t != null)
+ {
+ if (t.name == "SaleView" || t.name == "SellView" || t.name == "SalelView")
+ {
+ glowTubeEffect = t.GetComponentInChildren(true);
+ break;
+ }
+ t = t.parent;
+ }
+
+ if (glowTubeEffect == null)
+ glowTubeEffect = FindObjectOfType(true);
}
- private void UpdateRingProgress(float progress)
+ /// 辉光管剩余量:1=满管,0=空管。旋钮拧到失败阈值时正好排空。
+ private float GetGlowFill()
{
- if (_ringProgressMaterial == null)
- return;
-
- if (ringProgressRenderer != null && ringProgressRenderer.sprite != null)
- _ringProgressMaterial.SetTexture(MainTexId, ringProgressRenderer.sprite.texture);
-
- _ringProgressMaterial.SetFloat(ProgressId, Mathf.Clamp01(progress));
+ float span = glowFillUsesFailThreshold ? Mathf.Max(0.01f, failThreshold) : 1f;
+ return Mathf.Clamp01(1f - _knobValue / span);
}
private void EnsureEventTriggerEntries()
@@ -455,6 +409,8 @@ namespace AibisDream.MiniGame.HuoShan
private void Start()
{
UpdateFromKnobAngle();
+ if (glowTubeEffect != null)
+ glowTubeEffect.SetFillImmediate(GetGlowFill());
}
private void Update()
@@ -603,7 +559,6 @@ namespace AibisDream.MiniGame.HuoShan
{
_knobAngle = Mathf.Clamp(_knobAngle, 0f, _maxAngle);
_knobValue = _knobAngle / _maxAngle;
- UpdateRingProgress(_knobValue);
// Intensity: cubic falloff
_intensity = Mathf.Pow(1f - _knobValue, 3f);
@@ -784,13 +739,14 @@ namespace AibisDream.MiniGame.HuoShan
float overshoot = _overshootIntensity * Mathf.Exp(-_overshootDecay * 2.5f)
* (1f + Mathf.Sin(_overshootDecay * 40f) * 0.5f * Mathf.Exp(-_overshootDecay * 1.5f));
- // 辉光与环形进度一致:用线性剩余量驱动粒子,避免 Pow(...,3) 导致中段过暗、与灯带进度脱节
- float glowBase = Mathf.Max(0.03f, 1f - _knobValue);
- _displayIntensity = glowBase + _resistancePulse + Mathf.Max(0f, overshoot);
+ // 辉光管兼作进度条:管长(fill)与亮度同源,拧旋钮时管体从右往左退且整体变暗
+ float fill = GetGlowFill();
+ _displayIntensity = Mathf.Max(0.03f, fill) + _resistancePulse + Mathf.Max(0f, overshoot);
_displayIntensity = Mathf.Min(1.5f, _displayIntensity);
if (glowTubeEffect != null)
{
+ glowTubeEffect.SetFill(fill);
glowTubeEffect.SetIntensity(_displayIntensity);
if (_resistancePulse > 0.1f)
glowTubeEffect.TriggerPulse(_resistancePulse * 0.5f);
@@ -954,6 +910,9 @@ namespace AibisDream.MiniGame.HuoShan
UpdateFromKnobAngle();
+ if (glowTubeEffect != null)
+ glowTubeEffect.SetFillImmediate(GetGlowFill());
+
HideInfoPanel();
Debug.Log("[KnobController] Reset");
@@ -987,16 +946,6 @@ namespace AibisDream.MiniGame.HuoShan
onPowerAdjustmentSuccess?.Invoke(_currentPower);
}
- private void OnDestroy()
- {
- if (_ringProgressMaterial == null) return;
-
- if (Application.isPlaying)
- Destroy(_ringProgressMaterial);
- else
- DestroyImmediate(_ringProgressMaterial);
- }
-
#endregion
}