고급 사용법
다음은 관심 관리 추가 기능을 쉽게 사용할 수 있는 사례를 보여주며, 추가 기능을 사용하여 플레이어의 경험을 향상시키고 게임을 최적화하는 방법을 보여줍니다.
먼 지역
일부 영역과 동작은 기본 플레이어의 관심 범위 밖의 먼 거리에서도 명확하게 볼 수 있습니다.
플레이어가 타워를 볼 때 관심 영역이 플레이어의 관심 영역에 추가됩니다. 이것은 타워 객체에 간단한 스크립트를 추가함으로써 수행됩니다:
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;
}
}
블록 된 뷰
인테리어와 같은 일부 위치는 플레이어의 시야를 방해합니다. 이 정보는 전체 뷰 프레임을 동기화하지 않음으로써 최적화에 사용될 수 있습니다.
플레이어가 집에 들어오면 자신의 관심사는 무시됩니다. 이는 InterestProvider
컴포넌트에서 Interest Mode
를 Override
로 설정하고 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