ObjectPooler.cs 소스입니다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
public class ObjectPooler : MonoBehaviourPun
{
[System.Serializable]
public class Pool
{
public string tag;
public GameObject prefab;
public int size;
}
public static ObjectPooler OP;
void Awake() => OP = this;
public List<Pool> pools;
public Dictionary<string, Queue<GameObject>> poolDictionary;
public void PrePoolInstantiate()
{
poolDictionary = new Dictionary<string, Queue<GameObject>>();
foreach (Pool pool in pools)
{
Queue<GameObject> objectPool = new Queue<GameObject>();
for (int i = 0; i < pool.size; i++)
{
GameObject obj = PhotonNetwork.Instantiate(pool.tag, Vector3.zero, Quaternion.identity);
obj.GetComponent<PhotonView>().RPC("SetActiveRPC", RpcTarget.All, false);
objectPool.Enqueue(obj);
}
poolDictionary.Add(pool.tag, objectPool);
}
}
public GameObject PoolInstantiate(string tag, Vector3 position, Quaternion rotation)
{
if (!poolDictionary.ContainsKey(tag))
{
Debug.LogWarning($"Pool with tag {tag} doesn't excist.");
return null;
}
GameObject obj = poolDictionary[tag].Dequeue();
obj.GetComponent<PhotonView>().RPC("SetActiveRPC", RpcTarget.All, true);
obj.transform.position = position;
obj.transform.rotation = rotation;
poolDictionary[tag].Enqueue(obj);
return obj;
}
public void PoolDestroy(GameObject obj)
{
obj.GetComponent<PhotonView>().RPC("SetActiveRPC", RpcTarget.All, false);
}
}
PoolScript.cs 소스입니다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
public class PoolScript : MonoBehaviourPun
{
[PunRPC]
void SetActiveRPC(bool b)
{
gameObject.SetActive(b);
}
}
NetworkManager.cs 소스입니다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Photon.Pun;
using Photon.Realtime;
using static ObjectPooler;
public class NetworkManager : MonoBehaviourPunCallbacks
{
public static NetworkManager NM;
void Awake() => NM = this;
public List<PlayerScript> players = new List<PlayerScript>();
public PlayerScript myPlayer;
public Text LogText;
[HideInInspector] public PhotonView PV;
public GameObject CurObj;
void Start()
{
PV = photonView;
Screen.SetResolution(960, 540, false);
PhotonNetwork.ConnectUsingSettings();
}
public void ShowLog(string log) => LogText.text = log;
public void SortPlayers() => players.Sort((p1, p2) => p1.actor.CompareTo(p2.actor));
public override void OnConnectedToMaster() => PhotonNetwork.JoinLobby();
public override void OnJoinedLobby(){ PhotonNetwork.JoinOrCreateRoom("Room", new RoomOptions { MaxPlayers = 4 }, null);}
public override void OnJoinedRoom()
{
myPlayer = PhotonNetwork.Instantiate("Player", Vector3.zero, Quaternion.identity).GetComponent<PlayerScript>();
}
void Update()
{
if (!PhotonNetwork.InRoom) return;
if (Input.GetKeyDown(KeyCode.Alpha1))
OP.PrePoolInstantiate();
else if (Input.GetKeyDown(KeyCode.Alpha2))
CurObj = OP.PoolInstantiate("Portion", Vector3.zero, Quaternion.identity);
else if (Input.GetKeyDown(KeyCode.Alpha3))
OP.PoolDestroy(CurObj);
else if (Input.GetKeyDown(KeyCode.Alpha4))
++myPlayer.Coin;
}
}
PlayerScript.cs 소스입니다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using static NetworkManager;
public class PlayerScript : MonoBehaviourPun
{
[HideInInspector] public PhotonView PV;
[HideInInspector] public string nick;
[HideInInspector] public int actor;
[SerializeField] int coin;
public int Coin { get => coin; set { PV.RPC("SetCoinRPC", RpcTarget.AllBufferedViaServer, value); } }
[PunRPC] void SetCoinRPC(int value) => coin = value;
void Start()
{
PV = photonView;
nick = PV.Owner.NickName;
actor = PV.OwnerActorNr;
NM.players.Add(this);
NM.SortPlayers();
}
void OnDestroy()
{
NM.players.Remove(this);
NM.SortPlayers();
}
}
PhotonChatGUI.cs 소스입니다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
using Photon.Realtime;
using Photon.Chat;
using ExitGames.Client.Photon;
public class PhotonChatGUI : MonoBehaviourPunCallbacks, IChatClientListener
{
[HideInInspector] public Vector3 matrixPos = new Vector3(30, 30, 0);
[HideInInspector] public float matrixScale = 1.9f;
ChatClient chatClient;
string stateChatLabel, callbackChatLabel, chatLabel;
string channelName = "채널001", nicknameInput, chatInput;
bool autoJoinChatChannel = true;
Vector2 chatScroll;
void Awake()
{
Screen.SetResolution(1280, 720, false);
matrixScale = Screen.height * 1.9f / 1080f;
chatClient = new ChatClient(this);
}
void Update()
{
chatClient.Service();
}
void OnGUI()
{
GUI.matrix = Matrix4x4.TRS(matrixPos, Quaternion.identity, Vector3.one * matrixScale);
GUILayout.BeginVertical("Box", GUILayout.Width(320));
GUILayout.Label("채팅상태 : " + stateChatLabel);
GUILayout.Label("채팅콜백 : " + callbackChatLabel);
autoJoinChatChannel = GUILayout.Toggle(autoJoinChatChannel, " 자동로비접속");
GUILayout.BeginHorizontal();
GUILayout.Label("닉네임");
nicknameInput = GUILayout.TextField(nicknameInput, GUILayout.Width(150));
GUILayout.EndHorizontal();
GUILayout.Space(10);
GUILayoutOption width = GUILayout.Width(160);
GUILayout.BeginHorizontal();
if (GUILayout.Button("채팅서버 연결", width)) ConnectChatClick();
if (GUILayout.Button("채팅서버 나가기", width)) DisconnectChatClick();
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if (GUILayout.Button("채널입장", width)) SubscribeClick();
if (GUILayout.Button("채널나가기", width)) UnsubscribeClick();
GUILayout.EndHorizontal();
GUILayout.Space(10);
chatScroll = GUILayout.BeginScrollView(chatScroll, "Box", GUILayout.MaxHeight(200));
GUILayout.Label(chatLabel);
GUILayout.EndScrollView();
chatInput = GUILayout.TextArea(chatInput);
if (chatInput != null && chatInput.Contains("\n"))
{
if(StringAvailable(chatInput)) Send(chatInput.Trim());
chatInput = "";
}
GUILayout.Label("* 엔터를 치면 보내집니다. (보낼닉네임>>보낼메세지) 로 귓속말이 됩니다");
GUILayout.EndVertical();
}
bool StringAvailable(string s)
{
if (string.IsNullOrWhiteSpace(s)) return false;
return true;
}
public void OnChatStateChange(ChatState state)
{
stateChatLabel = state.ToString();
}
void SetCallbackChatLabel(string s)
{
callbackChatLabel = s;
}
void ReceiveMessages(string nickName, string msg)
{
chatLabel += (chatLabel != "" ? "\n" : "") + nickName + " : " + msg;
}
void ReceiveMessages(string msg)
{
chatLabel += (chatLabel != "" ? "\n" : "") + msg;
}
#region 버튼과 콜백
void ConnectChatClick()
{
if (StringAvailable(nicknameInput))
{
chatClient.Connect(PhotonNetwork.PhotonServerSettings.AppSettings.AppIdChat, PhotonNetwork.AppVersion,
new Photon.Chat.AuthenticationValues(nicknameInput));
}
}
public override void OnConnected()
{
SetCallbackChatLabel("OnConnected");
if (autoJoinChatChannel) SubscribeClick();
}
void DisconnectChatClick()
{
chatClient.Disconnect();
}
public void OnDisconnected()
{
SetCallbackChatLabel("OnDisconnected");
}
void SubscribeClick()
{
chatClient.Subscribe(new string[] { channelName }, 10);
}
public void OnSubscribed(string[] channels, bool[] results)
{
chatLabel = "";
SetCallbackChatLabel("OnSubscribed");
}
void UnsubscribeClick()
{
chatClient.Unsubscribe(new string[] { channelName });
}
public void OnUnsubscribed(string[] channels)
{
SetCallbackChatLabel("OnUnsubscribed");
}
void Send(string s)
{
if (s.Contains(">>"))
{
string[] ss = s.Split(new string[] { ">>" }, System.StringSplitOptions.None);
chatClient.SendPrivateMessage(ss[0], ss[1]);
}
else chatClient.PublishMessage(channelName, s);
}
public void OnGetMessages(string channelName, string[] senders, object[] messages)
{
for (int i = 0; i < messages.Length; i++)
{
ReceiveMessages(senders[i], messages[i].ToString());
}
chatScroll.y = 100000;
}
public void OnPrivateMessage(string sender, object message, string channelName)
{
ReceiveMessages(sender + "의 귓속말", message.ToString());
chatScroll.y = 100000;
}
#endregion
public void OnUserSubscribed(string channel, string user) { }
public void OnUserUnsubscribed(string channel, string user) { }
public void OnStatusUpdate(string user, int status, bool gotMessage, object message) { }
public void DebugReturn(DebugLevel level, string message) { }
}