Carrot
본문 바로가기
Unity/멋쟁이사자처럼 부트캠프

[멋쟁이사자처럼부트캠프] 유니티 게임 개발 5기(109일차/Final Project) - 에셋 적용 & 스포너 로직 수정

by 독기품은토끼 2025. 11. 3.
✅ 오늘의 백로그
1. 복숭아가지 에셋 적용
2. 스폰매니저 멀티 연동

1. 복숭아가지 에셋 적용

기존에 에셋이 아직 구매되지 않아서 Cube로 만들어놓은 복숭아가지 모델을 수정해야한다.

 

 

Ultimate Stick & Branches Package / 30 Variations | 3D 소품 | Unity Asset Store

Elevate your workflow with the Ultimate Stick & Branches Package / 30 Variations asset from PackDev. Find this & other 소품 options on the Unity Asset Store.

assetstore.unity.com

 

 

Flower Malaysia | 3D 꽃 | Unity Asset Store

Elevate your workflow with the Flower Malaysia asset from VuStudios. Find this & other 꽃 options on the Unity Asset Store.

assetstore.unity.com

 

복숭아가지 본체는 stick 에셋을 활용해줄 거고

약간의 꾸밈을 위해 꽃잎도 넣어줄 것이다.

 

 

꽃잎 에셋의 피봇 위치가 이상해서.. 인스펙터 창에서 Transform 위치를 조절하면 자꾸 원하지 않는 곳으로 이동이 되어버리는 바람에 수동으로 위치 조정을 해주었다.

그리고 나뭇가지에 비해 사이즈가 너무 커서 사이즈를 조절해주려고 했는데

예전 최적화 강의에서 Scale 값을 변경하기 보다는 모델의 자체 사이즈를 줄이는 게 좋다 말씀해주셔서

모델 자체의 스케일값을 변경하려고 봤는데..

이미 프리팹으로 만들어지 에셋이고 모델이 따로 없어서 결국 Scale값을 조절해주었다.

 

 

그리고 이제 플레이어가 제대로 아이템을 줍는지 테스트를 해보았는데

에셋이 손 위치에서 좀 벗어나는 문제가 있었다.

이부분은 팀원분께서 해결해주신다 하셨고 나는 모델만 분리해서 푸쉬하였다!

 


 

이제 에셋을 적용해봤으니 제대로 테스트 되는지 확인해봐야 하는데

최근에 팀원분께서 귀신 스폰 로직을 조금 변경하셨더니

맵에 귀신이 스폰되지 않는다.. 원인을 좀 찾아보고 테스트 해봐야겠다.

원래는 됐던건데 에셋만 바꿨다고 안되진 않을테니까 일단 급한거부터 고!!!

 

2. 스포너 로직 수정

1. 우선순위 - 하

어제 팀원분과 이야기하면서 문제점을 발견한 게 있었다.

 

Q: 게임을 시작하자마자 오브젝트풀이 작동되는데 이게 맞나요?

내가 생각했을 때에는

지금 로직이 게임 시작하자마자 이상현상을 맵에 스폰하고 있고

스폰된 이상현상은 바로 오브젝트 풀을 불러오는 스크립트가 컴포넌트로 추가되어 있어서 생긴 문제인 것 같다.

 

그래서 스폰 주기를 좀 늦춰주어야겠다고 판단했다.

생각해보면 게임을 시작하자마자 이상현상이 나타나기보단 중간에 나타나는 게 더 무서울 것 같다!

 

IEnumerator SpawnDelay()
{
    float delay = Random.Range(5f, 10f); // 추후 5분~10분으로 변경 예정
    yield return new WaitForSeconds(delay);

    // TODO : 난이도에 따라 바로 스폰하도록 하는 로직도 필요할 것 같음
}

 

우선 이렇게 코루틴을 만들었는데..

제대로 동작되지 않는다... 딜레이를 안한다.

 

 

우선 테스트하다가

천우인이 거꾸로 떨어지고 있길래 이부분 수정해줬고

 

 

맵 안에 스폰되는 놈은 왜 거꾸로 스폰되는지 아직 원인을 잘 모르겠다 ㅋ

모델링 자체가 거꾸로 되어있어서 그런 것 같긴한데ㅜ

pos값을 건들게되면 다른 이상현상들도 90도 회전될텐데 ㅎㅋ;;; 큰일이다 모델링 수정할 여유가 생기면 고쳐줘야겠다..

 

우선 모든 우선순위는 이게 아니야~!!! 이건 나중에 버그 고칠때 하면되고

당장 멀티 부분을 손봐줘야 다른분들이 작업을 하실 수 있기에 그거부터 해주기로 한다.

 

2. 우선순위 - 상

Q : 스폰 했을 때 동기화 작업이 이루어지지 않습니다!

Q : 오브젝트풀도 동기화되지 않습니다!

A : 네!! 아직 멀티 구현이 하나도 안되어있습니돠!!

 

부적 상호작용 멀티 테스트를 하셔야 한다 하셔서 후다닥 스폰매니저부터 멀티가 되도록 변경해주어야 한다.

 

 

 

Fusion 2 - Fusion 2 소개 | Photon Engine

Fusion은 유니티를 위한 새로운 고성능 상태 동기화 네트워킹 라이브러리입니다. Fusion은 기본적으로 데이터 압축, 클라이언트 측 예측 및 지연 보상과 같은 고급 기능을 제공하는 동시에 일반적

doc.photonengine.com

 

우선 우리 프로젝트는 퓨전2로 멀티플레이를 구현해주고 있는데

퓨전2의 사용법부터 좀 익혀야할 것 같다..

 

 

Network object 컴포넌트를 붙인 프리팹은

Network Project Config SO 파일에 

자동으로 매핑이 되어있다.

 

이제 이걸 토대로 호스트가 여기에있는 프리팹을 스폰하도록 하는 로직을 만들어주면 되는데!

 

기존에 프리팹을 생성하기위해서 Instantiate 함수를 사용해주었는데

이건 로컬에만 생성하는 함수라 네트워크로 복제되지 않는 문제점이 있었다.

 

그래서 Runner.Spawn으로 접근해서 Fusion이 위 이미지에있는 프리팹 중에 해당하는걸 스폰하도록 변경해주어야한다.

 

var networkObj = Runner.Spawn(
    data.prefab.GetComponent<NetworkObject>(),
    spawnPos,
    Quaternion.identity,
    inputAuthority: null
    );

 

스폰을 이렇게 해주었다면 이제 클라이언트에 복제를 해주는 작업이 필요하다.

 

[Networked] NetworkId _heukgiRef { get; set; }
[Networked] NetworkId _cheonwooinRef { get; set; }
[Networked] NetworkId _eodukshiniRef { get; set; }

 

우선 당장은 이상현상이 3개 뿐이라 하드코딩 해주었는데

나중에는 리팩토링을 고려해야할 것 같다.. (시간이 급하므로 ㅠ 구현에 집중하기로 했다.)

 

NetworkId는 네트워크에 등록된 객체를 가리키는 번호표로

이 번호로 Runner가 그 객체를 찾아내고 동기화 작업을 진행한다.

 

[Networked] 키워드는 fusion이 스냅샷으로 관리/복제한다는 의미를 준다!

그래서 프로퍼티로 구현되어야 한다. (public이나 static, readonly로는 사용할 수 없음)

그리고 NetworkBehaviour을 상속받은 클래스 내부에서만 사용할 수 있다.

 

/// <summary>
/// 네트워크 참조값 가져오기
/// 스폰할 때 모든 곳에서 같은 곳을 참조해야 해서 적용
/// TODO : 유지보수에 좋지 않으니 Array로 만들어서 알아서 매핑되도록 변경하기
/// </summary>
NetworkId GetRef(EAbnormal type)
{
    return type switch
    {
        EAbnormal.Heukgi => _heukgiRef,
        EAbnormal.Cheonwooin => _cheonwooinRef,
        EAbnormal.Eodukshini => _eodukshiniRef,
        _ => default
    };
}

/// <summary>
///  Runner.Spawn()으로 만든 Network Object의 ID를 해당 참조값에 기록하기
///  클라이언트는 동일한 대상을 가리키고
///  IsAlive()로 존재 확인
///  DeSpawn될 때도 정확히 그 개체를 찾기위함
/// </summary>
void SetRef(EAbnormal type, NetworkObject networkObj)
{
    var r = (NetworkId)networkObj;
    switch (type)
    {
        case EAbnormal.Heukgi: _heukgiRef = r; break;
        case EAbnormal.Cheonwooin: _cheonwooinRef = r; break;
        case EAbnormal.Eodukshini: _eodukshiniRef = r; break;
    }
}

/// <summary>
/// 디스폰 이후 참조값 초기화
/// </summary>
void ClearRef(EAbnormal type)
{
    switch (type)
    {
        case EAbnormal.Heukgi: _heukgiRef = default; break;
        case EAbnormal.Cheonwooin: _cheonwooinRef = default; break;
        case EAbnormal.Eodukshini: _eodukshiniRef = default; break;
    }
    _spawned.Remove(type);
}

 

이제 이 참조값들을 enum타입에 값을 넣어주어서

클라이언트가 모두 동일한 객체를 바라보도록 수정해주었다.

 

 

결과를 보면!!
맵에 스폰된 천우인이 두 클라이언트 모두 동일한 위치에 있는걸 확인할 수 있었다!