[Unity + Photon] Make Multiplayer Racing Game

[Unity + Photon] Make Multiplayer Racing Game


먼저 씬을 저장합니다. [Ctrl + 9]를 눌러 에셋 스토어로 가서 무료 터레인 에셋을 다운받습니다. 이게 괜찮아보이네요. 텍스쳐와 터레인만 불러오겠습니다. 터레인을 배치하고 라이트 설정을 해줍니다. 스카이박스도 지정합니다. 아직 라이트맵이 없어서 라이팅 결과가 조금 이상하네요. 터레인은 크기가 커서 라이트맵 생성도 오래걸리니 그냥 넘어갑시다. 이제 맵이 있으니 플레이어를 넣어봅시다. 표준 에셋에 있는 Car Controller를 활용할겁니다. 없으신 분은 Asset Store에서 다운로드 가능합니다. Car 프리팹을 찾아 씬에 넣습니다. 이 프리팹은 차량 조종을 위한 기능이 모두 들어가있습니다. 카메라가 플레이어의 뒤에 옮기기 위해서 카메라를 차 오브젝트 안에 넣고 Reset Transform한 후에 위치를 조절합니다. 다음, P.U.N을 다운받습니다. 이 영상을 만들때 V2가 나왔습니다. 이전 버젼은 Classic으로 부르더군요. 이 영상은 Classic을 사용하겠습니다. P.U.N.을 불러오면 App ID를 넣으라고 합니다. 따라서 포톤 대시 보드 사이트에서 PUN 앱을 만들어야 합니다. 저는 한국에 살고 있으므로 Kr 지역을 선택했습니다. 가까운 지역을 선택해주시고, “Auto Join Lobby”를 켜줍니다. 라이트맵 생성이 너무 오래걸려서 그냥 꺼버리겠습니다. 게임을 실행해서 확인해봅시다. 괜찮네요. 유니티에서 차량 컨트롤러를 잘 만들어놨네요. 근데 카메라가 조금 어색합니다. 표준 에셋에 더 나은 카메라 스크립트가 있으니 그걸 사용합시다. “MultipurposeCameraRig” 이걸 사용하겠습니다. 기본 카메라를 대체해줍시다. “Auto Target Player”라는 옵션이 있는데 이는 자동으로 Player 태그가 붙은 오브젝트를 추적하는 기능입니다. 이제 카메라에 부드러운 느낌이 생겼습니다. 값을 조절해서 원하는 느낌을 찾아보세요. 저는 이게 괜찮아보이네요. 값을 복사한 후 테스트를 중지하고, “Paste Component Values”로 복사한 값을 적용해줍니다. 이제 플레이어가 준비됬으니 프리팹으로 저장해줍니다. 참고로 포톤에서 오브젝트를 생성하려면 프리팹이 무조건 Resources 폴더 안에 있어야 합니다. 플레이어를 제거합니다. 이제 로비를 만들어봅시다. 먼저 로비용 카메라를 추가합니다. 카메라를 수동으로 옮길 필요없이, 화면을 원하는 곳으로 이동한 후 카메라 오브젝트를 선택하고 “Ctrl +Shift +F”를 누르면 카메라를 즉시 그곳으로 이동시킬 수 있습니다. 카메라에 Clipping Planes ->Far 값을 증가해 카메라가 렌더링하는 범위를 넓혀줍니다. 이제 로비 화면을 만들어봅시다. 여기서 UI 오브젝트를 선택하고 “Alt + Shift”를 누른 상태로 피벗을 지정하면 피벗 변경과 이동이 동시에 적용됩니다. 빈 패널을 추가해 UI 오브젝트들을 랩핑합니다. 그러면 해당 패널을 비활성화하면 모든 화면을 숨길 수 있습니다. 텍스트 오브젝트를 선택하고 “Ctrl +D”를 눌러 복제합니다. 이 폰트는 게임 상태를 출력할겁니다. 이제 스크립트를 작성할 시간입니다. NetworkManager라는 스크립트를 만듭니다. import UnityEngine.UI 를 추가합니다. MonoBehaviour 대신 Photon.PunBehavior를 상속받습니다. 플레이어가 생성될 위치도 필요합니다. 일부 포톤에 필요한 문자열 값을 선언해줍니다. PUN에서 오브젝트를 생성하려면 Resources 폴더에 있는 프리팹의 이름을 전달합니다. 빈 오브젝트를 만들고 이름을 NetworkManager로 바꿔준 후 NetworkManager 컴포넌트를 추가해줍니다. 스폰할 위치가 필요합니다. 좋은 위치를 찾아봅시다. 여기가 좋아보입니다. 빈 오브젝트를 만듭니다. 스폰된 플레이어가 바닥에 끼이거나 튕겨나가는걸 방지하기 위해 땅보다 약간 위에 놓아줍니다. 개인적으로는 플레이어 별로 다른 위치에 생성하는걸 추천드립니다. 이제 네트워크 연결을 처리합시다. 먼저 포톤 네트워크에 접속합니다. 이어서 현재 네트워크 상태를 statusText에 출력합니다. 연결 실패에 대한 부분은 이 비디오에 넣지 않겠습니다. 만약 실제 멀티플레이 게임을 만드실거면, 이 부분을 적절하게 처리해주셔야 합니다. 포톤 네트워크에 접속하면 자동으로 로비로 접속됩니다. 이는 이전에 우리가 포톤 설정에서 체크했기 때문이죠. 이제 룸을 만들거나 접속하면 됩니다. 룸에 들어갔다면 플레이어를 생성할 차례입니다. 로비 화면과 카메라를 숨기는걸 잊지마세요! 이 비디오는 그냥 예제이므로, 다른 플레이어가 접속되거나 나가는 부분은 처리하지 않겠습니다. 오브젝트를 생성하려면 먼저 Player 오브젝트에 PhotonView를 추가해줘야 합니다. PhotonView는 네트워크로 전달된 데이터를 처리하거나 다른 클라이언트들에게 데이터를 전달하는 역할을 수행합니다. 테스트를 해봅시다. 잘되네요. 룸에도 접속되었고 플레이어도 만들어졌습니다. 근데 로비 화면을 안껐군요 ๐Ÿ˜› 룸에도 접속했고 플레이어도 만들었습니다. 하지만 아직 플레이어들끼리 동기화가 안되죠. 이를 위해 PhotonView를 통해 플레이어간 데이터를 주고 받을 필요가 있습니다. 이를 가장 쉽게 구현하는 방법은 PhotonView의 Observed Components에 트랜스폼을 넣어 자동으로 동기화하는 겁니다. 물리적인 기능도 동기화하려면 Rigidbody도 동기화해야 합니다. 그런데 이렇게 하는것 대신, 포톤에서 더 효율적으로 처리하기 위해 TransformView와 RigidbodyView라는 것을 제공합니다. 스케일 값은 동기화할 필요가 없으니 위치와 회전 값만 체크해줍니다. 이제 각 플레이어들의 트랜스폼은 자동으로 동기화됩니다. 이제 해줘야할건 다른 플레이어의 차량까지 컨트롤 하는걸 방지하는 작업입니다. 이를 위해 다른 사용자의 차면 해당 스크립트를 꺼버리는 NetworkPlayer라는 스크립트를 만들어줍시다. 각각의 플레이어(차량)은 내부에 카메라가 있습니다. 따라서 다른 플레이어 차량의 카메라는 제거해줘야 합니다. 이어서 PhotonView와 NetworkPlayer를 제외한 모든 컴포넌트를 꺼줍니다. 차에 NetworkPlayer 컴포넌트를 추가하고, 카메라를 할당해줍니다. 다된거같네요! 게임을 빌드해서 한번 봅시다. 와우 차가 튕겨나는것도 모잘라 동기화도 안되네요. 왜냐면 Transform과 Rigidbody를 Observed Components에 안넣어서 그렇습니다 ๐Ÿ™ 다시 한번 해볼까요 ㅅㅂ? 다행히 동기화는 잘되네요 물리 상태도 잘 동기화됩니다. 이제 그 괴상한 튕겨나가는 현상을 고쳐봅시다. 이 부분은 아까 튕겨나가는 부분입니다. 잘보세요. 문제의 원인을 아시겠나요? 다시 한번 영상을 천천히 돌려보겠습니다. 보이시나요? 두 차량이 같은 곳에 있어서 물리 엔진이 서로를 밀어낸거였습니다. 이 현상을 방지하려면 플레이어끼리 서로 뚫고 다닐 수 있게 하거나 아니면 다른 위치에 생성하면 됩니다. 하지만 전 똑똑하므로 다른 방법을 쓸겁니다. 대신 1초동안 차량들의 Collider를 끄는겁니다. 실제 게임에서는 이렇게 처리안하시는걸 강력 추천드립니다. 예외가 뜨네요 ㅋㅋㅋㅋ 차의 Collider를 껐더니 차량 컨트롤러에서 에러가 납니다. 따라서 그냥 다른 플레이어의 Collider만 끄도록 합시다. 테스트 타임! 잘되네요~~! 제가 준비한 영상은 여기까지고요, 멀티플레이 게임 만드는 과정이 재미있으셨길 바랍니다. 다음 비디오에서 또 찾아뵜겠습니다. 구독 잊지 말아주세요^^

16 Replies to “[Unity + Photon] Make Multiplayer Racing Game”

  1. ์™€.. 27๋ถ„๋™์•ˆ ์˜์–ด์ž๋ง‰ ์“ฐ์‹œ๋Š”๊ฑฐ ๊ต‰์žฅํžˆ ํž˜๋“œ์…จ์„ํ…๋ฐ ๋Œ€๋‹จํ•ด์š”! ๋งŽ์€ ๋„์›€์ด ๋์–ด์š”~

  2. If the room is full of player. the other will spawn in other same room automatically?
    sorry if any wrong in grammar or other.

  3. what function code to called the second player? because i only spawn 1 and they sync in the exe and on unity and not respawning the other car

  4. It was nice to watch this tutorial. As it is not very common to stumble upon written tutorials, this had a nice commentary in it ๐Ÿ™‚ Thank you

  5. ํ•œ๊ตญ๋ถ„์ด์…จ๋„ค์š” ์˜์–ด์ผ์ค„์•Œ๊ณ  ๊ฐ์˜คํ•˜๊ณ  ๋“ค์–ด์™”๋Š”๋ฐ ใ…‹ใ…‹

  6. hello again I have a request this time frankly I used to teach you to make truck games but not very well I noticed that there are some problems, such as connecting to the server later, such as the other one, such as I had made it like 2d game detailed and beautiful I would like to ask online game how to show using pun?

  7. I get a error error CS1061: 'Transform' does not contain a definition for 'positon' and no accessible extension method 'positon' accepting a first argument of type 'Transform' could be found (are you missing a using directive or an assembly reference?)

    Here's the code:
    using UnityEngine;

    using UnityEngine.UI;

    public class NetworkManager : Photon.PunBehaviour {

    public GameObject lobbyCam;

    public Transform spawnPoint;

    public GameObject lobbyUI;

    public Text statusText;

    public const string Version = "1.0";

    public const string RoomName = "Multyplayer";

    public string playerPrefabName = "Player";

    void Start() {

    PhotonNetwork.ConnectUsingSettings(Version);

    }

    void Update() {

    statusText.text = PhotonNetwork.connectionStateDetailed.ToString();

    }

    public override void OnConnectionFail(DisconnectCause cause) {

    print("Connection Failed" + cause.ToString());

    print(cause.ToString());

    }

    public override void OnJoinedLobby() {

    RoomOptions roomoptions = new RoomOptions() { IsVisible = false, MaxPlayers = 4};

    PhotonNetwork.JoinOrCreateRoom(RoomName, roomoptions, TypedLobby.Default);

    }

    public override void OnJoinedRoom() {

    lobbyCam.SetActive(false);

    lobbyUI.SetActive(false);

    GameObject player = PhotonNetwork.Instantiate(playerPrefabName, spawnPoint.positon, spawnPoint,rotation, 0);

    }

    public override void OnPhotonPlayerConnected(PhotonPlayer newPlayer) {

    print("New Player Connected");

    }

    public override void OnPhotonPlayerDisconnected(PhotonPlayer otherPlayer) {

    print("Player Disconnected");

    }

    }

    I think I copyed something wrong can you help?

Leave a Reply

Your email address will not be published. Required fields are marked *