Merge branch '7.27night春晖优化' into 'develop'
fix(fix-system): 修正线盘松弛预判朝向与绷紧判定 See merge request aibis-dream/aibis-dream!801
This commit is contained in:
@@ -92,10 +92,11 @@ namespace AibisDream.FixSystem
|
||||
return;
|
||||
}
|
||||
|
||||
// 线缆还有余量时不驱动转盘,避免"还没拉紧就先转"
|
||||
// 松弛时不驱动转盘,并缓动回正,避免出线口对着插头“预判”朝向
|
||||
if (tautness <= 0f)
|
||||
{
|
||||
angularVelocity *= Mathf.Exp(-angularDamping * Time.deltaTime);
|
||||
angularVelocity = 0f;
|
||||
currentAngle = Mathf.LerpAngle(currentAngle, 0f, returnSpeed * Time.deltaTime);
|
||||
ApplyRotation();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -96,16 +96,21 @@ public class PhysicCable : MonoBehaviour
|
||||
|
||||
public float CurrentLength => _length;
|
||||
|
||||
/// <summary>0=完全松弛,1=绷直。线盘只在真正拉紧后才应转动。</summary>
|
||||
public float GetTautness(float slackMargin = 0.35f)
|
||||
/// <summary>
|
||||
/// 0=完全松弛,1=绷直。已扣除送线故意留的余量(1.04×直线距 + lengthMargin),
|
||||
/// 避免「有设计余量就永远不转」;线盘只在真正被拽时才应转动。
|
||||
/// </summary>
|
||||
public float GetTautness(float extraSlackMargin = 0.2f)
|
||||
{
|
||||
if (State != CableState.Dragging && State != CableState.Plugged) return 0f;
|
||||
if (_pts == null || startTransform == null) return 0f;
|
||||
|
||||
float straightDist = Vector3.Distance(startTransform.position, FlattenZ(EndPosition));
|
||||
float slack = _length - straightDist;
|
||||
if (slack >= slackMargin) return 0f;
|
||||
return 1f - Mathf.Clamp01(slack / slackMargin);
|
||||
float baselineLength = straightDist * 1.04f + lengthMargin;
|
||||
float extraSlack = _length - baselineLength;
|
||||
if (extraSlack >= extraSlackMargin) return 0f;
|
||||
if (extraSlack <= 0f) return 1f;
|
||||
return 1f - extraSlack / extraSlackMargin;
|
||||
}
|
||||
|
||||
private struct Particle
|
||||
|
||||
@@ -199,15 +199,14 @@ namespace AibisDream.FixSystem
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// 拖拽/插接时转盘朝插头方向转动,闲置时缓动回正。
|
||||
// 不再要求线缆完全绷紧,否则送线会让 tautness 长时间为 0,视觉上看不到旋转。
|
||||
// 仅拖拽时由拉力驱动出线口倾斜;插接/松弛不预判朝向插头。
|
||||
// GetTautness 已扣除送线设计余量,绷紧时才会转。
|
||||
if (CableReelRef != null && physicCableRef != null
|
||||
&& physicCableRef.State != PhysicCable.CableState.Hidden)
|
||||
{
|
||||
bool active = physicCableRef.State == PhysicCable.CableState.Dragging
|
||||
|| physicCableRef.State == PhysicCable.CableState.Plugged
|
||||
|| physicCableRef.State == PhysicCable.CableState.Collapsing;
|
||||
CableReelRef.UpdateRotation(active);
|
||||
bool active = physicCableRef.State == PhysicCable.CableState.Dragging;
|
||||
float tautness = active ? physicCableRef.GetTautness() : 0f;
|
||||
CableReelRef.UpdateRotation(active, tautness);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -125,9 +125,9 @@ namespace AibisDream.MiniGame.Language
|
||||
[Tooltip("可选:场景中一块与屏幕内框对齐的 RectTransform(World Space Canvas 子物体即可)。不指定则用粒子用的 movementBounds(canvasSize - textMargin)")]
|
||||
[SerializeField] private RectTransform completionScreenClipRect;
|
||||
[Tooltip("在裁剪区基础上再向内缩进的世界单位距离,避免放大后的字半个挂在边外")]
|
||||
[SerializeField] private float completionClipEdgePadding = 0.2f;
|
||||
[SerializeField] private float completionClipEdgePadding = 0.35f;
|
||||
[Tooltip("屏幕内容的最小安全边距;最终边距还会根据字形、光晕、圆环和晃动幅度动态增大。")]
|
||||
[SerializeField, Min(0f)] private float minimumScreenMargin = 0.12f;
|
||||
[SerializeField, Min(0f)] private float minimumScreenMargin = 0.2f;
|
||||
[Tooltip("将目标粒子拉回屏幕裁剪区时的平滑时间(越大越柔和,略增加拖尾感)")]
|
||||
[SerializeField, Range(0.02f, 0.55f)] private float completionPositionSmoothTime = 0.2f;
|
||||
|
||||
@@ -1051,24 +1051,30 @@ namespace AibisDream.MiniGame.Language
|
||||
{
|
||||
float padding = Mathf.Max(minimumScreenMargin, completionClipEdgePadding);
|
||||
float glyphExtent = 0f;
|
||||
float maxScale = 1f;
|
||||
|
||||
foreach (CandidateParticle particle in targetParticles)
|
||||
{
|
||||
if (particle == null)
|
||||
continue;
|
||||
|
||||
maxScale = Mathf.Max(maxScale, particle.transform.localScale.x, particle.transform.localScale.y);
|
||||
|
||||
if (particle.textMesh != null && particle.textMesh.renderer != null)
|
||||
{
|
||||
Bounds textBounds = particle.textMesh.renderer.bounds;
|
||||
glyphExtent = Mathf.Max(glyphExtent, textBounds.extents.x, textBounds.extents.y);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
float zoomedGlyph = glyphExtent * Mathf.Max(1f, focusZoomScale);
|
||||
float shakeExtent = Mathf.Max(shuffleDistance, nonTargetShakeIntensity, completionPositionSmoothTime * 0.1f);
|
||||
// renderer.bounds 已含当前缩放;未放大到 focusZoom 时再预留缩放余量,避免重复乘 zoom
|
||||
float resolvedGlyph = maxScale >= focusZoomScale * 0.9f
|
||||
? glyphExtent
|
||||
: glyphExtent * Mathf.Max(1f, focusZoomScale);
|
||||
// 抖动/漂浮是局部偏移,硬钳制根节点后仍可能露出字形一角,留一点余量即可
|
||||
float floatAllowance = Mathf.Max(0.04f, focusInterferenceShakeAmplitude * 0.35f);
|
||||
|
||||
float horizontal = Mathf.Max(padding, zoomedGlyph, shakeExtent);
|
||||
float horizontal = padding + resolvedGlyph + floatAllowance;
|
||||
return new Vector2(horizontal, horizontal);
|
||||
}
|
||||
|
||||
@@ -1635,8 +1641,10 @@ namespace AibisDream.MiniGame.Language
|
||||
Mathf.Lerp(1f, 0.12f, gather);
|
||||
Vector3 edgeJitter = CalculateLieEdgeJitter(visual, compression);
|
||||
visual.scatterOffset = Vector3.Lerp(visual.scatterOffset, Vector3.zero, Time.deltaTime * 5.5f);
|
||||
visual.particle.transform.position =
|
||||
compressedPosition + shuffleOffset + edgeJitter + visual.scatterOffset;
|
||||
// 硬钳制:shuffle/jitter 会顶出裁剪区,仅靠 LateUpdate SmoothDamp 追不上,字会贴边甚至出屏
|
||||
visual.particle.transform.position = ClampPositionToBounds(
|
||||
compressedPosition + shuffleOffset + edgeJitter + visual.scatterOffset,
|
||||
GetCompletionClipBounds());
|
||||
|
||||
// 锁字判定用原始进度:target=0.92 时阈值 0.95 的最后一个字永远锁不住
|
||||
UpdateTruthGatherLock(visual, truthGatherProgress, visualCount);
|
||||
@@ -1843,7 +1851,9 @@ namespace AibisDream.MiniGame.Language
|
||||
Vector3 dynamicTarget = GetDynamicArrangementTarget(visual, arrangementProgress, localTime);
|
||||
Vector3 targetPosition = Vector3.Lerp(visual.focusPosition, dynamicTarget, Mathf.SmoothStep(0f, 1f, arrangementProgress));
|
||||
Vector3 shuffleOffset = CalculateShuffleOffset(visual, arrangementProgress, localTime);
|
||||
visual.particle.transform.position = targetPosition + shuffleOffset;
|
||||
visual.particle.transform.position = ClampPositionToBounds(
|
||||
targetPosition + shuffleOffset,
|
||||
GetCompletionClipBounds());
|
||||
|
||||
if (!visual.stabilized && probabilityProgress >= 1f)
|
||||
{
|
||||
|
||||
@@ -25,10 +25,10 @@ namespace AibisDream.MiniGame.HuoShan
|
||||
[SerializeField] private float innerRadius = 1.5f;
|
||||
|
||||
[Tooltip("滑片滑动弧度范围(度)")]
|
||||
[SerializeField] private float slideAngleRange = 330f;
|
||||
[SerializeField] private float slideAngleRange = 340.8f;
|
||||
|
||||
[Tooltip("滑片起始角度偏移(度);270=正上方起点")]
|
||||
[SerializeField] private float startAngleOffset = 270f;
|
||||
[Tooltip("滑片起始角度偏移(度);必须与进入步进模式动画结束时滑片停的位置一致,否则接管控制时会跳位")]
|
||||
[SerializeField] private float startAngleOffset = 259.6f;
|
||||
|
||||
[Header("滑片配置")]
|
||||
[Tooltip("滑片Transform")]
|
||||
|
||||
@@ -119,6 +119,7 @@ namespace AibisDream
|
||||
|
||||
/// <summary>
|
||||
/// 换目标时的失焦:只做效果,不眨眼(眨眼仅在想象上色 FadeIn)。
|
||||
/// CanImagineColor 下若颜色已是失焦态,仍需补 BlurIn,否则未上色过的目标会一直保持清晰。
|
||||
/// </summary>
|
||||
private void ApplyUnfocusedEffectSilent(EyeTarget target)
|
||||
{
|
||||
@@ -130,6 +131,7 @@ namespace AibisDream
|
||||
if (_currentState == EyeColorState.CanImagineColor
|
||||
&& target.IsAtUnfocusedColorState(visualSettings))
|
||||
{
|
||||
target.BlurIn(GetEffectTransitionDuration());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user