1인 개발/PushAndSlash

푸쉬앤슬래시 개인 프로젝트 20일차

잼잼재미 2024. 6. 9. 15:47

구현 내용


1. 멀티 대전 입장


 

 

https://kkln2486.tistory.com/428

 

서버, 로비 접속 및 방 생성

구현 방법NetworkManager 스크립트using System.Collections;using System.Collections.Generic;using UnityEngine;using Photon.Pun;using Photon.Realtime;public class NetworkManager : MonoBehaviourPunCallbacks{ private void Awake() { Screen.SetResolution(

kkln2486.tistory.com

public void MultiPlayActive()
{
    _multiPlayPanel.SetActive(true);
    Connect();
}

public void Connect()
{
    PhotonNetwork.ConnectUsingSettings();
}

public override void OnConnectedToMaster()  // 콜백 : 성공적으로 실행되었다면, 함수가 실행
{
    PhotonNetwork.LocalPlayer.NickName = GameManager.I.DataManager.GameData.UserName;
    MyDataSettingInRoom();
    JoinRandomOrCreateRoom();
}

public void JoinRandomOrCreateRoom()
{
    PhotonNetwork.JoinRandomOrCreateRoom(expectedMaxPlayers : 2, roomOptions : new RoomOptions() { MaxPlayers = 2 });
}

public override void OnJoinedRoom()
{
    Debug.Log("방참가완료");
    PhotonNetwork.Instantiate("PUN2/Room/RoomController", transform.position, Quaternion.identity);
}

 

 

멀티 대전을 클릭하면 서버에 접속하고 랜덤으로 Room에 입장하고, Room이 없다면 최대 접속 인원을 2로 설정하여 Create 하도록 했다. 그리고 현재 자신의 캐릭터 정보를 왼쪽 창에 활성화 되도록 했다. 그리고 Room을 정상적으로 참가했다면, Resources 폴더에 있는 RoomController를 PhotonNetwork를 통해 Instantiate했다. 

 

 

 

RoomController의 현재 PC의 캐릭터가 가지고 있는 정보를 상대 PC로 전송해주는 역할을 한다. OnPhotonSerializeView 함수를 통해, 실시간으로 데이터를 전송할 수 있다. 즉, PC1에서 생성한 RoomController는 PC1의 캐릭터 정보를 PC2의 자신과 동일한 RoomController에 전달하고, PC2에서 생성한 RoomController는 PC2의 캐릭터 정보를 PC1의 자신과 동일한 RoomController에게 전달한다. Room에 2명의 플레이어가 있다면, 각각 PC에서 생성한 RoomController가 2개가 존재하면서 서로의 데이터를 실시간으로 전달하는 방식이다.

 

 

https://kkln2486.tistory.com/429

 

동기화

동기화 1.  PhotonView갱신이 빈번한 경우에 사용ex) 위치 이동, 상태 변경캐릭터의 동기화에 사용캐릭터에 PhotonView, PhotonScriptView 스크립트 추가  Setting OwnershipFixed : Ownership 고정Takeover : Ownership을

kkln2486.tistory.com

 

 

RoomController

private void Start()
{
        StartCoroutine(COUpdate());
}


IEnumerator COUpdate()
{
    yield return new WaitForSeconds(1f);

    while (true)
    {
        if (!_photonView.IsMine)
        {
            if (PhotonNetwork.InRoom && !_isJoin)
            {
                _isJoin = true;

                if (PhotonNetwork.CurrentRoom.PlayerCount == 2)
                    _networkManager.EnemyDataSettingInRoom(_roomEnemyCharacterName, _roomEnemyCharacterLevel, _roomEnemyCharacterRank.ToString(), _roomEnemyUserName, _roomEnemyRankPoint, _roomEnemyCharacterStar, _roomEnemyCharacterKorTag);
            }
        }

        yield return null;
    }
}

public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
    if (stream.IsWriting)
    {
        stream.SendNext(GameManager.I.DataManager.PlayerData.KoreaTag);
        stream.SendNext(GameManager.I.DataManager.PlayerData.Level);
        stream.SendNext(GameManager.I.DataManager.PlayerData.CharacterRank.ToString());
        stream.SendNext(GameManager.I.DataManager.GameData.UserName);
        stream.SendNext(GameManager.I.DataManager.GameData.RankPoint);
        stream.SendNext(GameManager.I.DataManager.PlayerData.Star);
        stream.SendNext(GameManager.I.DataManager.PlayerData.Tag);
    }
    else
    {
        _roomEnemyCharacterName = (string)stream.ReceiveNext();
        _roomEnemyCharacterLevel = (int)stream.ReceiveNext();
        _roomEnemyCharacterRank = (string)stream.ReceiveNext();
        _roomEnemyUserName = (string)stream.ReceiveNext();
        _roomEnemyRankPoint = (int)stream.ReceiveNext();
        _roomEnemyCharacterStar = (int)stream.ReceiveNext();
        _roomEnemyCharacterKorTag = (string)stream.ReceiveNext();
    }
}

 

코드는 위와 같이 OnPhotonSerializeView 함수를 통해 데이터를 실시간으로 전달하고, 전달 받은 데이터를 인자로 하여 오른쪽 캐릭터 창에 정보를 활성화 하도록 했다. IsMine이 아닌 RoomController가 상대 PC의 데이터를 가지고 있기 때문에 

IsMine이 아닌 RoomController만 해당 함수를 실행하도록 했다. 

여기서 update문을 바로 사용하지 않고 코루틴으로 update문을 구현해서 1초 뒤에 실행한 이유는 OnPhotonSerializeView의 데이터 전달 속도 때문이다. Room에 2명의 player가 모두 접속을 하고 바로 해당 함수를 실행하게 되면 데이터를 아직 전송하지 못하여 null 값을 인자로 전달하는 경우가 발생했다. 정확히 OnPhotonSerializeView 함수가 데이터를 얼마마다 전달하는지는 알수없지만 넉넉하게 상대 player가 접속하고 충분한 시간인 1초 뒤에 인자를 전달하도록 구현하기 위해 코루틴을 사용했는데 데이터가 잘 전달되어 인자를 전달할 수 있었다.

 

 

회고


드디어 멀티 플레이의 첫 구현에 성공했다. 아직 실제 게임을 플레이하기 전, Room에서의 데이터를 주고 받은 것 뿐이지만, 처음으로 멀티 플레이를 구현했다는 것 자체가 엄청 뿌듯했다. 아직 정말 초기 단계이지만, 이 정도 구현하는 것도 공부를 하면서 정리를 했기 때문에, 시간이 2~3일 정도가 걸린 것 같다. 가장 어려웠던 부분은 동기화 부분이다. 각각의 PC에 같은 오브젝트를 가지면서 IsMine에서 아닌쪽으로 데이터를 전달하는 방식을 이해하기가 가장 어려웠다. 시간이 많이 걸렸지만 어느정도 이해할 수 있었고, 내가 생각한 방법대로 구현을 했다. 위의 RoomController를 통해서 데이터를 주고 받는 방법이 최선의 방법은 아니라고 생각하지만, 현재 공부한 내용을 응용해서 스스로 잘 구현했다고 생각한다. 이제 2명의 player가 모두 준비 완료 버튼을 클릭하면 전투씬으로 이동하도록 구현하겠다!