DistanceInterestManagement.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // straight forward Vector3.Distance based interest management.
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. namespace Mirror
  5. {
  6. [AddComponentMenu("Network/ Interest Management/ Distance/Distance Interest Management")]
  7. public class DistanceInterestManagement : InterestManagement
  8. {
  9. [Tooltip("The maximum range that objects will be visible at. Add DistanceInterestManagementCustomRange onto NetworkIdentities for custom ranges.")]
  10. public int visRange = 500;
  11. [Tooltip("Rebuild all every 'rebuildInterval' seconds.")]
  12. public float rebuildInterval = 1;
  13. double lastRebuildTime;
  14. // cache custom ranges to avoid runtime TryGetComponent lookups
  15. readonly Dictionary<NetworkIdentity, DistanceInterestManagementCustomRange> CustomRanges = new Dictionary<NetworkIdentity, DistanceInterestManagementCustomRange>();
  16. // helper function to get vis range for a given object, or default.
  17. [ServerCallback]
  18. int GetVisRange(NetworkIdentity identity)
  19. {
  20. return CustomRanges.TryGetValue(identity, out DistanceInterestManagementCustomRange custom) ? custom.visRange : visRange;
  21. }
  22. [ServerCallback]
  23. public override void Reset()
  24. {
  25. lastRebuildTime = 0D;
  26. CustomRanges.Clear();
  27. }
  28. public override void OnSpawned(NetworkIdentity identity)
  29. {
  30. if (identity.TryGetComponent(out DistanceInterestManagementCustomRange custom))
  31. CustomRanges[identity] = custom;
  32. }
  33. public override void OnDestroyed(NetworkIdentity identity)
  34. {
  35. CustomRanges.Remove(identity);
  36. }
  37. public override bool OnCheckObserver(NetworkIdentity identity, NetworkConnectionToClient newObserver)
  38. {
  39. int range = GetVisRange(identity);
  40. return Vector3.Distance(identity.transform.position, newObserver.identity.transform.position) < range;
  41. }
  42. public override void OnRebuildObservers(NetworkIdentity identity, HashSet<NetworkConnectionToClient> newObservers)
  43. {
  44. // cache range and .transform because both call GetComponent.
  45. int range = GetVisRange(identity);
  46. Vector3 position = identity.transform.position;
  47. // brute force distance check
  48. // -> only player connections can be observers, so it's enough if we
  49. // go through all connections instead of all spawned identities.
  50. // -> compared to UNET's sphere cast checking, this one is orders of
  51. // magnitude faster. if we have 10k monsters and run a sphere
  52. // cast 10k times, we will see a noticeable lag even with physics
  53. // layers. but checking to every connection is fast.
  54. foreach (NetworkConnectionToClient conn in NetworkServer.connections.Values)
  55. {
  56. // authenticated and joined world with a player?
  57. if (conn != null && conn.isAuthenticated && conn.identity != null)
  58. {
  59. // check distance
  60. if (Vector3.Distance(conn.identity.transform.position, position) < range)
  61. {
  62. newObservers.Add(conn);
  63. }
  64. }
  65. }
  66. }
  67. // internal so we can update from tests
  68. [ServerCallback]
  69. internal void Update()
  70. {
  71. // rebuild all spawned NetworkIdentity's observers every interval
  72. if (NetworkTime.localTime >= lastRebuildTime + rebuildInterval)
  73. {
  74. RebuildAll();
  75. lastRebuildTime = NetworkTime.localTime;
  76. }
  77. }
  78. }
  79. }