레트로의 유니티6 : NGO 네트워크 게임 PONG - 3

댓글 0
댓글을 작성하려면 로그인이 필요합니다.
아직 댓글이 없습니다. 첫 번째 댓글을 작성해보세요!

댓글을 작성하려면 로그인이 필요합니다.
아직 댓글이 없습니다. 첫 번째 댓글을 작성해보세요!
네트워크 트랜스폼
넷코드에는 트랜스폼 동기화를 담당하는 네트워크 트랜스폼(NetworkTransform) 컴포넌트가 있다.

하지만 네트워크 트랜스폼 컴포넌트의 위치를 변경할 수 있는 권한은 서버만 가지고 있다. 따라서 네트워크 트랜스폼 컴포넌트를 사용할 경우 플레이어 캐릭터의 위치는 다음 과정을 통해 변경해야 한다.
이 방법은 변조의 위험이 적어 안전하지만, 위치 변경이 해당 네트워크 오브젝트를 소유한 클라이언트가 아닌 서버를 통해 이루어져서 구현이 비직관적일 수 있다. 또한 지연 시간이 길어질 수 있으며 조작감이 상대적으로 나쁠 수 있다.
퐁 게임에서는 간단한 구현과 나은 조작감을 위해 서버가 아니라고 해도 네트워크 오브젝트를 소유한 클라이언트라면 해당 게임 오브젝트의 위치를 변경할 수 있도록 위치 동기화 컴포넌트를 직접 구현함.
NetworkVariable
NetworkVariable<T>는 서버와 클라이언트 사이에서 상태를 자동으로 동기화하는 변수 컨테이너
일반 변수와 달리 값이 변경되면 연결된 클라이언트에 전달되고, 나중에 접속한 클라이언트도 현재 값을 받을 수 있습니다.
| 구분 | 일반 변수 | NetworkVariable<T> |
|---|---|---|
| 값 저장 | 현재 게임 인스턴스에만 저장 | 서버와 클라이언트에서 공유 |
| 변경 전파 | 직접 구현 | 자동 동기화 |
| 늦게 접속한 클라이언트 | 이전 상태를 알 수 없음 | 현재 값 자동 수신 |
| 변경 감지 | 직접 확인 | OnValueChanged 제공 |
| 읽기·쓰기 권한 | 제한 없음 | 서버 또는 소유자 권한 설정 |
| 사용 위치 | 어디서든 가능 | 일반적으로 NetworkBehaviour 내부 |
PositionSync 스크립트에서도 NetworkVariable 로 위치를 동기화시킴
// 위치값 동기화를 위한 네트워크 변수
public NetworkVariable<Vector2> networkPosition
= new NetworkVariable<Vector2>(
readPerm: NetworkVariableReadPermission.Everyone,
writePerm: NetworkVariableWritePermission.Owner);
읽기 권한 : NetworkVariableReadPermission.Everyone - 모두가 읽기 가능
쓰기 권한 : NetworkVariableWritePermission.Owner - 소유자만 쓰기 가능 (소유권을 가진 클라이언트)
// 플레이어의 위치를 동기화하기 위한 컴포넌트
public class PositionSync : NetworkBehaviour
{
private Vector2 _lastPosition; // 마지막으로 동기화된 위치
// 위치값 동기화를 위한 네트워크 변수
public NetworkVariable<Vector2> networkPosition
= new NetworkVariable<Vector2>(
readPerm: NetworkVariableReadPermission.Everyone,
writePerm: NetworkVariableWritePermission.Owner);
private void FixedUpdate()
{
if (IsOwner)
{
// 로컬 클라이언트가 소유자인 경우
// 마지막으로 동기화된 위치와 현재 위치가 일정 거리 이상 차이가 나면
if (Vector2.Distance(_lastPosition, transform.position) > 0.001f)
// 아주 미세한 위치 변화에도 매번 새로운 값을 써서 동기화하면 대역폭과 성능을 쓸데없이 낭비하게 되기 때문에, 직전 동기화한 위치와 현재 위치 사이의 거리가 0.001f보다 클 때만 동기화함.
{
// 위치 동기화
_lastPosition = (Vector2)transform.position;
networkPosition.Value = _lastPosition;
}
}
else
{
// 로컬 클라이언트가 소유자가 아닌 경우
// 전달받은 동기화된 위치로 이동
transform.position = (Vector3)networkPosition.Value;
}
}
}
Pong에서 채택한 오브젝트의 위치 동기화 방법
네트워크 게임에서는 오브젝트를 움직이는 로직과 그 결과를 다른 클라이언트에 전달하는 로직을 분리할 수 있다. 이 프로젝트에서는 PlayerPaddle과 Ball이 실제 이동을 계산하고, PositionSync가 계산된 최종 위치를 네트워크로 동기화한다.
| 스크립트 | 역할 | 실행 권한 |
|---|---|---|
PlayerPaddle | 입력을 받아 패들의 이동 방향과 위치 계산 | 해당 패들의 소유자(IsOwner) |
Ball | 공의 이동, 충돌, 반사, 속도 및 득점 처리 | 서버(IsServer) |
PositionSync | 변경된 위치를 전송하고 다른 클라이언트에 적용 | 소유자는 전송, 비소유자는 수신 |
입력·물리 계산
(PlayerPaddle / Ball)
↓
transform.position 변경
↓
PositionSync가 위치를 NetworkVariable에 기록
↓
다른 클라이언트가 전달받은 위치를 화면에 적용
PositionSync는 입력이나 공의 이동 방향을 동기화하는 것이 아니라, 이동 로직이 실행된 결과인 위치 값만 동기화한다. 따라서 패들의 입력 처리는 패들 소유자만 수행하고, 공의 물리 계산은 서버만 수행한다. 나머지 클라이언트는 같은 이동을 다시 계산하지 않고 전달받은 위치를 표시한다.
핵심:
PlayerPaddle과Ball은 어떻게 움직일지 결정하고,PositionSync는 그 결과를 모든 클라이언트가 동일하게 보도록 전달한다.
1:51 PM
XR을 활용한 게임 개발 3기(유니티) 수강생입니다. 곧 수료 하지만 앞으로 이곳에 가끔 저의 개발 경험이 나 지식 기록할까 합니다. 더 나아가 이 사이트가 제 개인위키의 역할을 할 수 있으면 좋겠습니다. 한국 게임 시장을 흔들겠습니다

게임 광고 수익은 단순히 광고를 붙이는 것이 아니라, 여러 광고 네트워크를 경쟁시켜 가장 높은 수익을 만드는 구조입니다.

안녕하세요. 플밍 4기 입니다. 게임 개발을 배우기 전 네트워크 엔지니어 도메인에서 익히고 배웠던 네트워크 이론에 대한 기초 입니다. 학습에 도움이 되길 바라며 공유 드립니다.
XR을 활용한 게임 개발 3기(유니티) 수강생입니다. 곧 수료 하지만 앞으로 이곳에 가끔 저의 개발 경험이 나 지식 기록할까 합니다. 더 나아가 이 사이트가 제 개인위키의 역할을 할 수 있으면 좋겠습니다. 한국 게임 시장을 흔들겠습니다



게임 광고 수익은 단순히 광고를 붙이는 것이 아니라, 여러 광고 네트워크를 경쟁시켜 가장 높은 수익을 만드는 구조입니다.


안녕하세요. 플밍 4기 입니다. 게임 개발을 배우기 전 네트워크 엔지니어 도메인에서 익히고 배웠던 네트워크 이론에 대한 기초 입니다. 학습에 도움이 되길 바라며 공유 드립니다.