오늘 해야할 일이 굉장히 많다
팀원들이 각자 개발한 것들의 자잘한 에러들을 다 해결하고 나면
나는 멀티 플레이 -> HP 바 연동
그냥 격투 모드 들어갔을 때 다 연동되는 거 구현해야하고
그전에 우선 room씬에라도 제대로 두명의 플레이어가 입장되게 해야하는데 지금 그부분이 자꾸 안된다..
1. 플레이어 공격 -> UI 연동
우선 팀원이 플레이어 공격 로직이 구현 완료되었다 하니
이제 플레이어가 AI를 공격하면 AI의 체력게이지가 줄어드는 것을 추가해주어야 한다.
근데 여기서 위기를 느낀 점은..!
플레이어도 DDOL로 갖고오고, AI마저도 Instantiate로 생성되는 것이었다.

AI 프리팹이 총 2개인데
플레이어를 따라다니며 때리는 Fight 프리팹과
그냥 오목 게임시 앉아만 있는 Omok 프리팹이 있다.
처음에는 Omok 프리팹을 씬에 배치해두었다가
격투 모드가 시작되면 Fight 프리팹이 씬에 생성되는 로직으로 구현되어 있었다.

즉 하나의 UI에는 캐릭터를 연결
다른 UI는 AI를 연결 시켜야하는데
이 오목게임을 하는 씬에는 두 오브젝트가 하이어라키에 배치되어있지 않다는 점을 고려해야했다.
그리고 멀티플레이까지 고려하면 단순히 Player / AI 태그로 갖고와서 연결시킬 수도 없었다..!
void Unbind() // 구독 대상이 존재할 경우 구독 제거
{
if (bound != null)
{
bound.onHealthChanged -= OnHealthChanged;
bound = null;
}
}
void Bind(DummyPlayerHealth_UI hp)
{
if (!hp) return;
if (bound == hp) return;
Unbind();
// 초기값 반영 (현재 체력/최대체력으로 게이지 맞춤)
bound = hp;
bound.onHealthChanged += OnHealthChanged;
// 체력 변경
OnHealthChanged(bound.currentHP, bound.maxHP);
}
// UI와 캐릭터 연결
// 캐릭터가 Instatiacte, DontDestoryOnLoad로 생성되어서 잠시 대기 기능도 추가
void TryBindOrQueue()
{
if (TryBindNow()) return;
if (waitCo != null) StopCoroutine(waitCo);
waitCo = StartCoroutine(CoWaitAndBind());
}
bool TryBindNow()
{
// 로컬 플레이어
var localRoot = PlayerLocator.GetLocalPlayer(); // 씬 넘어가도 유지되는 내 플레이어
if (bindMode == BindMode.LocalPlayer)
{
var hpLocal = localRoot ? localRoot.GetComponent<DummyPlayerHealth_UI>() : null;
if (hpLocal) { Bind(hpLocal); return true; }
return false;
}
// 상대 플레이어
if (bindMode == BindMode.Opponent)
{
// 씬에 존재하는 모든 HP 컴포넌트 중에서 "로컬이 아닌" 쪽을 선택
var all = Object.FindObjectsByType<DummyPlayerHealth_UI>(FindObjectsInactive.Include,
FindObjectsSortMode.None);
var myHp = localRoot ? localRoot.GetComponent<DummyPlayerHealth_UI>() : null;
var opp = all.FirstOrDefault(hp => hp != null && hp != myHp);
if (opp) { Bind(opp); return true; }
return false;
}
return false;
}

ExplicitTarget, LocalPlayer, Opponent 세가지의 enum값을 생성해서
타입별로 로컬 플레이어 / 상대 플레이어를 구분해주기로 하였다.
플레이어 HP UI에는 BindMode.LocalPlayer를 설정하고
AI HP UI에는 BindMode.Opponent를 설정해주어서 자동으로 서로 다른 대상을 찾도록 해주는 것이다!
Opponent 모드에서는 FindObjectsByType<DummyPlayerHealth_UI>로 씬의 모든 체력 컴포넌트를 찾은 뒤
그중 내(LocalPlayer)의 체력 컴포넌트가 아닌 것을 골라내어 상대방으로 인식하도록 했다.
이렇게 하면 Omok 프리팹이든 Fight 프리팹이든 결국 DummyPlayerHealth_UI가 붙어 있는 객체라면 자동으로 연결된다.

싱글플레이에서는 이렇게 내 HP / AI HP만 구분해주면 되었지만
멀티플레이에서는 씬 안에 같은 컴포넌트가 여러개 존재할 수 있다.
기존에 구현해둔 PlayerLocator.GetLocalPlayer()는 내 캐릭터만 보장해주므로 LocalPlayer 모드에는 안전하다.
그렇지만 Opponent 모드에서는 단순히 “내가 아닌 첫 번째 컴포넌트”를 잡기 때문에
멀티플레이 인원 수가 늘어나면 정확히 누구를 Opponent로 매핑할지 찾을 수 없다..
그래서 멀티플레이를 구현할 때에는 여기서 IsMine 이나 Player ID를 기준으로 Opponent를 찾아주는 로직 구현이 필요하다.

아니 근데 포톤이 자꾸 서버를 찾을 수 없다고한다 미칠지경
근데 여기서 더 큰일난게 팀원들이 각자 개발한거 통합하는 과정에서 에러가 끝도없이 계속 생기고 있었다! ㅋㅋㅋ
그래서 결국 우리팀은 멀티 구현은 포기하기로 했고.. 나는 버그 고치는 거에 투입되기로..~~
2. 버그 해결
1. 복싱 끝 -> 오목 룸 이동
내가 씨네머신 연출로 벽이 무너지는 애니메이션을 넣었다보니
복싱이 끝나고 다시 오목 게임방으로 이동되었을 때 벽이 계속 무너져있는 문제가 있었다.
public void ResetWallsAnim() // 벽 되돌리기
{
// GameRoom을 활성화 해도 천장이나 게시판같은건 비활성화 상태길래 켜주었습니다.
if (top) top.SetActive(true); // 천장 복구
if (guide) guide.SetActive(true); // 게시판 복구
if (Wallobject) Wallobject.SetActive(true); // 조명 복구
if (basicWalls != null) foreach (var b in basicWalls) if (b) b.SetActive(true); // 벽 복구
// 각 벽 애니메이션 역재생
foreach (var wall in walls)
{
if (!wall) continue;
wall.SetActive(true);
var anim = wall.GetComponent<Animator>();
if (!anim) continue;
anim.ResetTrigger("Fall");
anim.speed = -1f; // 역재생
anim.Play("wall fall over", 0, 1f); // 애니메이터 상태 이름 기준으로 돌아오도록
anim.Update(0f); // 즉시 반영하도록
StartCoroutine(HoldAtStart(anim));
}
}
애니메이션을 역재생시키는 방법을 고안해서 이렇게 벽 원상복귀 메서드를 추가해주었다!
그리고 팀원분이 작성한 매니저 스크립트에 적절한 곳에 해당 함수를 불러오도록 해주었다

그런데 참놔 ㅋ 벽은 다시 생기면서 애니메이션은 동작 안하는 문제 발생
이 오브젝트들을 활성화 시킴과 동시에 애니메이션 동작을 수행하는데
활성화 되기도 전에 애니메이션 동작을 실행시키니까 작동을 안하는 것 같았다.
private IEnumerator HoldAtStart(Animator anim) // 프레임 대기를 안 넣어주면 안돌아와서..
{
if (!anim) yield break;
anim.speed = 0f; // 정지
anim.Play("wall fall over", 0, 0f); // 0프레임 고정(Idle 없을 때 대체)
}
그래서 이것도 프레임 대기를 해주어서 해결했다..!
프레임 대기가 정말 안 좋은 걸로 알고있는데.. 우선 기능이 제대로 돌아가야하니까 ㅠ.. 급하게 짱구를 돌렸다.. ^0^...
그리고 캐릭터 위치 초기화가 안되는 문제가 있었는데
이건! 내가 여태 계속 짱나했던 DDOL로 불러오기때문에 캐릭터를 제자리로 이동시키는 스크립트가 이 캐릭터를 못찾는 것 같았다.
그래서 그냥 전에 만들어둔 PlayerLocator()함수 써서 해결해주었다!
'Unity > 멋쟁이사자처럼 부트캠프' 카테고리의 다른 글
| [멋쟁이사자처럼부트캠프] 유니티 게임 개발 5기(87일차) - Omok AI (0) | 2025.09.23 |
|---|---|
| [멋쟁이사자처럼부트캠프] 유니티 게임 개발 5기(86일차) - [팀플] 1차 프로젝트 마무리 & 1등!! ⭐ (2) | 2025.09.22 |
| [멋쟁이사자처럼부트캠프] 유니티 게임 개발 5기(84일차) - [팀플] HP Bar 연동 및 멀티 구현 (1) (0) | 2025.09.18 |
| [멋쟁이사자처럼부트캠프] 유니티 게임 개발 5기(83일차) - [팀플] Scene BootStrap 구현 및 타임라인 설정 (0) | 2025.09.17 |
| [멋쟁이사자처럼부트캠프] 유니티 게임 개발 5기(82일차) - [팀플] 바둑알 효과 추가 및 씨네머신 활용 (0) | 2025.09.16 |