This document is about: FUSION 2
SWITCH TO

Advanced Usage

Following cases exemplify easy of use of the Interest Management addon and show how it can be used to improve player experience and optimize the game.

Distant areas

Some areas and actions in them can be clearly visible even at far distance, outside of default player's interest view.

custom interest provider

Notice an interest area is added to player's interest when the player is looking at the tower. This is done by adding a simple script to the tower object:

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

Synchronizing big area outside of player's view/camera would be inefficient. But if someone is shooting from behind, we want to receive info about the enemy. This must be processed selectively.

shooting from behind

When an enemy player starts shooting at another player who is looking away, an area around the enemy player is added to the victim's interest.

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;
    }
}

Blocked view

Some locations like interiors prevent player's view. This information can be used for optimizations by not synchronizing whole view frustum.

interest override

When a player enters the house, his interest gets overridden. This is done by setting Interest Mode to Override on InterestProvider component and setting Sort Order to a value greater than order on PlayerInterestView component. As a bonus, the default player's interest view is not evaluated. Following component is added on the house game object. More details explained in 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);
    }
}

Spectator

Thanks to well defined architecture, getting correctly replicated other player's view is very simple:

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