This document is about: QUANTUM 3
SWITCH TO

フラスタム予測カリング

以下のスニペットは、Quantumエンティティにシンプルなフラスタムカリングを適用する方法を示しています。

Quantumでカリングされたエンティティは、シミュレーションの予測フレームで更新されないため、パフォーマンスが向上します。

詳細はQuantumのプロファイリングをご覧ください。

独自のカリングシステムの実装は、3つのステップに分けられます。

カスタムカリングコールバック定義

実際のカリングロジックを定義する際に使用するコールバックを宣言しておきます。

C#

namespace Quantum
{
  using Photon.Deterministic;

  partial class FrameContextUser
  {
    public delegate bool CullingDelegate(FPVector3 position);

    public CullingDelegate CullingCallback;
  }
}

カスタムカリングシステム

コールバックをトリガーする新しいシステムを作成します。
補足:SystemsConfigアセットでデフォルトで提供されている通常のカリングシステムを、このシステムに置き換える必要があります。

C#

namespace Quantum
{
  using UnityEngine.Scripting;
  using Quantum.Task;

  [Preserve]
  public unsafe class CustomCullingSystem : SystemBase
  {
    private TaskDelegateHandle _updateTask;

    public override void OnInit(Frame f)
    {
      f.Context.TaskContext.RegisterDelegate(Update, "CustomCullingSystem Update", ref _updateTask);
    }

    private void Update(FrameThreadSafe frame, int start, int count, void* arg)
    {
      var f = (Frame)frame;
      var context = f.Context;
      var filter = f.Filter<Transform3D>();
      while (filter.NextUnsafe(out var entity, out var transform))
      {
        if (context.CullingCallback(transform->Position))
        {
          f.Cull(entity);
        }
      }
    }

    protected override TaskHandle Schedule(Frame f, TaskHandle taskHandle)
    {
      if (f.IsVerified)
      {
        return taskHandle;
      }

      if (f.Context.CullingCallback != null)
      {
        var handle = f.Context.TaskContext.AddMainThreadTask(_updateTask, null);
        handle.AddDependency(taskHandle);
        return handle;
      }

      return taskHandle;
    }
  }
}

フラスタムカリングロジック

新しく作成したスクリプトにカリングロジックを実装し、上記で作成したコールバックを設定してください。

C#

namespace Quantum
{
  using Photon.Deterministic;
  using UnityEngine;

  public class FrustumPredictionCulling : QuantumSceneViewComponent
  {
    public float ProximityRadiusOverhaul = 20;

    public override void OnActivate(Frame frame)
    {
      Game.Frames.Verified.Context.CullingCallback = Callback;
    }

    private bool Callback(FPVector3 position)
    {
      var unityPosition = position.ToUnityVector3();
      var distance = (unityPosition - Camera.main.transform.position).sqrMagnitude;

      if (distance < ProximityRadiusOverhaul * ProximityRadiusOverhaul) return false;

      var normalizedPos = Camera.main.WorldToViewportPoint(unityPosition);
      if (normalizedPos.z <= 0) return true;

      if (normalizedPos.y < 0 || normalizedPos.y > 1) return true;
      if (normalizedPos.x < 0 || normalizedPos.x > 1) return true;

      return false;
    }
  }
}
Back to top