fix(tarot): 塔罗逆位用本地 Z 旋转避免镜像闪变

Made-with: Cursor
This commit is contained in:
2026-04-15 19:10:04 +08:00
parent 6319ba4d92
commit c0b658fee0
+26 -12
View File
@@ -66,6 +66,7 @@ namespace AibisDream.MiniGame.Tarot
IsFaceUp = false;
Orientation = TarotOrientation.Normal;
transform.localScale = Vector3.one;
transform.localRotation = Quaternion.identity;
}
private void Awake()
@@ -149,7 +150,7 @@ namespace AibisDream.MiniGame.Tarot
/// <summary>
/// Flip the card to reveal front side with a target orientation.
/// X-scale: 1 -> 0 (swap sprite) -> 1, then apply orientation via Y-scale.
/// X-scale: 1 -> 0 (swap sprite) -> 1, then apply orientation via local Z rotation (0° / 180°).
/// </summary>
public IEnumerator Flip(TarotOrientation targetOrientation, float duration = 0.5f)
{
@@ -169,10 +170,7 @@ namespace AibisDream.MiniGame.Tarot
else if (IsFaceUp)
Debug.LogWarning("[TarotCard] Front Sprite 未设置,翻牌后无法显示正面。", this);
Orientation = targetOrientation;
var s = transform.localScale;
s.y = Mathf.Abs(s.y) * (targetOrientation == TarotOrientation.Inverted ? -1f : 1f);
transform.localScale = s;
ApplyOrientationToTransform(targetOrientation);
});
seq.Append(transform.DOScaleX(scale.x, half).SetEase(Ease.OutQuad));
@@ -181,7 +179,7 @@ namespace AibisDream.MiniGame.Tarot
/// <summary>
/// Change orientation of an already face-up card (rotate 180 degrees around local Z).
/// After animation completes, resets rotation to identity and applies Y-scale for the new state.
/// 结束后与翻牌一致:用本地 Z 旋转表示逆位,避免动画末尾用负 scale.y 与 Rz(180°) 不等价造成镜像闪变。
/// </summary>
public IEnumerator SetOrientationAnimated(TarotOrientation targetOrientation, float duration = 0.4f)
{
@@ -190,6 +188,9 @@ namespace AibisDream.MiniGame.Tarot
_flipTween?.Kill();
_orientationTween?.Kill();
// 旧版用负 scale.y 表示逆位时,收束为绕本地 Z 再转 180°,避免与后续 Rz 动画叠加错乱
EnsureOrientationUsesRotationNotNegativeScale();
// 使用本地旋转,避免 DORotate(世界欧拉)与 localEulerAngles 混用导致几乎不转或乱跳
var endLocal = transform.localRotation * Quaternion.Euler(0f, 0f, 180f);
_orientationTween = transform.DOLocalRotateQuaternion(endLocal, duration)
@@ -198,21 +199,34 @@ namespace AibisDream.MiniGame.Tarot
yield return _orientationTween.WaitForCompletion();
_orientationTween = null;
Orientation = targetOrientation;
transform.localRotation = Quaternion.identity;
var s = transform.localScale;
s.y = Mathf.Abs(s.y) * (targetOrientation == TarotOrientation.Inverted ? -1f : 1f);
transform.localScale = s;
ApplyOrientationToTransform(targetOrientation);
}
public void SetOrientationImmediate(TarotOrientation orientation)
{
ApplyOrientationToTransform(orientation);
}
/// <summary>正立/逆位统一用本地 Z0° / 180°),scale.y 恒为正。</summary>
private void ApplyOrientationToTransform(TarotOrientation orientation)
{
Orientation = orientation;
transform.localRotation = Quaternion.Euler(0f, 0f, orientation == TarotOrientation.Inverted ? 180f : 0f);
var s = transform.localScale;
s.y = Mathf.Abs(s.y) * (orientation == TarotOrientation.Inverted ? -1f : 1f);
s.y = Mathf.Abs(s.y);
transform.localScale = s;
}
/// <summary>仅处理旧版负 scale.y:改为正 scale 并在本地绕 Z 补 180°,不覆盖扇形等已有 localRotation。</summary>
private void EnsureOrientationUsesRotationNotNegativeScale()
{
var s = transform.localScale;
if (s.y >= 0f) return;
s.y = Mathf.Abs(s.y);
transform.localScale = s;
transform.localRotation = transform.localRotation * Quaternion.Euler(0f, 0f, 180f);
}
public void SetAlpha(float alpha)
{
if (_spriteRenderer == null) _spriteRenderer = GetComponent<SpriteRenderer>();