내일배움캠프/프로젝트

팀 프로젝트 - 유령 배치, Navmesh 동적 생성

서보훈 2024. 12. 17. 21:05

학생측의 역할이 된 플레이어의 게임 씬에 유령의 역할을 할 오브젝트를 스폰시키도록 제작해주었습니다.

현재, 교수측은 직접적으로 유령과 조우하지 않기 때문에 학생측에게만 유령을 생성하도록 만들어주었으며, 교수측에게 필요한 정보는 별도로 Rpc를 사용하여 전달하게 될 듯 합니다.

생성 코드입니다.

public class NetworkGameManager : NetworkBehaviour
{
    //...생략
    private void DoNextStep()
    {
        //...생략
        else
        {
            NetworkSpawnController.Instance.SpawnPlayer(ProfessorId, StudentId);
            SpawnGhostClientRpc();
        }
    }
    
    [ClientRpc]
    private void SpawnGhostClientRpc()
    {
        if (NetworkManager.Singleton.LocalClientId == StudentId)
        {
            NetworkSpawnController.Instance.SpawnGhost();
        }
    }
}

public class NetworkSpawnController : MonoSingleton<NetworkSpawnController>
{
    //...생략
    public void SpawnGhost()
    {
        navMesh.BuildNavMesh();
        //TODO : 반복문으로 바꿔서 모든 지점에 스폰될수 있도록 변경하기
        Ghost ghost = Instantiate(GameManager.Instance.mapData.ghostPrefab, GameManager.Instance.mapData.ghostSpawnPos[0], Quaternion.identity);
        ghost.SetPatrolPoints(GameManager.Instance.mapData.patrolPos[0].patrolPositions);
        GameManager.Instance.networkGameManager.SpawnCompliteClientRpc();
    }
}

플레이어를 생성한 뒤, 학생 역할을 하는 클라이언트에게 유령을 생성하는 Rpc를 보내게 됩니다

이 Rpc를 통해 학생측 플레이어의 씬에 유령을 생성합니다.

※ ClientRpc기능중, 특정 클라이언트에게만 Rpc를 보내는 기능이 있긴 합니다. 이후 해당 방식으로 변경할 가능성이 있습니다.

 

또한, 유령의 경우 Navmesh를 통해 이동을 구현해주었기 때문에 맵이 생성된 후, Navmesh를 생성하도록 만들어주었습니다.

현재 테스트용도로 하나의 건물에만 이동이 불가능하도록 만들어주었습니다.

유령이 건물 내부로 쫒아오지 못하게 만들어줄 예정이기때문에, Navmesh에 인식되지 않도록 만들어주고 차후에 유령의 상태를 변경시키도록 만들어주어야합니다.

 

관련 코드입니다.

public class NetworkSpawnController : MonoSingleton<NetworkSpawnController>
{
    public NetworkObject networkGameManager;
    public NetworkObject playerPrefab;
    private NavMeshSurface navMesh;

    protected override void Awake()
    {
        //... 싱글톤
        
        navMesh = GetComponent<NavMeshSurface>();
        NetworkManager.Singleton.SceneManager.OnSynchronizeComplete += SpawnManager;
    }
    
    //...생략
    
    public void SpawnGhost()
    {
        navMesh.BuildNavMesh();
        //TODO : 반복문으로 바꿔서 모든 지점에 스폰될수 있도록 변경하기
        Ghost ghost = Instantiate(GameManager.Instance.mapData.ghostPrefab, GameManager.Instance.mapData.ghostSpawnPos[0], Quaternion.identity);
        ghost.SetPatrolPoints(GameManager.Instance.mapData.patrolPos[0].patrolPositions);
        GameManager.Instance.networkGameManager.SpawnCompliteClientRpc();
    }
}

 

유령을 생성하기 전, NavMeshSurface의 BuildNavMesh() 메서드를 사용하여 NavMesh를 만들어주게 됩니다.

 


트러블 슈팅

  • Source mesh ~ does not allow read access. This will work in playmode in the editor but not in player 오류
    • NavMesh를 베이크 할 때, 원본 소스에 접근하여 내용을 수정하지 못할경우 발생하는 오류입니다.
    • 해당 Mesh에 이동경로가 필요할경우 Read/Write 를 true 로 바꾸어주면 됩니다.
    • 이 Mesh에 이동경로가 필요하지 않을경우 Mesh가 사용된 프리팹에 NavMeshModifier 를 사용, Mode를 RemoveObject 로 해주고 NavMeshSurface의 Collect Objects 를 NavMeshModifier Component Only 로 변경하여 NavMesh 생성 대상에서 제외해주면 해결 가능합니다.