This document is about: FUSION 2
SWITCH TO

TickTimer

소개

특정 로직을 트리거 하기 전에 일정 시간 동안 대기하는 것이 유용할 때가 많습니다. TickTimer는 Fusion에서 이를 안전하고, 편리하며, 대역폭 효율적으로 처리할 수 있는 방법을 제공합니다. 이름과 달리, TickTimer는 실제 타이머가 아니라 대상 틱 값을 저장하고 현재 시뮬레이션 틱을 사용하여 검사를 수행하는 구조체입니다.

TickTimer는 현재 틱(NetworkRunner에서 제공)과 초기화 시 저장된 대상 틱을 사용하여 일반적인 타이머와 유사하게 작동하며 다음과 같은 질문에 답할 수 있습니다:

  • 타이머가 만료되었습니까?
  • 타이머가 실행 중입니까?
  • 얼마나 많은 시간(틱)이 남아 있습니까?

TickTimer는 float 또는 int 값을 증가/감소시키는 대신 대상 틱을 사용하므로 네트워크 상태에서 [Networked] 속성으로 포함될 때 변경되지 않아 대역폭을 절약할 수 있습니다.

참고: TickTimer.CreateFromSeconds()로 초기화할 때도 TickTimer는 대상 틱을 사용합니다. 이와 틱 속도를 고려할 때, 예를 들어 TickTimer.CreateFromSeconds(1.37f)와 같이 초 단위로 생성된 경우, 계산된 대상 틱이 약간의 정확도를 잃을 수 있습니다.

API

  • CreateFromSeconds: 제공된 값을 사용하여 대상 틱을 계산하고 새로운 TickTimer를 반환합니다.
  • CreateFromTicks: 제공된 틱(ticks) 값을 사용하여 대상 틱을 계산하고 새로운 TickTimer를 반환합니다.
  • RemainingTime: TickTimer가 만료될 때까지 남은 시간을 단위로 반환합니다.
  • RemainingTicks: TickTimer가 만료될 때까지 남은 시간을 단위로 반환합니다.
  • IsRunning: 현재 시뮬레이션 틱보다 대상 틱이 크면 true를 반환합니다.
  • Expired: TickTimer가 실행 중이며, 대상 틱이 현재 시뮬레이션 틱보다 작거나 같은 경우 true를 반환합니다.
  • ExpiredOrNotRunning: TickTimerdefault, TickTimer.None이거나 실행 중이며 대상 틱이 현재 시뮬레이션 틱보다 작거나 같은 경우 true를 반환 합니다.

TickTimer 재설정

TickTimer는 대상 틱을 초과한 시뮬레이션 틱 이후 매 틱마다 만료 상태를 true로 반환합니다. 이를 한 번만 얻으려면 조건이 true로 평가된 첫 번째 틱에서 TickTimer를 재설정하는 것이 유용합니다. 이는 TickTimer.None 또는 default로 설정하여 수행할 수 있습니다.

C#

[Networked] TickTimer timer { get; set; }

void FixedUpdateNetwork()
{
  if (timer.Expired(Runner))
  {
    // Execute Logic

    // Reset timer
    timer = TickTimer.None;
    // alternatively: timer = default.

    Debug.Log("Timer Expired");
  }
}

사용자 정의 기능 생성

TickTimer의 간단한 특성 덕분에 사용자 정의 버전을 만들어 더 많은 또는 다른 기능을 구현할 수 있습니다. 아래 예제에서는 타이머가 생성된 이후 경과된 틱을 계산하고 정규화된 값을 반환하는 기능을 추가한 간단한 사용자 정의 TickTimer를 보여줍니다.

참고: 다음 코드는 사용자 정의 기능을 보여주기 위한 간단한 버전의 TickTimer입니다.

C#

public struct CustomTickTimer : INetworkStruct
{
  private int _target;
  private int _initialTick;

  public bool Expired(NetworkRunner runner) => runner.IsRunning && _target > 0
    && (Tick) _target <= runner.Simulation.Tick;

  public bool IsRunning => _target > 0;

  public static CustomTickTimer CreateFromTicks(NetworkRunner runner, int ticks)
  {
    if (runner == false || runner.IsRunning == false)
      return new CustomTickTimer();

    CustomTickTimer fromTicks = new CustomTickTimer();
    fromTicks._target = (int) runner.Simulation.Tick + ticks;
    fromTicks._initialTick = runner.Simulation.Tick;
    return fromTicks;
  }

  public float NormalizedValue(NetworkRunner runner)
  {
    if (runner == null || runner.IsRunning == false || IsRunning == false)
      return 0;

    if (Expired(runner))
      return 1;

    return ElapsedTicks(runner) / (_target - (float)_initialTick);
  }

  public int ElapsedTicks(NetworkRunner runner)
  {
    if (runner == false || runner.IsRunning == false)
      return 0;

    if (IsRunning == false || Expired(runner))
      return 0;

    return runner.Simulation.Tick - _initialTick;
  }
}

경과된 틱 계산

타이머가 생성된 이후 경과된 틱 수를 가져오려면 초기 틱 값을 NetworkRunner의 현재 틱에서 빼십시오.

C#

public int ElapsedTicks(NetworkRunner runner)
{
  if (runner == false || runner.IsRunning == false)
      return 0;

  if (IsRunning == false || Expired(runner))
    return 0;

  return runner.Simulation.Tick - _initialTick;
}

0에서 1 사이의 정규화된 값

타이머의 현재 진행 상황에 대한 0에서 1 사이의 정규화된 float 값을 반환하려면, 경과된 틱 수를 타이머가 계산 중인 총 틱 수로 나누십시오.

C#

public float NormalizedValue(NetworkRunner runner)
{
  if (runner == null || runner.IsRunning == false || IsRunning == false)
    return 0;

  if (Expired(runner))
    return 1;

  return ElapsedTicks(runner) / (_target - (float)_initialTick);
}

이제, CustomTickTimer를 사용하여 위 값을 표시할 수 있습니다.

C#

[Networked]
public CustomTickTimer MyTickTimer { get; set; }

public void StartTimer()
{
  if (Runner.IsServer)
  {
    MyTickTimer = CustomTickTimer.CreateFromTicks(Runner, 120);
  }
}

public override void FixedUpdateNetwork()
{
  Debug.Log($"Elapsed {MyTickTimer.ElapsedTicks(Runner)} ticks.");
  Debug.Log($"Normalized Value {MyTickTimer.NormalizedValue(Runner)}.");

  if (MyTickTimer.Expired(Runner))
  {
    // Execute Logic

    // Reset timer
    MyTickTimer = default;

    Debug.Log("Timer Finished on tick: " + Runner.Simulation.Tick);
  }
}
Back to top