VioletaBabel

62. Photon Tutorial (8) 본문

BCA/8. Photon
62. Photon Tutorial (8)
Beabletoet 2018. 8. 7. 10:05
Player instance를 생성하자.


PlayerManager.cs를 열어

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//PlayerManager.cs
using System.Collections;
using UnityEngine;
using UnityEngine.EventSystems;
public class PlayerManager : Photon.PunBehaviour, IPunObservable
{
    public GameObject Beams;
    public float Health = 1f;
    public static GameObject LocalPlayerInstance;
    private bool IsFiring;
    private void Awake()
    {
        if (Beams == null)
            Debug.LogError("<Color=Red><a>Missing</a><Color> Beams Reference."this);
        else
            Beams.SetActive(false);
        if (photonView.isMine)
            PlayerManager.LocalPlayerInstance = this.gameObject;
        DontDestroyOnLoad(this.gameObject);
    }
    private void Start()
    {
        CameraWork _cameraWork = this.gameObject.GetComponent<CameraWork>();
        if (_cameraWork != null)
        {
            if (photonView.isMine)//이것이 내꺼냐?
                _cameraWork.OnStartFollowing();//그럼 얘만 따라다니자
        }
        else
            Debug.LogError("<Color=Red><a>Missing</a></Color> CameraWork Component on playerPrefab."this);
    }
    private void Update()
    {
        if (photonView.isMine) // 얘도 플레이어 자기 캐릭만 동작해야하니까 랩핑함.
            ProcessInputs();
        if (Health <= 0f)
            GameManager.instance.LeaveRoom(); // 체력이 0이 되면 게임 오버
        if (Beams != null && IsFiring != Beams.GetActive())
            Beams.SetActive(IsFiring);
    }
 
    void ProcessInputs()
    {
        if (Input.GetButtonDown("Fire1"))
            if (!IsFiring)
                IsFiring = true;
        if (Input.GetButtonUp("Fire1"))
            if (IsFiring)
                IsFiring = false;
    }
 
    private void OnTriggerEnter(Collider other)
    {
        if (!photonView.isMine)//자기 거인지 확인
            return;
        if (!other.CompareTag("Beam"))
            return;
        Health -= 0.1f;
    }
 
    private void OnTriggerStay(Collider other)
    {
        if (!photonView.isMine)
            return;
        if (!other.CompareTag("Beam"))
            return;
        Health -= 0.1f * Time.deltaTime;
    }
 
    void IPunObservable.OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {   //메소드 안에서 stream 변수를 전달하였다. 네트워크를 타고 전송되며 이 호출로 데이터를 읽고 쓴다.
        //photonView.isMine이 true일 때 write, 아닐 때 read된다.
        if (stream.isWriting)//write일 때
            stream.SendNext(IsFiring);//data Stream에 추가
        else//read일 때
            this.IsFiring = (bool)stream.ReceiveNext();
    }
}
 
cs

로 수정한 후 


GameManager.cs를 열어 다음과 같이 수정한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//GameManager.cs
using System.Collections;
using System;
using UnityEngine;
using UnityEngine.SceneManagement;
 
public class GameManager : Photon.PunBehaviour {
 
    static public GameManager instance;
    public GameObject playerPrefab;
 
    private void Start()
    {
        instance = this;
        if (playerPrefab == null)
            Debug.LogError("<Color=Red><a>Missing</a></Color> playerPrefab Reference. Please set it up in GameObject 'Game Manager'"this);
        else
        {
            if (PlayerManager.LocalPlayerInstance == null)//기존 참조가 없는 경우
            {
                Debug.Log("We are Instantiating LocalPlayer from " + SceneManager.GetActiveScene().name);
                PhotonNetwork.Instantiate(this.playerPrefab.name, new Vector3(0f, 5f, 0f), Quaternion.identity, 0);//프리팹 생성
            }
            else//기존 참조가 있으면 생성을 넘어감.
                Debug.Log("Ignoring scene load for " + SceneManager.GetActiveScene().name);
        }
    }
 
    private void LoadArena()
    {
        if (!PhotonNetwork.isMasterClient) // 마스터 클라이언트인지 확인.
            Debug.LogError("PhotonNetwork : Trying to Load a level but we are not the master Client");
        Debug.Log("PhotonNetwork : Loading Level : " + PhotonNetwork.room.PlayerCount);
        PhotonNetwork.LoadLevel("Room for " + PhotonNetwork.room.PlayerCount);  //네트워크 메세지 큐를 잠시 멈추기 위해
                                                //레벨 로딩을 Wrap함.
                                                //이 메소드는 PhotonNetwork.isMessageQueueRunning을 false함.
                                                //그리고 레벨 로딩이 끝나면 enable.
                                                //룸 내의 로드된 레벨과 동기화를 위하여 
                                                //PhotonNetwork.automaticallySyncScene을 사용하도록 하였기에
                                                //룸 안의 모든 클라이언트의 레벨 로드를 유니티가 아닌 Photon이 하도록 함.
                                                //마스터인 경우에만 호출되어야 함.
    }
    public void OnLeftRoom()
    {
        SceneManager.LoadScene(0); // Photon Callback인 OnLeftRoom을 listen하여 0번 Scene인 Launcher를 로드한다.
    }
    public void LeaveRoom()
    {
        PhotonNetwork.LeaveRoom();  // 현재 참여하고 있는 룸을 떠나 마스터 서버로 되돌아간다.
                                    // autoCleanUp을 false로 하지 않았을 경우, PhotonView의 모든 네트워크 게임 오브젝트를 제거.
                                    // 마스터 서버도 되돌아가며, 오프라인 모드에서는 OnLeftRoom이 곧바로 호출됨.
                                    // 추상화를 위해 public 메소드로 wrap 함.
    }
 
    public override void OnPhotonPlayerConnected(PhotonPlayer other)
    {   //원격 플레이어가 룸에 들어왔을 때 호출. PhotonPlayer가 playerlist에 이미 추가된 시점에 불림.
        //특정 수의 플레이어로 게임이 시작 시, 이 콜백 내에서 Room.playerCount를 체크해 게임 시작이 가능한지 확인하기도 함.
        Debug.Log("OnPhotonPlayerConnected() " + other.NickName);
        if(PhotonNetwork.isMasterClient)
        {
            Debug.Log("OnPhotonPlayerConnected isMasterClient" + PhotonNetwork.isMasterClient);
            LoadArena();
        }
    }
 
    public override void OnPhotonPlayerDisconnected(PhotonPlayer other)
    {   //원격 플레이어가 룸을 나갔을 때 호출. PhotonPlayer가 playerlist에서 이미 제거된 시점에 불림.
        //클라이언트가 PhotonNetwork.leaveRoom을 호출할 때 이 메소드를 호출함.
        //원격 클라이언트의 연결이 끊어져도 이 콜백이 몇 초간의 타임아웃 후 실행 됨.
        Debug.Log("OnPhotonPlayerDisconnected() " + other.NickName);
        if(PhotonNetwork.isMasterClient)
        {
            Debug.Log("OnPhotonPlayerConnected is MasterClient " + PhotonNetwork.isMasterClient);
            LoadArena();
        }
    }
}
cs




그리고 경기장 밖에 있는 경우의 플레이어 위치를 관리해보자. 경기장의 크기는 플레이어의 수에 따라 변하고, 한 명의 플레이어가 나가면 다른 플레이어들이 바뀐 경기장 밖에 위치할 수도 있다. 그러므로 경기장의 중심부로 플레이어들의 위치를 재조정하자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//GameManager.cs
using System.Collections;
using System;
using UnityEngine;
using UnityEngine.SceneManagement;
 
public class GameManager : Photon.PunBehaviour {
 
    static public GameManager instance;
    public GameObject playerPrefab;
 
    private void Start()
    {
        instance = this;
        if (playerPrefab == null)
            Debug.LogError("<Color=Red><a>Missing</a></Color> playerPrefab Reference. Please set it up in GameObject 'Game Manager'"this);
        else
        {
            if (PlayerManager.LocalPlayerInstance == null)//기존 참조가 없는 경우
            {
                Debug.Log("We are Instantiating LocalPlayer from " + SceneManager.GetActiveScene().name);
                PhotonNetwork.Instantiate(this.playerPrefab.name, new Vector3(0f, 5f, 0f), Quaternion.identity, 0);//프리팹 생성
            }
            else//기존 참조가 있으면 생성을 넘어감.
                Debug.Log("Ignoring scene load for " + SceneManager.GetActiveScene().name);
        }
    }
 
    private void LoadArena()
    {
        if (!PhotonNetwork.isMasterClient) // 마스터 클라이언트인지 확인.
            Debug.LogError("PhotonNetwork : Trying to Load a level but we are not the master Client");
        Debug.Log("PhotonNetwork : Loading Level : " + PhotonNetwork.room.PlayerCount);
        PhotonNetwork.LoadLevel("Room for " + PhotonNetwork.room.PlayerCount);  //네트워크 메세지 큐를 잠시 멈추기 위해
                                                //레벨 로딩을 Wrap함.
                                                //이 메소드는 PhotonNetwork.isMessageQueueRunning을 false함.
                                                //그리고 레벨 로딩이 끝나면 enable.
                                                //룸 내의 로드된 레벨과 동기화를 위하여 
                                                //PhotonNetwork.automaticallySyncScene을 사용하도록 하였기에
                                                //룸 안의 모든 클라이언트의 레벨 로드를 유니티가 아닌 Photon이 하도록 함.
                                                //마스터인 경우에만 호출되어야 함.
    }
    public void OnLeftRoom()
    {
        SceneManager.LoadScene(0); // Photon Callback인 OnLeftRoom을 listen하여 0번 Scene인 Launcher를 로드한다.
    }
    public void LeaveRoom()
    {
        PhotonNetwork.LeaveRoom();  // 현재 참여하고 있는 룸을 떠나 마스터 서버로 되돌아간다.
                                    // autoCleanUp을 false로 하지 않았을 경우, PhotonView의 모든 네트워크 게임 오브젝트를 제거.
                                    // 마스터 서버도 되돌아가며, 오프라인 모드에서는 OnLeftRoom이 곧바로 호출됨.
                                    // 추상화를 위해 public 메소드로 wrap 함.
    }
 
    public override void OnPhotonPlayerConnected(PhotonPlayer other)
    {   //원격 플레이어가 룸에 들어왔을 때 호출. PhotonPlayer가 playerlist에 이미 추가된 시점에 불림.
        //특정 수의 플레이어로 게임이 시작 시, 이 콜백 내에서 Room.playerCount를 체크해 게임 시작이 가능한지 확인하기도 함.
        Debug.Log("OnPhotonPlayerConnected() " + other.NickName);
        if(PhotonNetwork.isMasterClient)
        {
            Debug.Log("OnPhotonPlayerConnected isMasterClient" + PhotonNetwork.isMasterClient);
            LoadArena();
        }
    }
 
    public override void OnPhotonPlayerDisconnected(PhotonPlayer other)
    {   //원격 플레이어가 룸을 나갔을 때 호출. PhotonPlayer가 playerlist에서 이미 제거된 시점에 불림.
        //클라이언트가 PhotonNetwork.leaveRoom을 호출할 때 이 메소드를 호출함.
        //원격 클라이언트의 연결이 끊어져도 이 콜백이 몇 초간의 타임아웃 후 실행 됨.
        Debug.Log("OnPhotonPlayerDisconnected() " + other.NickName);
        if(PhotonNetwork.isMasterClient)
        {
            Debug.Log("OnPhotonPlayerConnected is MasterClient " + PhotonNetwork.isMasterClient);
            LoadArena();
        }
    }
 
    private void OnLevelWasLoaded(int level)
    {//플레이어 아래로 raycast하여 아무 것도 접촉하고 있지 않다면 경기장 중심부로 위치를 재조정함.
        if (!Physics.Raycast(transform.position, -Vector3.up, 5f))
            transform.position = new Vector3(0f, 5f, 0f);
    }
}
cs


'BCA > 8. Photon' 카테고리의 다른 글

63. Photon Tutorial (9)  (0) 2018.08.07
61. Photon Tutorial (7)  (0) 2018.08.06
60. Photon Tutorial (6)  (0) 2018.08.06
59. Photon Tutorial (5)  (0) 2018.08.06
58. Photon Tutorial (4)  (0) 2018.08.06
Comments