diff --git a/Assets/Scripts/Runtime/ActionResolver.cs b/Assets/Scripts/Runtime/ActionResolver.cs
index d7aa20cc..cef5232a 100644
--- a/Assets/Scripts/Runtime/ActionResolver.cs
+++ b/Assets/Scripts/Runtime/ActionResolver.cs
@@ -54,6 +54,8 @@ namespace TKS
if (dist < 0.001f || !u.IsAlive) yield break;
Vector2 dir = delta / dist;
+ // 슬링샷 돌진 중 = 병종 돌진 포즈 1프레임 고정 · 끝나면 대기 (PD 2026-11-05 #1084)
+ if (u.View != null) u.View.SetCharging(true);
switch (u.Type)
{
case UnitType.Infantry:
@@ -69,6 +71,7 @@ namespace TKS
yield return ArcherRoutine(u, origin, dir, dist, target, moveOnly, o);
break;
}
+ if (u.View != null) u.View.SetCharging(false);
}
// ---------- 미리보기(드라이런) ----------
diff --git a/Assets/Scripts/Runtime/UnitView.cs b/Assets/Scripts/Runtime/UnitView.cs
index 362cbd9c..0032c8e8 100644
--- a/Assets/Scripts/Runtime/UnitView.cs
+++ b/Assets/Scripts/Runtime/UnitView.cs
@@ -33,6 +33,7 @@ namespace TKS
Color baseColor;
Coroutine flash;
bool aiming;
+ bool charging; // 슬링샷 돌진(이동) 중 = 돌진 포즈 고정
bool facingBack; // 위를 봄(뒷모습 back_* 세트) · false = 아래를 봄(앞모습 front_*)
bool facingLeft; // 왼쪽을 봄(좌우 반전) · false = 오른쪽(기본)
const float FacingEps = 0.05f;
@@ -88,7 +89,8 @@ namespace TKS
string cur = anim.Current ?? "";
string suffix = cur.StartsWith("back_") ? cur.Substring(5) : (cur.StartsWith("front_") ? cur.Substring(6) : "idle");
anim.SetIdle(ClipName("idle"));
- if (suffix == "idle") anim.PlayIdle();
+ if (charging) anim.Play(ClipName("action"), true);
+ else if (suffix == "idle") anim.PlayIdle();
else if (suffix == "ready") anim.Play(ClipName("ready"), true);
else if (suffix == "victory") anim.Play(ClipName("victory"), false);
else anim.Play(ClipName(suffix), false, AttackHold, true);
@@ -200,19 +202,34 @@ namespace TKS
if (highlightRing != null) highlightRing.enabled = on;
}
- /// 조준(당기는) 중 = 준비 자세 · 끝나면 대기.
+ /// 조준(당기는) 중 = 출발 자세(ready · 1프레임) · 끝나면 대기 (PD 2026-11-05 #1084).
public void SetAiming(bool on)
{
if (anim == null || aiming == on) return;
aiming = on;
if (on) anim.Play(ClipName("ready"), true);
- else anim.PlayIdle();
+ else if (!charging) anim.PlayIdle();
}
- /// 공격 자세(1 프레임) 잠깐 → 대기.
+ /// 슬링샷 돌진(이동) 중 = 병종 돌진 포즈(action · 1프레임 고정) · 멈추면 대기 (PD 2026-11-05 #1084).
+ public void SetCharging(bool on)
+ {
+ if (anim == null || charging == on) return;
+ charging = on;
+ aiming = false;
+ if (on) anim.Play(ClipName("action"), true);
+ else if (unit != null && unit.IsAlive) anim.PlayIdle();
+ }
+
+ public bool Charging
+ {
+ get { return charging; }
+ }
+
+ /// 공격 자세(1 프레임) 잠깐 → 대기. 돌진 중이면 이미 돌진 포즈라 그대로 둔다.
public void PlayAttack()
{
- if (anim == null || !isActiveAndEnabled) return;
+ if (anim == null || !isActiveAndEnabled || charging) return;
aiming = false;
anim.Play(ClipName("action"), false, AttackHold, true);
}
@@ -237,7 +254,7 @@ namespace TKS
if (anim != null)
{
anim.Renderer.color = ArtHitTint;
- if (unit.IsAlive) anim.Play(ClipName("damage"), false, HitHold, true);
+ if (unit.IsAlive && !charging) anim.Play(ClipName("damage"), false, HitHold, true); // 돌진 중 피격은 색만(포즈 유지)
}
else
{
diff --git a/Assets/Tests/PlayMode/BattleFlowTests.cs b/Assets/Tests/PlayMode/BattleFlowTests.cs
index ead23498..0f39a260 100644
--- a/Assets/Tests/PlayMode/BattleFlowTests.cs
+++ b/Assets/Tests/PlayMode/BattleFlowTests.cs
@@ -475,6 +475,21 @@ namespace TKS.Tests
rigged.View.PlayAttack();
Assert.AreEqual("back_action", rigged.View.Anim.Current, "공격 자세 클립");
+ // PD 2026-11-05 #1084: 조준 중 = 출발 자세(ready) · 돌진 중 = 돌진 포즈(action 고정) · 멈추면 대기
+ rigged.View.SetAiming(true);
+ Assert.AreEqual("back_ready", rigged.View.Anim.Current, "조준(당기는) 중 = 출발 자세");
+ rigged.View.SetAiming(false);
+ rigged.View.SetCharging(true);
+ Assert.AreEqual("back_action", rigged.View.Anim.Current, "돌진 중 = 병종 돌진 포즈");
+ rigged.View.OnHit();
+ Assert.AreEqual("back_action", rigged.View.Anim.Current, "돌진 중 피격은 포즈 유지");
+ rigged.View.SetCharging(false);
+ Assert.AreEqual("back_idle", rigged.View.Anim.Current, "멈추면 대기");
+ var o2 = new ActionOutcome();
+ yield return bm.ResolveForTest(rigged, rigged.Position + new Vector2(0f, 2f), false, o2);
+ Assert.IsFalse(rigged.View.Charging, "슬링샷이 끝나면 돌진 포즈 해제");
+ Assert.AreEqual("back_idle", rigged.View.Anim.Current);
+
// 원화 세션 1차 납품(2026-11-04): 황건적 5종 정지 그림(front_idle 1장) + 전장 배경
int enemyArt = 0;
foreach (var e in bm.AliveUnits(Faction.Enemy))