using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; using MLAPI.Connection; using MLAPI.Messaging; namespace MLAPI.Prototyping { /// /// A prototype component for syncing NavMeshAgents /// [AddComponentMenu("MLAPI/NetworkNavMeshAgent")] [RequireComponent(typeof(NavMeshAgent))] public class NetworkNavMeshAgent : NetworkBehaviour { private NavMeshAgent m_Agent; /// /// Is proximity enabled /// public bool EnableProximity = false; /// /// The proximity range /// public float ProximityRange = 50f; /// /// The delay in seconds between corrections /// public float CorrectionDelay = 3f; //TODO rephrase. /// /// The percentage to lerp on corrections /// [Tooltip("Everytime a correction packet is received. This is the percentage (between 0 & 1) that we will move towards the goal.")] public float DriftCorrectionPercentage = 0.1f; /// /// Should we warp on destination change /// public bool WarpOnDestinationChange = false; private void Awake() { m_Agent = GetComponent(); } private Vector3 m_LastDestination = Vector3.zero; private float m_LastCorrectionTime = 0f; private void Update() { if (!IsOwner) return; if (m_Agent.destination != m_LastDestination) { m_LastDestination = m_Agent.destination; if (!EnableProximity) { OnNavMeshStateUpdateClientRpc(m_Agent.destination, m_Agent.velocity, transform.position); } else { var proximityClients = new List(); foreach (KeyValuePair client in NetworkManager.Singleton.ConnectedClients) { if (client.Value.PlayerObject == null || Vector3.Distance(client.Value.PlayerObject.transform.position, transform.position) <= ProximityRange) { proximityClients.Add(client.Key); } } OnNavMeshStateUpdateClientRpc(m_Agent.destination, m_Agent.velocity, transform.position, new ClientRpcParams { Send = new ClientRpcSendParams { TargetClientIds = proximityClients.ToArray() } }); } } if (NetworkManager.Singleton.NetworkTime - m_LastCorrectionTime >= CorrectionDelay) { if (!EnableProximity) { OnNavMeshCorrectionUpdateClientRpc(m_Agent.velocity, transform.position); } else { var proximityClients = new List(); foreach (KeyValuePair client in NetworkManager.Singleton.ConnectedClients) { if (client.Value.PlayerObject == null || Vector3.Distance(client.Value.PlayerObject.transform.position, transform.position) <= ProximityRange) { proximityClients.Add(client.Key); } } OnNavMeshCorrectionUpdateClientRpc(m_Agent.velocity, transform.position, new ClientRpcParams { Send = new ClientRpcSendParams { TargetClientIds = proximityClients.ToArray() } }); } m_LastCorrectionTime = NetworkManager.Singleton.NetworkTime; } } [ClientRpc] private void OnNavMeshStateUpdateClientRpc(Vector3 destination, Vector3 velocity, Vector3 position, ClientRpcParams rpcParams = default) { m_Agent.Warp(WarpOnDestinationChange ? position : Vector3.Lerp(transform.position, position, DriftCorrectionPercentage)); m_Agent.SetDestination(destination); m_Agent.velocity = velocity; } [ClientRpc] private void OnNavMeshCorrectionUpdateClientRpc(Vector3 velocity, Vector3 position, ClientRpcParams rpcParams = default) { m_Agent.Warp(Vector3.Lerp(transform.position, position, DriftCorrectionPercentage)); m_Agent.velocity = velocity; } } }