using System; using System.Collections; using System.Reflection; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif namespace Colosseum.Player { /// /// 아군 타게팅 시스템의 시각적 데모 + 설정 검증. /// BalanceDummy 씬에서 TrainingDummy를 임시 아군으로 만들고, /// 인디케이터 프리팹 표시 → 치유 스킬 투사체 발사를 실제로 보여줍니다. /// public class AllyTargetingDebugTest : MonoBehaviour { [Header("테스트 설정")] [Tooltip("가짜 아군으로 사용할 GameObject 이름")] [SerializeField] private string allyTargetName = "TrainingDummy"; [Tooltip("치유 스킬 에셋 경로")] [SerializeField] private string healSkillPath = "Assets/_Game/Data/Skills/Data_Skill_Player_치유.asset"; [Tooltip("보호막 스킬 에셋 경로")] [SerializeField] private string shieldSkillPath = "Assets/_Game/Data/Skills/Data_Skill_Player_보호막.asset"; [Tooltip("인디케이터 높이 오프셋")] [Min(0f)] [SerializeField] private float indicatorHeight = 2.2f; [Tooltip("시작 지연 (초)")] [Min(0.5f)] [SerializeField] private float startDelay = 2f; // 복원용 private TeamType originalTeamType; private GameObject spawnedIndicator; private GameObject allyObject; private void Start() { Debug.Log("═══════════════════════════════════════════════════"); Debug.Log("[AllyTargetDemo] 아군 타게팅 시각적 데모 시작"); Debug.Log("═══════════════════════════════════════════════════"); StartCoroutine(RunDemo()); } private void OnDestroy() { // 플레이 종료 시 복원 if (allyObject != null) { RestoreTeam(); DestroyIndicator(); } } private IEnumerator RunDemo() { yield return new WaitForSeconds(startDelay); var player = FindPlayer(); if (player == null) { Debug.LogError("[AllyTargetDemo] 플레이어를 찾을 수 없습니다."); EndDemo(); yield break; } allyObject = GameObject.Find(allyTargetName); if (allyObject == null) { Debug.LogError($"[AllyTargetDemo] '{allyTargetName}'을(를) 찾을 수 없습니다."); EndDemo(); yield break; } // ── 1. TrainingDummy 팀을 임시 Player로 변경 ── var allyTeam = allyObject.GetComponent(); if (allyTeam == null) { Debug.LogError($"[AllyTargetDemo] {allyTargetName}에 Team 컴포넌트가 없습니다."); EndDemo(); yield break; } originalTeamType = allyTeam.TeamType; SetTeamType(allyTeam, TeamType.Player); Debug.Log($"[AllyTargetDemo] {allyTargetName} 팀 변경: {originalTeamType} → Player"); // 거리 로그 float dist = Vector3.Distance(player.transform.position, allyObject.transform.position); Debug.Log($"[AllyTargetDemo] 플레이어 ↔ 아군 거리: {dist:F1}m"); // ── 2. 인디케이터 프리팹 표시 (초록색) ── yield return ShowIndicator(player, allyObject); // ── 3. 2초 대기 (인디케이터 관찰 시간) ── Debug.Log("[AllyTargetDemo] ▶ 인디케이터 표시 중... 2초 대기"); yield return new WaitForSeconds(2f); // ── 4. 인디케이터 색상 빨간색으로 변경 (거리 초과 시뮬레이션) ── yield return ChangeIndicatorColor(new Color(1f, 0.3f, 0.3f, 0.8f)); Debug.Log("[AllyTargetDemo] ▶ 인디케이터 빨간색으로 변경 (거리 초과 시뮬) — 2초 대기"); yield return new WaitForSeconds(2f); // ── 5. 인디케이터 제거 후 잠시 대기 ── DestroyIndicator(); Debug.Log("[AllyTargetDemo] ▶ 인디케이터 제거"); yield return new WaitForSeconds(1f); // ── 6. 치유 스킬 실행 (투사체 발사) ── Debug.Log("[AllyTargetDemo] ▶ 치유 스킬 투사체 발사..."); yield return ExecuteSkillVisual(player, allyObject, healSkillPath, "치유"); yield return new WaitForSeconds(3f); // ── 7. 보호막 스킬 실행 (투사체 발사) ── Debug.Log("[AllyTargetDemo] ▶ 보호막 스킬 투사체 발사..."); yield return ExecuteSkillVisual(player, allyObject, shieldSkillPath, "보호막"); yield return new WaitForSeconds(3f); // ── 8. 인디케이터 다시 표시 (복원 데모) ── yield return ShowIndicator(player, allyObject); Debug.Log("[AllyTargetDemo] ▶ 인디케이터 최종 표시 — 3초 후 종료"); yield return new WaitForSeconds(3f); // ── 9. 정리 ── DestroyIndicator(); RestoreTeam(); Debug.Log("[AllyTargetDemo] 팀 복원 완료"); Debug.Log("═══════════════════════════════════════════════════"); Debug.Log("[AllyTargetDemo] 데모 완료"); Debug.Log("═══════════════════════════════════════════════════"); EndDemo(); } #region 시각적 데모 단계 private IEnumerator ShowIndicator(GameObject player, GameObject ally) { // 플레이어의 AllyTargetIndicator에서 프리팹 참조 가져오기 var indicator = player.GetComponent(); if (indicator == null) { Debug.LogError("[AllyTargetDemo] AllyTargetIndicator 컴포넌트가 없습니다."); yield break; } var prefabField = typeof(UI.AllyTargetIndicator).GetField("indicatorPrefab", BindingFlags.NonPublic | BindingFlags.Instance); if (prefabField == null) { Debug.LogError("[AllyTargetDemo] indicatorPrefab 필드 접근 실패."); yield break; } var prefab = prefabField.GetValue(indicator) as GameObject; if (prefab == null) { Debug.LogError("[AllyTargetDemo] indicatorPrefab이 null입니다."); yield break; } // 아군 머리 위에 인스턴스화 Vector3 pos = ally.transform.position; pos.y += indicatorHeight; spawnedIndicator = Instantiate(prefab, pos, Quaternion.Euler(90f, 0f, 0f)); // 초록색으로 설정 var renderer = spawnedIndicator.GetComponent(); if (renderer != null) { renderer.material.color = new Color(0.2f, 1f, 0.2f, 0.8f); } Debug.Log($"[AllyTargetDemo] 인디케이터 표시: {prefab.name} @ {ally.name} (y+{indicatorHeight})"); yield return null; } private IEnumerator ChangeIndicatorColor(Color color) { if (spawnedIndicator == null) yield break; var renderer = spawnedIndicator.GetComponent(); if (renderer != null) { renderer.material.color = color; Debug.Log($"[AllyTargetDemo] 인디케이터 색상 변경: ({color.r:F1}, {color.g:F1}, {color.b:F1}, {color.a:F1})"); } yield return null; } private IEnumerator ExecuteSkillVisual(GameObject player, GameObject ally, string skillPath, string skillLabel) { #if UNITY_EDITOR var skillData = AssetDatabase.LoadAssetAtPath(skillPath); if (skillData == null) { Debug.LogError($"[AllyTargetDemo] 스킬 로드 실패: {skillPath}"); yield break; } var entry = Skills.SkillLoadoutEntry.CreateTemporary(skillData); bool hasSingleAlly = entry.HasEffectWithTargetType(Skills.TargetType.SingleAlly); Debug.Log($"[AllyTargetDemo] {skillLabel}: SingleAlly 효과 있음={hasSingleAlly}"); var skillController = player.GetComponent(); if (skillController == null) { Debug.LogError("[AllyTargetDemo] SkillController가 없습니다."); yield break; } if (skillController.IsExecutingSkill) { Debug.LogWarning($"[AllyTargetDemo] 스킬 실행 중 — 대기"); yield return new WaitUntil(() => !skillController.IsExecutingSkill); } // 플레이어를 아군 방향으로 회전 Vector3 direction = (ally.transform.position - player.transform.position); direction.y = 0; if (direction.sqrMagnitude > 0.001f) { player.transform.rotation = Quaternion.LookRotation(direction); } Debug.Log($"[AllyTargetDemo] {skillLabel} 실행 → 타겟: {ally.name}"); bool success = skillController.ExecuteSkill(entry, ally); if (success) Debug.Log($"[AllyTargetDemo] {skillLabel} 스킬 발동 성공 — 투사체 확인!"); else Debug.LogError($"(); return controllers.Length > 0 ? controllers[0].gameObject : null; } private static void SetTeamType(Team team, TeamType type) { var field = typeof(Team).GetField("teamType", BindingFlags.NonPublic | BindingFlags.Instance); field?.SetValue(team, type); } private void RestoreTeam() { if (allyObject == null) return; var allyTeam = allyObject.GetComponent(); if (allyTeam != null) { SetTeamType(allyTeam, originalTeamType); Debug.Log($"[AllyTargetDemo] 팀 복원: {allyObject.name} → {originalTeamType}"); } } private void DestroyIndicator() { if (spawnedIndicator != null) { Destroy(spawnedIndicator); spawnedIndicator = null; } } private static void EndDemo() { #if UNITY_EDITOR EditorApplication.isPlaying = false; #endif } #endregion } }