Prediction
Network Transform의 Interpolation Data Source를 Predicted로 하고 Interpolation Space를 World로 한다.
- Interpolation Target을 분리해 놓은 이유 : Render는 유니티의 Update에서 불리고 Interpolation으로 계속 그려줘야한다. 그러나 이동 입력은 FixedUpdateNetwork에서 불리기 때문에 둘의 단위가 달라서 구분해 준 것이다.
TickTimer를 설정하기 위해 NetworkedAttribute의 기본 생성자인 [Networked] 를 속성으로 부여했다.
FixedUpdateNetwork에서 TIckTimer.Expired(NetworkRunner Runner)가 다 되면 NetworkRunner.Despawn(Network Object)으로 NetworkObject를 파괴하고 안 되면 앞 쪽으로 이동하게 한다.
Init() 함수에서 TickTimer.CreateFromSeconds(NetworkRunner runner, float delayInSeconds)로 Senconds에 대해 타겟의 Tick을 생성하고 반환한다.
public class Ball : NetworkBehaviour
{
[Networked] TickTimer Life { get; set; }
public override void FixedUpdateNetwork()
{
if (Life.Expired(Runner))
{
Runner.Despawn(Object);
}
else
{
transform.position += 5 * transform.forward * Runner.DeltaTime;
}
}
public void Init()
{
Life = TickTimer.CreateFromSeconds(Runner, 5.0f);
print(Life.TargetTick);
}
}
PhotonInstantiate 스크립트
NetworkInputData.MOUSEBUTTON1로부터 mouseButton0을 Set해준다.
public void OnInput(NetworkRunner runner, NetworkInput input)
{
var data = new NetworkInputData();
if (Input.GetKey(KeyCode.W))
data.direction += Vector3.forward;
if (Input.GetKey(KeyCode.S))
data.direction += Vector3.back;
if (Input.GetKey(KeyCode.A))
data.direction += Vector3.left;
if (Input.GetKey(KeyCode.D))
data.direction += Vector3.right;
if (_mouseButton0)
{
data.buttons |= NetworkInputData.MOUSEBUTTON1;
}
_mouseButton0 = false;
input.Set(data);
}
마우스 좌클릭으로 Ball을 생성하는데 시간차를 두기 위해 Networked속성을 적용한 TickTimer를 생성하여 적용하였다.
public class Player : NetworkBehaviour
{
[SerializeField] Ball _prefabBall;
[Networked] TickTimer delay { get; set; }
NetworkCharacterControllerPrototype _cc;
Vector3 _forward;
void Awake()
{
_cc = GetComponent<NetworkCharacterControllerPrototype>();
_forward = transform.forward;
}
public override void FixedUpdateNetwork()
{
if (GetInput(out NetworkInputData data))
{
data.direction.Normalize();
_cc.Move(5 * data.direction * Runner.DeltaTime);
// OnInput에서 Set된 NetworkInputData.direction 값이 0보다 클 때
if (data.direction.sqrMagnitude > 0)
{
_forward = data.direction;
}
// NetworkRunner의 TickTimer가 도달했거나 세팅되지 않았을 때 -> 생성 빈도의 제한을 거는 것
if (delay.ExpiredOrNotRunning(Runner))
{
// NetworkInputData.MOUSEBUTTON1이 0x01이니 byte인 data.button이 1이고 &연산(둘 다 1일 때)으로 1이 될 때
if ((data.buttons & NetworkInputData.MOUSEBUTTON1) != 0)
{
delay = TickTimer.CreateFromSeconds(Runner, 0.5f);
// NetworkRunner의 바라보는 forward만큼 앞으로, 회전은 입력의 방향으로(data.direction의 방향)
// Object.InputAuthority는 누구의 입력에서 나왔는지에 대한 PlayerRef이다(PlayerID를 포함한 정보).
// Spawn하기 전에 파괴될 틱을 설정해주어야 하기 때문에(Life.CreateFromSeconds(NetworkRunner, int delayInSeconds))
// 마지막의 람다식 delegate void OnBeforeSpawned(NetworkRunner runner, NetworkObject obj)에서 Ball의 Init을 호출한다.
Runner.Spawn(_prefabBall, transform.position + _forward, Quaternion.LookRotation(_forward),
Object.InputAuthority,
(runner, o) =>
{
print("Lambda init");
o.GetComponent<Ball>().Init();
});
}
}
}
}
}
'공부 모음 > 포톤 퓨전 시작해보기' 카테고리의 다른 글
포톤 퓨전 원격 프로시져 호출(RPC) (0) | 2022.12.09 |
---|---|
포톤 퓨전 속성 변경 (0) | 2022.12.09 |
포톤 퓨전 물리 (2) | 2022.12.08 |
포톤 퓨전 시작하기, 씬 설정하기 (0) | 2022.12.07 |