This document is about: FUSION 2
SWITCH TO

고급 사용법

다음은 관심 관리 추가 기능을 쉽게 사용할 수 있는 사례를 보여주며, 추가 기능을 사용하여 플레이어의 경험을 향상시키고 게임을 최적화하는 방법을 보여줍니다.

먼 지역

일부 영역과 동작은 기본 플레이어의 관심 범위 밖의 먼 거리에서도 명확하게 볼 수 있습니다.

사용자 지정 관심 공급자

플레이어가 타워를 볼 때 관심 영역이 플레이어의 관심 영역에 추가됩니다. 이것은 타워 객체에 간단한 스크립트를 추가함으로써 수행됩니다:

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

뒤에서 슈팅

플레이어의 시야/카메라 밖에 있는 큰 영역을 동기화하는 것은 비효율적일 것입니다. 하지만 누군가가 뒤에서 슈팅을 하고 있다면, 적에 대한 정보를 수신하고 싶습니다. 이는 선택적으로 처리되어야 합니다.

뒤에서 슈팅

적 플레이어가 시선을 돌리고 있는 다른 플레이어를 향해 총을 쏘기 시작하면, 적 플레이어 주변 영역이 피해자의 관심에 추가됩니다.

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로 설정하고 PlayerInterestView 컴포넌트에서 정렬 순서를 순서보다 큰 값으로 설정하면 됩니다. 보너스로 기본 플레이어의 관심사는 평가되지 않습니다.

홈 게임 오브젝트에 다음과 같은 컴포넌트가 추가됩니다. 자세한 내용은 샘플 프로젝트에서 설명합니다.

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