김산나
[멋쟁이사자처럼부트캠프 유니티 게임 개발 7기] 2026년 5월 27일 회고록 - Unity Netcode 2 본문
2026_05_27 강의 요약본
1. 네트워크 변수
네트워크로 동기화되는 변수. 선언 방법은 다음과 같다.
public class TempController : NetworkBehaviour
{
// 네트워크에서 동기화되는 변수
NetworkVariable<int> randNum = new NetworkVariable<int>(1,
NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner);
// 괄호 안 = Default 값, 읽을 수 있는 권한 범위, 쓸 수 있는 권한 범위
}
NetworkVariable<자료형>으로 선언한다.
권한을 직접 지정하지 않는 경우, 읽기는 Everyone, 쓰기는 Server(Host)가 기본으로 세팅된다.
* 자료형은 기본 형식(숫자), 벡터, 색상, 레이, enum...값을 바로 넣는 타입의 변수들, 구조체, 길이가 고정된 string을 전달할 수 있다. - FixedString32Bytes ~ FixedString4096Bytes까지.
void Update()
{
Debug.Log($"owner id: "+ OwnerClientId + "\nRandom number: "+ randNum.Value);
if(!IsOwner) return; // 주인이 아니라면 하단 코드 실행 금지
// T키를 입력 시 랜덤 숫자 추첨
if(Input.GetKeyDown(KeyCode.T))
{
randNum.Value = Random.Range(0, 100);
}
}
테스트 코드를 작성한다.
T키를 누르면 랜덤 숫자를 추첨한다.
권한 설정이 기본인 읽기는 Everyone, 쓰기는 Server인 경우, 호스트를 제외한 유저는 번호 추첨을 할 수 없다.
하지만 권한을 수정하여 NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner로 변경한다면
모든 유저가 수정한 것을 확인할 수 있다.
네트워크 변수는 서버의 유일한 변수를 생성하는 것이 아닌, 유저마다 다른 값을 갖는다.
플레이어 1은 39를 추첨했고, 플레이어 2는 35를 추첨했다.

* 네트워크 구조체
public class TempController : NetworkBehaviour
{
struct SomeData : INetworkSerializable
{
public int someInt;
public bool someBool;
public void NetworkSerialize<T> (BufferSerializer<T> serializer) where T : IReaderWriter
{
serializer.SerializeValue(ref someInt);
serializer.SerializeValue(ref someBool);
}
}
NetworkVariable<SomeData> randNum = new NetworkVariable<SomeData>(new SomeData { someInt = 1, someBool = false },
NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner);
// 괄호 안 = Default 값, 읽을 수 있는 권한 범위, 쓸 수 있는 권한 범위
void Update()
{
Debug.Log("owner id: "+ OwnerClientId + "\nRandom number: "+
randNum.Value.someInt + "\nBool: " + randNum.Value.someBool);
if(!IsOwner) return;
if(Input.GetKeyDown(KeyCode.T))
{
randNum.Value = new SomeData { someInt = Random.Range(0, 100), someBool = true };
}
}
}



플레이어 1, 2 둘 다 정상적으로 찍히는 걸 볼 수 있다.
* 네트워크 문자열 변수
// 네트워크 변수 - String
NetworkVariable<FixedString32Bytes> netString = new NetworkVariable<FixedString32Bytes>
("", NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner);
...
void Update()
{
Debug.Log("String: " + netString.Value + "\nowner id: "+ OwnerClientId + "\nRandom number: "+
randNum.Value.someInt + "\nBool: " + randNum.Value.someBool);
...
if(Input.GetKeyDown(KeyCode.R))
{
netString.Value = "가나다라마바사";
}
}

2. RPC(Remote Procedure Call)
Host, Client가 다른 유저의 요소를 호출하기 위한 기술. 사용법은 다음과 같다.
[Rpc(SendTo.Server)]
private void TestServerRPC(int number, string msg, RpcParams rpcParams = default)
{
Debug.Log("called Owner ID" + OwnerClientId + "Received number " + number + "and message: " + msg
+ "sender client ID: " + rpcParams.Receive.SenderClientId);
}
[Rpc(SendTo.대상)] ... 메서드 작성 ...
void Update()
{
if(Input.GetKeyDown(KeyCode.R))
{
TestServerRPC(Random.Range(0, 100), "Hello Server!", new RpcParams());
}
}
테스트 코드 작성.

위 예시 코드는 Server(Host)로만 전송하는 RPC 예제이다. 특정 유저에게 보내려면 어떻게 해야 할까?
[Rpc(SendTo.SpecifiedInParams)] // 파라미터로 받을 대상 직접 지정
void TestClientRpc(RpcParams rpcParams = default)
{
Debug.Log("called Owner ID" + OwnerClientId + "sender client ID: " + rpcParams.Receive.SenderClientId);
}
SendTo.(대상) 대상에 특정 파라미터를 받겠다고 선언하고, 매개변수로 파라미터 값을 받으면 된다.
...
if(Input.GetKeyDown(KeyCode.Alpha1))
{
TestClientRpc(RpcTarget.Single(0, RpcTargetUse.Temp));
// 0번을 타겟으로 하겠다.
}
if(Input.GetKeyDown(KeyCode.Alpha2))
{
TestClientRpc(RpcTarget.Single(1, RpcTargetUse.Temp));
// 1번을 타겟으로 하겠다.
}
if(Input.GetKeyDown(KeyCode.Alpha3))
{
TestClientRpc(RpcTarget.Single(2, RpcTargetUse.Temp));
// 2번을 타겟으로 하겠다.
}
...



<응용>
특정 키를 눌러 플레이어 자신의 색상을 랜덤하게 변경한다.
[Rpc(SendTo.Everyone)]
void TestChangeColorRPC(Color color, RpcParams rpcParams = default)
{
transform.GetChild(0).GetComponent<Renderer>().material.color = color;
}
void Update()
{
if(!IsOwner) return;
if(Input.GetKeyDown(KeyCode.Alpha1))
{
if(OwnerClientId == 0)
{
Color randomColor = Random.ColorHSV();
TestChangeColorRPC(randomColor);
}
}
if(Input.GetKeyDown(KeyCode.Alpha2))
{
if(OwnerClientId == 1)
{
Color randomColor = Random.ColorHSV();
TestChangeColorRPC(randomColor);
}
}
if(Input.GetKeyDown(KeyCode.Alpha3))
{
if(OwnerClientId == 2)
{
Color randomColor = Random.ColorHSV();
TestChangeColorRPC(randomColor);
}
}
}
* IsOwner 판정을 통해 플레이어 자신의 오브젝트만 제어하도록 한다.
* Alpha0 vs KeyPad0: 전자는 키보드 상단 키패드이고, 후자는 텐키이다.
* Random.ColorHSV(): 랜덤 컬러 함수
* transform.GetChild(0).GetComponent<Renderer>().material.color = color
자식의 색상을 변경하는 코드. (3D 오브젝트 기준) 플레이어 오브젝트 구조가 다음과 같아 이렇게 짠다.

결과

플레이어가 특정 버튼을 누를 때, 자신의 캐릭터 색상만 변경할 수 있다.
===========================================================
