This document is about: FUSION 2
SWITCH TO

高度な使用例

以下のケースは、Interest Management アドオンの使いやすさを示し、プレイヤー体験を向上させ、ゲームを最適化する方法を示しています。

離れたエリア

一部のエリアやその中のアクションは、デフォルトのプレイヤーインタレストビューの外側でも、遠くからはっきりと見ることができます。

Custom Interest Provider

プレイヤーが塔を見ているとき、インタレストエリアがプレイヤーのインタレストに追加されることに注意してください。これは、塔オブジェクトにシンプルなスクリプトを追加することで実現されます:

C#

public class InterestByView : InterestProvider
{
    public float MaxViewAngle;
    public float MaxViewDistance;

    public override bool IsPlayerInterested(PlayerInterestView playerView)
    {
        // Compare player camera position and transform of this object.
        if (Vector3.Distance(playerView.CameraPosition, Transform.position) > MaxViewDistance)
            return false;

        // Compare player camera direction and direction from camera to this object.
        if (Vector3.Angle(playerView.CameraDirection, Transform.position - playerView.CameraPosition) > MaxViewAngle)
            return false;

        return true;
    }
}

背後からの射撃

プレイヤーのビュー/カメラの外側の広範囲を同期することは非効率的です。しかし、誰かが背後から射撃している場合、敵についての情報を受け取る必要があります。これは選択的に処理しなくてはなりません。

Shooting from behind

敵のプレイヤーが別のプレイヤーに射撃を開始し、そのプレイヤーがこちらを向いていない場合、敵プレイヤーの周囲のエリアが被害者のインタレストに追加されます。

C#

public sealed class AgentInterestView : PlayerInterestView
{
    [SerializeField]
    private PlayerInterestConfig _shootInterest = new PlayerInterestConfig();

    public void UpdateShootInterestTargets()
    {
        List<PlayerInterestView> otherPlayerViews = new List<PlayerInterestView>();
        float maxViewAngleCos = Mathf.Cos(_shootInterest.MaxViewAngle * Mathf.Deg2Rad);

        // Filter all players by view => need to get all players in front of this player.
        GlobalInterestManager globalInterestManager = Runner.GetGlobalInterestManager();
        globalInterestManager.GetPlayerViews(otherPlayerViews, FilterPlayersByView, this, _shootInterest.MinViewDistance * _shootInterest.MinViewDistance, _shootInterest.MaxViewDistance * _shootInterest.MaxViewDistance, maxViewAngleCos);

        // We add an interest shape around this agent transform to all players in front.
        for (int i = 0, count = otherPlayerViews.Count; i < count; ++i)
        {
            // The interest is added for [Duration] seconds => we don't have to care about unregistration.
            otherPlayerViews[i].RegisterProvider(_shootInterest.Provider, _shootInterest.Duration);
        }
    }

    private static bool FilterPlayersByView(PlayerInterestView otherPlayerView, PlayerInterestView localPlayerView, float sqrMinDistance, float sqrMaxDistance, float maxAngleCos)
    {
        AgentInterestView otherAgentView = otherPlayerView as AgentInterestView;

        if (ReferenceEquals(otherAgentView, null) == true)
            return false;
        if (ReferenceEquals(otherAgentView, localPlayerView) == true)
            return false;

        Vector3 positionDifference = otherAgentView.PlayerPosition - localPlayerView.CameraPosition;

        float sqrDistance = Vector3.SqrMagnitude(positionDifference);
        if (sqrDistance > sqrMaxDistance || sqrDistance < sqrMinDistance)
            return false;

        float dot = Vector3.Dot(localPlayerView.CameraDirection, Vector3.Normalize(positionDifference));
        if (dot < maxAngleCos)
            return false;

        return true;
    }
}

ブロックされた視界

建物内部のような一部の場所はプレイヤーの視界を妨げます。この情報は、視錐全体を同期しないことで最適化に利用できます。

Interest override

プレイヤーが家に入ると、そのインタレストは上書きされます。これは、InterestProvider コンポーネントの Interest ModeOverride に設定し、Sort OrderPlayerInterestView コンポーネントの順序よりも大きい値に設定することで実現されます。ボーナスとして、デフォルトのプレイヤーインタレストビューは評価されません。
次のコンポーネントが家のゲームオブジェクトに追加されています。詳細は Sample Project で説明されています。

C#

public class ZoneInterestProvider : InterestProvider
{
    public Bounds Bounds;

    public override bool IsPlayerInterested(PlayerInterestView playerView)
    {
        // Simply checking bounds does the trick!
        Bounds bounds = Bounds;
        bounds.center += Transform.position;
        return bounds.Contains(playerView.PlayerPosition);
    }
}

観客

明確に定義されたアーキテクチャのおかげで、他のプレイヤーのビューを正しく複製することは非常に簡単です:

C#

public override void FixedUpdateNetwork()
{
    // Try to use observed agent reference, otherwise use our local agent.
    Agent observedAgent = SpectateAgent;
    if (observedAgent == null)
    {
        observedAgent = LocalAgent;
    }

    PlayerRef observedPlayer = observedAgent.Object.InputAuthority;
    if (observedPlayer.IsRealPlayer == true)
    {
        // Setting observed PlayerRef is all we need.
        InterestManager.ObservedPlayer = observedPlayer;
    }
}
Back to top