Forecast Vehicle Physics 고급
이 샘플은 개발 중인 Fusion SDK 2.1.0을 사용하며, Gaming Circle 회원만 얼리 액세스가 가능합니다.
개요
Forecast Vehicle Physics 고급
샘플은 Forecast Vehicle Physics 기초
튜토리얼의 결과물을 확장한 버전입니다.
이 샘플은 튜토리얼을 여러 가지 방식으로 확장합니다:
- 상호작용 가능한 물리 오브젝트
- 상태 권한의 자동 전환
- 차량 리셋 기능
이 샘플은 플레이어가 달성해야 할 특정 목표나 과제가 정해져 있지 않습니다. 다양한 장애물을 주행하거나 주변을 탐험하고 물리 오브젝트와 상호작용하며 자유롭게 실험해 보세요.

다운로드
Version | Release Date | Download |
---|---|---|
2.1.0 | 8월 12, 2025 | Advanced Forecast Vehicle Physics 2.1.0 |
샘플 시작하기
샘플은 곧바로 공유 모드 게임을 시작하며, 플레이어의 차량이 월드에 스폰 됩니다. 간단한 조작 설명 후 화면을 클릭하면 카메라가 차량을 따라 내려옵니다.
다른 플레이어들도 같은 월드에 별도의 차량으로 합류할 수 있습니다.
차량이나 오브젝트의 측면에는 해당 오브젝트에 대한 권한을 가진 플레이어의 Player ID가 표시됩니다. 이는 플레이 중 누가 어떤 오브젝트를 제어하는지 확인하는 데 유용합니다.
Physics Forecast
이 샘플의 Network Project Config Asset
에서는 Physics Forecast
가 활성화되어 있습니다. 이 기능이 활성화되면 Forecast Physics 외삽이 가능해집니다. 비활성화되면 물리는 원격 시간(Remote Time)으로 동기화됩니다. 활성화 시 클라이언트 간 오브젝트와 속도의 로컬 시간 동기화가 더욱 정밀해집니다.
상호작용 가능한 물리 오브젝트
개요
이 샘플에는 두 가지 물리 오브젝트가 배치되어 있습니다:
- 큐브: 상대적으로 무거우며 차량이 간신히 밀거나 넘어뜨릴 수 있습니다.
- 공: 큰 크기의 비교적 가벼운 공으로, 차량이 쉽게 밀 수 있습니다.
두 오브젝트 모두 다음 과정을 거쳐 생성되었습니다:
- 씬 계층 뷰에서
3D Object > Sphere/Cube
를 생성합니다. 이는Mesh
와Collider
가 포함된GameObject
를 생성합니다. RigidBody
컴포넌트를 추가하고 설정을 원하는 대로 조정합니다.NetworkTransform
과NetworkObject
Fusion 컴포넌트를 추가합니다.
이 세 단계를 거치면 새 오브젝트는 네트워크에 연결되어 플레이어들이 상호작용할 수 있으며 위치가 동기화됩니다. 단, 기본적으로 오브젝트에 대한 권한은 첫 번째로 접속한 플레이어에게 있으며, 그 플레이어가 떠나면 오브젝트는 삭제됩니다. 이 기본 동작은 특정 경우에 유용하지만, 이 샘플에서는 적합하지 않습니다.
이를 해결하기 위해 NetworkObject
컴포넌트에서 Is Master Client Object
옵션을 체크할 수 있습니다. 이 경우 권한은 항상 Shared Mode Master Client
로 전환되며, 첫 번째 플레이어가 떠나더라도 오브젝트는 삭제되지 않고 새로운 Shared Mode Master Client
가 권한을 이어받습니다.
그러나 본 샘플에서는 Ball과 Cube에 대해 Is Master Client Object
기능에 의존하지 않고, 권한을 전환하는 별도의 로직을 적용했습니다.
권한 자동 전환
큐브와 공은 차량과 충돌 시 물리적으로 상호작용합니다. 특히 공은 가볍기 때문에 차량 위치, 조향, 속도 변화에 매우 민감하게 반응합니다. 네트워크 지연이나 물리 시뮬레이션 차이로 인해 권한을 가진 플레이어와 다른 클라이언트 간 동작이 약간 다를 수 있습니다.
이 샘플은 공과 실제 상호작용하는 플레이어가 최적의 경험을 하도록 설계되었습니다. 이를 위해 오브젝트와의 거리 기반으로 권한을 전환하는 로직을 추가했습니다. 결과적으로 대부분의 경우 오브젝트와 상호작용하는 플레이어가 자신의 차량과 오브젝트 모두에 대한 권한을 가지게 되며, 물리 상호작용 전반에 권한을 갖게 됩니다. 이렇게 하면 다른 권한자의 보정에 영향을 받지 않고 가장 자연스러운 플레이 경험을 제공합니다.
이 단순한 접근 방식은 DistanceBasedAuthority.cs
스크립트에 구현되어 있으며, NetworkBehaviour
컴포넌트로 작성되어 Object
와 Runner
에 접근할 수 있습니다.
이 스크립트가 작동하려면 Object의 NetworkObject
컴포넌트에서 다음 옵션이 설정되어야 합니다:
Is Master Client Object
→ FalseAllow State Authority Override
→ TrueDestroy When State Authority Leaves
→ False
로직은 CarSpawner.cs에서 설정된 플레이어 오브젝트 참조를 기반으로 하며, 로컬 플레이어와 권한 플레이어의 차량과 오브젝트 간 거리를 비교하여 가까운 경우 권한을 전환합니다.
C#
// Find the player object of the player that currently has authority
var authorityPlayerObject = Runner.GetPlayerObject(Object.StateAuthority);
...
// Find the player object of the local player
var localPlayerObject = Runner.GetPlayerObject(Runner.LocalPlayer);
노트: 이것은 스포너 스크립트에서 플레이어의 Player Object가 자동차로 설정되었다는 사실에 의존합니다. 자세한 내용은 CarSpawner.cs
를 참고하세요.
자동차에 대한 참조가 확인되면, 해당 객체와의 거리를 비교하고 더 가까운 경우 로컬 플레이어에게 권한을 전환하면 됩니다.
C#
// Compare local player object distance to this object with the distance to the auth player object from this object
// Optimisation: As we are only comparing the distances we can avoid using the square route used when calling Vector3.Distance()
// and instead just use sqrMagnitude.
float playerObjectWithAuthorityDistanceSquared = (transform.position - authorityPlayerObject.transform.position).sqrMagnitude;
float localPlayerObjectDistanceSquared = (transform.position - localPlayerObject.transform.position).sqrMagnitude;
// Request authority over the this object if the local player object is the closest
if (localPlayerObjectDistanceSquared < playerObjectWithAuthorityDistanceSquared) {
Object.RequestStateAuthority();
}
노트: 초기화 처리, 특수한 경우 처리, 그리고 두 대의 자동차가 객체로부터 동일한 거리에 있을 때 권한이 계속 바뀌는 것을 방지하는 방법에 대해서는 스크립트를 참고하세요.
오브젝트 및 차량에 Player ID 표시
PlayerIDTextSetter.cs
스크립트는 오브젝트와 차량에 권한을 가진 플레이어의 ID를 표시하는 역할을 합니다. 큐브와 공에는 플레이어가 일반 플레이어인지, Shared Mode Master Client
인지에 따라 P
또는 M
이 표시됩니다. 차량의 경우 번호판에 PLYR
또는 MSTR
이 표시됩니다.
이 스크립트는 두 가지 네트워크 속성을 사용합니다: _stateAuthorityPlayerID
와 _stateAuthorityPlayerIsSharedModeMasterClient
. 권한을 가진 플레이어가 FixedNetworkUpdate()
에서 값을 설정하고, 모든 클라이언트에 동기화되어 동일한 정보를 표시할 수 있습니다.
각 속성은 OnChangedRender
특성을 사용하여 값이 변경될 때 메서드(OnPlayerIDChanged
)를 호출하고, 연결된 TextMeshPro
요소를 업데이트합니다.
C#
// The player ID and the master client status is networked so that all clients can display the same values.
// Only the player with the state authority over the network object can set these values.
[Networked, OnChangedRender(nameof(OnPlayerIDChanged))]
int _stateAuthorityPlayerID { get; set; }
[Networked, OnChangedRender(nameof(OnPlayerIDChanged))]
NetworkBool _stateAuthorityPlayerIsSharedModeMasterClient { get; set; }
리셋 기능
R
키를 누르면 차량이 시작 지점으로 리셋됩니다. 이는 NetworkTransform.Teleport()
메서드를 사용하여 구현됩니다. 이 메서드를 사용해야 모든 클라이언트에서 즉시 차량이 "순간 이동"되며, 단순히 Transform이나 Rigidbody 위치를 조정하는 경우에는 권한자의 화면에서는 순간 이동처럼 보이더라도 다른 클라이언트에서는 보정되어 여러 프레임에 걸쳐 이동하게 됩니다.
C#
// Reset method to teleport the car back to its starting position
void Reset() {
if (TryGetComponent(out NetworkTransform nt)) {
nt.Teleport(_initialSpawnPosition, _initialSpawnRotation);
// Remove all velocity when resetting
_rigidBody.velocity = Vector3.zero;
_rigidBody.angularVelocity = Vector3.zero;
}
}
Back to top