미러 동기화 예제 코드
using Mirror;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class CharacterCustomize : NetworkBehaviour
{
[SerializeField] private SkinnedMeshRenderer outerwearMesh;
[SerializeField] private List<Mesh> outerwearList;
// SyncVar를 사용한 방법 - 자동 동기화
[SyncVar(hook = nameof(OnOuterwearIndexChanged))]
private int index = 0;
public void Update()
{
if(Input.GetKeyDown(KeyCode.C))
{
Set();
}
}
// UI 버튼에서 호출할 메서드 (클라이언트에서 실행)
public void Set()
{
if(isOwned)
{
// 클라이언트에서 서버로 명령 전송
CmdChangeOuterwear();
}
}
// 서버에서 실행되는 Command
[Command]
public void CmdChangeOuterwear()
{
index++;
if (index >= outerwearList.Count)
{
index = 0;
}
Debug.Log($"Server: Outerwear index changed to {index}");
}
// SyncVar Hook - 값이 변경될 때 모든 클라이언트에서 자동 호출
private void OnOuterwearIndexChanged(int oldIndex, int newIndex)
{
Debug.Log($"index{oldIndex} and {newIndex}");
if (outerwearList.Count > 0 && newIndex < outerwearList.Count)
{
outerwearMesh.sharedMesh = outerwearList[newIndex];
Debug.Log($"Client: Outerwear changed to index: {newIndex}");
}
}
최종정리
[SyncVar]만 써도 되는 경우
- 데이터 값의 동기화만 필요할 때
- 내부 로직에만 쓰이고, 표시되지도 않고, 동작도 트리거하지 않을때
[SyncVar] Hook을 써야 하는 경우
- UI를 즉시 업데이트해야 할 때
- 애니메이션/사운드/이펙트를 즉각 반응시키고 싶을 때
- 어떤 값이 바뀌었을 때만 뭔가 동작하게 하려면 Hook이 필요함
Hook의 예시
변화를 비교하기 위해 이전값과 현재값을 가지고 있음
[SyncVar(hook = nameof(OnHealthChanged))]
private int health;
void OnHealthChanged(int oldValue, int newValue)
{
healthBar.SetValue(newValue); // 클라이언트 UI 업데이트
}
[ClientRpc] / [TargetRpc]를 써야 하는 경우
동기화가 아닌 즉시 행동이 필요한 경우
- 애니메이션 재생
- 효과음/이펙트 실행
- 특정 조건에서만 실행되어야 하는 로직 등
행동을 클라이언트가 직접 수행해야 하므로 SyncVar로는 안 됨.
여러 값/복합적인 동작을 동시에 처리해야 할 경우
SyncVar는 하나의 변수에만 적용됩니다. 여러 변수/복잡한 로직을 한 번에 보내려면 ClientRpc가 효율적
특정 클라이언트에게만 호출할 때( 비공개 메시지, 개인 상태 갱신 등)