https://www.photonengine.com/ko-kr
글로벌 크로스 플랫폼 실시간 게임 개발 | Photon Engine
EssentialPhoton Details Discover a summary of our product range, notable features, the power of the Photon Cloud, and our cost-effective pricing plans. HAVE A LOOK
www.photonengine.com
들어가서 회원가입 및 로그인
https://dashboard.photonengine.com/ko-kr
로그인 | Photon Engine
Sign In 아직 계정이 없으신가요? 회원 등록은 여기를 클릭
id.photonengine.com
대시보드에서 app 생성
PUN, 이름 설정
Unity project에 PUN2 asset store에서 찾아서 받기
Photon Server Settings에서 만들어둔 App id에 입력해준다
포톤을 이용해 채팅을 구현한 스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Photon.Pun;
using Photon.Realtime;
public class PhotonMgr : MonoBehaviourPunCallbacks
{
public Text logText; //접속 상태
public InputField userId; //사용자 아이디
public GameObject lobbyPanel; //껐다 켰다용도
public GameObject chatPanel;
public GameObject joinButton; //접속중일때 join 안하게 setactive 제어용
//public GameObject RoomPanel;
public Text RoomNameText; //방 제목
public Text RoomCountText; //방 사람 제한
public Text ListText; //방에 접속한 이름 표시
public Text[] ChatText; //전체 채팅 배열
public InputField ChatInput; //채팅 입력
public PhotonView PV;
void Awake()
{
joinButton.SetActive(false);
chatPanel.SetActive(false);
PhotonNetwork.ConnectUsingSettings();
}
public override void OnConnectedToMaster() //포톤서버에 접속이 성공했다면 자동으로 호출되는 pun 콜백함수
{
// Debug.Log("connected server!!"); //서버 접속 성공하면 바로 로비에 접속
PhotonNetwork.JoinLobby(); //로비에 접속을 시도
// PhotonNetwork.JoinRandomRoom(); //방에 입장을 시도
}
public override void OnDisconnected(DisconnectCause cause) //서버 접속에 실패하면 호출되는 콜백
{
base.OnDisconnected(cause);
print("연결 실패");
}
public override void OnJoinedLobby() //로비에 접속되면
{
Debug.Log("Enter Lobby!!");
joinButton.SetActive(true); //버튼 활성화
}
public void OnClickJoinRoom() //방에 접속하는 버튼 클릭시
{
string userName = userId.text; //user name 받아오기
if (string.IsNullOrEmpty(userName))
{
userName = "USER_" + Random.Range(0, 999).ToString(); //user name 없으면 랜덤으로 써주기
}
PhotonNetwork.NickName = userName;//유저 이름 설정
PhotonNetwork.JoinRandomRoom(); // 무작위 방에 입장
}
public override void OnJoinRandomFailed(short returnCode, string message) //무작위 방 접속에 실패했다면
{
Debug.Log("No Rooms");
//참여 인원 수 20명으로 방을 만든다
PhotonNetwork.CreateRoom("New Chatting", new RoomOptions { MaxPlayers = 20 }); //방 새로 만들기~
}
public override void OnJoinedRoom() //방에 접속하기
{
Debug.Log("Enter Room");
lobbyPanel.SetActive(false);
chatPanel.SetActive(true);
RoomRenewal();
ChatInput.text = "";
for (int i = 0; i < ChatText.Length; i++) ChatText[i].text = "";
}
// Update is called once per frame
void Update()
{
logText.text = PhotonNetwork.NetworkClientState.ToString(); //실시간으로 네트워크 상태 반영
if (Input.GetKeyDown(KeyCode.Return) && !ChatInput.isFocused) //enter를 눌렀고 채팅창이 활성화되어있을때 (클릭)
{
Send();
}
}
public void Send()
{
//채팅 전송할 때 인풋필드 내용이 있는지 검사, 없다면 무시
if (!string.IsNullOrEmpty(ChatInput.text))
{
string chatText = "<color=#00ff00>" + //r 00 g ff b 00
PhotonNetwork.NickName + " : " + ChatInput.text + "</color>";
PV.RPC("ChatRPC", RpcTarget.AllBuffered, chatText); //ChatRPC 함수를 실행,
ChatInput.text = ""; //보내면 내용 비우기
}
//채팅내용을 전송한 뒤 인풋필드 레이블을 비워주고, 포커스를 다시
//인풋필드에 맞춤
ChatInput.ActivateInputField();
}
[PunRPC] // RPC는 플레이어가 속해있는 방 모든 인원에게 전달한다
void ChatRPC(string msg)
{
bool isInput = false;
for (int i = 0; i < ChatText.Length; i++)
{
if (ChatText[i].text == "") //채팅 텍스트 배열이 비어있다면
{
isInput = true;
ChatText[i].text = msg;
break;
}
}
if (!isInput) // 꽉차면 한칸씩 위로 올림
{
for (int i = 1; i < ChatText.Length; i++) ChatText[i - 1].text = ChatText[i].text; //위로 올려서 덮어쓰기
ChatText[ChatText.Length - 1].text = msg; //새로 들어온 텍스트는 제일 밑에
}
}
void RoomRenewal() //방 정보를 갱신하는 함수
{
ListText.text = "";
for (int i = 0; i < PhotonNetwork.PlayerList.Length; i++)
ListText.text += PhotonNetwork.PlayerList[i].NickName + "\n";
RoomNameText.text = PhotonNetwork.CurrentRoom.Name;
RoomCountText.text = "Current: " + PhotonNetwork.CurrentRoom.PlayerCount + " / Max: " + PhotonNetwork.CurrentRoom.MaxPlayers;
}
public override void OnPlayerEnteredRoom(Player newPlayer) //누군가 방에 들어오면 자동으로 호출되는 함수
{
RoomRenewal();
ChatRPC("<color=yellow>" + newPlayer.NickName + " joined the chatting.</color>");
}
public override void OnPlayerLeftRoom(Player otherPlayer) //누군가 방을 나가면 호출
{
RoomRenewal();
ChatRPC("<color=red>" + otherPlayer.NickName + " left the chatting.</color>");
}
}
RPC로 사용할 함수 위에 [PunRPC]를 꼭 써줘야 사용이 가능하다 (using문도 써주기)
PV.RPC("RPC함수이름", RPCTarget.타겟대상, 매개변수);
RPCTarget.?
MasterClient: 서버만 실행해!
All: 모두 다 실행
Others: 나빼고 다 실행
PhotonView 컴포넌트: 네트워크를 통해 동기화될 모든 게임 오브젝트에 필요한 컴포넌트
viewID: 네트워크 상에서 구별 가능한 식별자
isMine은 본인이 서버라면 true이다
Controller는 서버의 권한을 갖고있는 사람이다
OnPhotonSerializeView()
PhotonView 컴포넌트를 사용해 로컬과 리모트 사이에서 어떤 값을 어떻게 주고받을지를 결정
stream을 통해 송신인지 수신인지 판단
PhotonView가 update처럼 계속 OnPhotonSerializeView를 호출
IPunObservable 인터페이스를 상속
// 주기적으로 자동 실행되는, 동기화 메서드
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) {
// 로컬 오브젝트라면 쓰기 부분이 실행됨
if (stream.IsWriting)
{
// 남은 탄약수를 네트워크를 통해 보내기
stream.SendNext(ammoRemain);
// 탄창의 탄약수를 네트워크를 통해 보내기
stream.SendNext(magAmmo);
// 현재 총의 상태를 네트워크를 통해 보내기
stream.SendNext(state);
}
else
{
// 리모트 오브젝트라면 읽기 부분이 실행됨
// 남은 탄약수를 네트워크를 통해 받기
ammoRemain = (int) stream.ReceiveNext();
// 탄창의 탄약수를 네트워크를 통해 받기
magAmmo = (int) stream.ReceiveNext();
// 현재 총의 상태를 네트워크를 통해 받기
state = (State) stream.ReceiveNext();
}
}
'공부 > Unity' 카테고리의 다른 글
[Unity] Photon Network 포톤 네트워크 Lobby manager 예시 (2) | 2025.06.24 |
---|---|
[Unity] Oculus Integration / 컨트롤러 연결 및 조준선 표시 (2) | 2025.06.19 |
[Unity] NavMesh에서 랜덤한 포인트 얻기 (0) | 2025.06.16 |
[Unity] 유니티 Monobehaviour의 생명주기(Lifecycle) / Monobehaviour의 특징 (0) | 2025.06.12 |
[Unity] 유용한 링크 모음 (1) | 2025.06.09 |