본문 바로가기

Unity/Articles

Unity: UniRx로 NavMeshAgent의 도착 콜백 생성하기

 

neuecc/UniRx: Reactive Extensions for Unity (github.com)

 

neuecc/UniRx

Reactive Extensions for Unity. Contribute to neuecc/UniRx development by creating an account on GitHub.

github.com

 

 

내장된 NavMeshAgent에는 따로 도착 콜백이 존재하지 않아 UniRx를 이용해서 임의로 콜백을 호출하도록 구현했습니다. 멈춘상태인지를 판단하는 IsStopped 함수를 만들고, Start에서 Update루프에서 확인하도록 등록해주었습니다.

 

public class PlayerCharacter: Character {
  public NavMeshAgent agent =
    default;

  public Action < eCharacterMoveState > onSprintChange;

  private IDisposable arriveStream =
    default;
  private Action onArriveCallback =
    default;

  private void Start() {

    arriveStream = this.UpdateAsObservable()
      .Select(IsStopped)
      .DistinctUntilChanged()
      .ThrottleFrame(3)
      .Where(stopped => stopped)
      .Subscribe(stopped => onArriveCallback?.Invoke())
      .AddTo(this);
  }

  private bool IsStopped(Unit unit) {
    if (!agent.pathPending) {
      if (agent.remainingDistance <= agent.stoppingDistance) {
        if (!agent.hasPath || agent.velocity.sqrMagnitude == 0 f) {
          return true;
        }
      }
    }

    return false;
  }
}

 

외부에서 agent.SetDestination 함수를 통해 목적지를 지정하고 이동하는 경우 도착시 onArrivedCallback 액션이 호출됩니다.

 

UpdateAsObservable() : Update루프에서 해당 로직을 수행합니다.

Select : IsStopped 함수를 수행하여 이동중인지 판단합니다.

DistincUntilChanged : 이동중인지 여부가 바뀔 때만 통과합니다.

ThrottleFrame : n 프레임만큼 값이 유지되면 통과합니다.

Where : stopped가 true 일 때만(이동 중이다가 멈춘 상태만) 통과합니다.

Subscribe : 콜백을 호출합니다.

AddTo(this) : 이 컴포넌트에 종속적으로 만듭니다. 이 컴포넌트가 파괴되면 스트림도 Dispose 됩니다.