namespace Fusion.Addons.InterestManagement { using UnityEngine; /// /// Special InterestProvider that tracks transform/view information and other interest providers related to a specific player. /// There can be more instances per player spawned at the same time, but only one can be active - set to PlayerInterestManager.InterestView. /// [DefaultExecutionOrder(PlayerInterestView.EXECUTION_ORDER)] public class PlayerInterestView : InterestProvider { // CONSTANTS public new const int EXECUTION_ORDER = InterestProvider.EXECUTION_ORDER - 1000; // PUBLIC MEMBERS /// /// Owner player, equals to object input authority. /// public PlayerRef Player => _player; /// /// Reference to player object transform. Typically a character root. /// public Transform PlayerTransform => _playerTransform; /// /// Cached player position. /// Prefer this property over PlayerTransform.position when resolving player interest conditions. /// public Vector3 PlayerPosition { get; private set; } /// /// Cached player rotation. /// Prefer this property over PlayerTransform.rotation when resolving player interest conditions. /// public Quaternion PlayerRotation { get; private set; } /// /// Cached normalized player direction. /// Prefer this property over PlayerTransform.rotation * Vector3.forward when resolving player interest conditions. /// public Vector3 PlayerDirection { get; private set; } /// /// Reference to player camera transform. Typically this can be an offsetted child object of the player object. /// Don't set Camera.main.transform, otherwise all players will share same view with incorrect interest. /// public Transform CameraTransform => _cameraTransform; /// /// Cached player camera position. /// Prefer this property over CameraTransform.position when resolving player interest conditions. /// public Vector3 CameraPosition { get; private set; } /// /// Cached player camera rotation. /// Prefer this property over CameraTransform.rotation when resolving player interest conditions. /// public Quaternion CameraRotation { get; private set; } /// /// Cached normalized player camera direction. /// Prefer this property over CameraTransform.rotation * Vector3.forward when resolving player interest conditions. /// public Vector3 CameraDirection { get; private set; } // PRIVATE MEMBERS private PlayerRef _player; private Transform _playerTransform; private Transform _cameraTransform; // PUBLIC METHODS /// /// Updates player and camera transform and caches their position, rotation and direction. /// public void SetPlayerInfo(Transform playerTransform, Transform cameraTransform) { _playerTransform = playerTransform; _cameraTransform = cameraTransform; UpdatePlayerInfo(); } // PlayerInterestView INTERFACE /// /// Called on the end of Spawned(), after setting player info defaults, before registering child providers to self and before self-registring to GlobalInterestManager. /// protected virtual void OnViewSpawned() {} /// /// Called on the start of Despawn(), after self-unregistering from GlobalInterestManager and after unregistering all registered providers. /// protected virtual void OnViewDespawned(NetworkRunner runner, bool hasState) {} /// /// Called on the end of FixedUpdateNetwork(), after updating internal providers list and player info - transforms and related cached properties. /// protected virtual void OnViewFixedUpdateNetwork() {} /// /// Called on the end of Render(), after updating internal providers list and player info - transforms and related cached properties. /// protected virtual void OnViewRender() {} // InterestProvider INTERFACE protected override sealed void OnSpawned() { _player = Object.InputAuthority; UpdatePlayerInfo(); if (IsGlobal == true) { Debug.LogWarning($"{nameof(IsGlobal)} is enabled on {GetType().Name} ({name}). This is not allowed and will be disabled.", gameObject); IsGlobal = false; } OnViewSpawned(); GlobalInterestManager globalInterestManager = Runner.GetGlobalInterestManager(); globalInterestManager.RegisterPlayerView(this); } protected override sealed void OnDespawned(NetworkRunner runner, bool hasState) { GlobalInterestManager globalInterestManager = runner.GetGlobalInterestManager(); globalInterestManager.UnregisterPlayerView(this); OnViewDespawned(runner, hasState); _player = default; _playerTransform = default; _cameraTransform = default; } protected override sealed void OnFixedUpdateNetwork() { _player = Object.InputAuthority; UpdatePlayerInfo(); OnViewFixedUpdateNetwork(); } protected override sealed void OnRender() { if (Object.IsInSimulation == false) { _player = Object.InputAuthority; UpdatePlayerInfo(); } OnViewRender(); } // PRIVATE METHODS private void UpdatePlayerInfo() { if (_playerTransform == null) { _playerTransform = Transform; } if (_cameraTransform == null) { _cameraTransform = _playerTransform; } _playerTransform.GetPositionAndRotation(out Vector3 playerPosition, out Quaternion playerRotation); PlayerPosition = playerPosition; PlayerRotation = playerRotation; PlayerDirection = playerRotation * Vector3.forward; if (ReferenceEquals(_cameraTransform, _playerTransform) == true) { CameraPosition = PlayerPosition; CameraRotation = PlayerRotation; CameraDirection = PlayerDirection; } else { _cameraTransform.GetPositionAndRotation(out Vector3 cameraPosition, out Quaternion cameraRotation); CameraPosition = cameraPosition; CameraRotation = cameraRotation; CameraDirection = cameraRotation * Vector3.forward; } } } }