diff --git a/Assets/BossRoom/Prefabs/Character/Player.prefab b/Assets/BossRoom/Prefabs/Character/Player.prefab
index 652270524..51d735021 100644
--- a/Assets/BossRoom/Prefabs/Character/Player.prefab
+++ b/Assets/BossRoom/Prefabs/Character/Player.prefab
@@ -13,6 +13,19 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
m_FeedbackPrefab: {fileID: 9137928905311479176, guid: 5d22c1d86e0e5604cbe14004bf924827, type: 3}
+--- !u!114 &-4877982356580531930
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6009713983291384756}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: a46d628dbb19f12449867d14fa5268b0, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ m_CachedServerCharacter: {fileID: 6012286037226018870}
--- !u!114 &2576537793715222015
MonoBehaviour:
m_ObjectHideFlags: 0
@@ -210,6 +223,17 @@ Transform:
m_CorrespondingSourceObject: {fileID: 4600110157238723791, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3}
m_PrefabInstance: {fileID: 7831782662127126385}
m_PrefabAsset: {fileID: 0}
+--- !u!114 &6012286037226018870 stripped
+MonoBehaviour:
+ m_CorrespondingSourceObject: {fileID: 4602672899881656135, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3}
+ m_PrefabInstance: {fileID: 7831782662127126385}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6009713983291384756}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 920a440eb254ba348915767fd046027a, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
--- !u!114 &7751377510591478590 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 514105321093282895, guid: 0d2d836e2e83b754fa1a1c4022d6d65d, type: 3}
diff --git a/Assets/BossRoom/Scripts/Server/Game/AIState/IdleAIState.cs b/Assets/BossRoom/Scripts/Server/Game/AIState/IdleAIState.cs
index 95dc27637..e5846b1de 100644
--- a/Assets/BossRoom/Scripts/Server/Game/AIState/IdleAIState.cs
+++ b/Assets/BossRoom/Scripts/Server/Game/AIState/IdleAIState.cs
@@ -1,3 +1,4 @@
+using MLAPI;
using UnityEngine;
namespace BossRoom.Server
@@ -33,7 +34,8 @@ protected void DetectFoes()
float detectionRangeSqr = detectionRange * detectionRange;
Vector3 position = m_Brain.GetMyServerCharacter().transform.position;
- foreach (ServerCharacter character in ServerCharacter.GetAllActiveServerCharacters())
+ // in this game, NPCs only attack players (and never other NPCs), so we can just iterate over the players to see if any are nearby
+ foreach (var character in PlayerServerCharacter.GetPlayerServerCharacters())
{
if (m_Brain.IsAppropriateFoe(character) && (character.transform.position - position).sqrMagnitude <= detectionRangeSqr)
{
diff --git a/Assets/BossRoom/Scripts/Server/Game/Character/PlayerServerCharacter.cs b/Assets/BossRoom/Scripts/Server/Game/Character/PlayerServerCharacter.cs
new file mode 100644
index 000000000..c1d3a36b8
--- /dev/null
+++ b/Assets/BossRoom/Scripts/Server/Game/Character/PlayerServerCharacter.cs
@@ -0,0 +1,54 @@
+using System.Collections;
+using System.Collections.Generic;
+using MLAPI;
+using UnityEngine;
+
+namespace BossRoom.Server
+{
+ ///
+ /// Attached to the player-characters' prefab, this maintains a list of active ServerCharacter objects for players.
+ ///
+ ///
+ /// This is an optimization. In server code you can already get a list of players' ServerCharacters by
+ /// iterating over the active connections and calling GetComponent() on their PlayerObject. But we need
+ /// to iterate over all players quite often -- the monsters' IdleAIState does so in every Update() --
+ /// and all those GetComponent() calls add up! So this optimization lets us iterate without calling
+ /// GetComponent(). This will be refactored with a ScriptableObject-based approach on player collection.
+ ///
+ [RequireComponent(typeof(ServerCharacter))]
+ public class PlayerServerCharacter : NetworkBehaviour
+ {
+ static List s_ActivePlayers = new List();
+
+ [SerializeField]
+ ServerCharacter m_CachedServerCharacter;
+
+ public override void NetworkStart()
+ {
+ if( !IsServer )
+ {
+ enabled = false;
+ }
+ }
+
+ void OnEnable()
+ {
+ s_ActivePlayers.Add(m_CachedServerCharacter);
+ }
+
+ void OnDisable()
+ {
+ s_ActivePlayers.Remove(m_CachedServerCharacter);
+ }
+
+ ///
+ /// Returns a list of all active players' ServerCharacters. Treat the list as read-only!
+ /// The list will be empty on the client.
+ ///
+ public static List GetPlayerServerCharacters()
+ {
+
+ return s_ActivePlayers;
+ }
+ }
+}
diff --git a/Assets/BossRoom/Scripts/Server/Game/Character/PlayerServerCharacter.cs.meta b/Assets/BossRoom/Scripts/Server/Game/Character/PlayerServerCharacter.cs.meta
new file mode 100644
index 000000000..a9c3da118
--- /dev/null
+++ b/Assets/BossRoom/Scripts/Server/Game/Character/PlayerServerCharacter.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a46d628dbb19f12449867d14fa5268b0
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/BossRoom/Scripts/Server/Game/Character/ServerCharacter.cs b/Assets/BossRoom/Scripts/Server/Game/Character/ServerCharacter.cs
index 6986ee231..76d3c129b 100644
--- a/Assets/BossRoom/Scripts/Server/Game/Character/ServerCharacter.cs
+++ b/Assets/BossRoom/Scripts/Server/Game/Character/ServerCharacter.cs
@@ -42,12 +42,6 @@ public bool IsNpc
// Cached component reference
private ServerCharacterMovement m_Movement;
- ///
- /// Temp place to store all the active characters (to avoid having to
- /// perform insanely-expensive GameObject.Find operations during Update)
- ///
- private static List s_ActiveServerCharacters = new List();
-
private void Awake()
{
m_Movement = GetComponent();
@@ -60,21 +54,6 @@ private void Awake()
}
}
- private void OnEnable()
- {
- s_ActiveServerCharacters.Add(this);
- }
-
- private void OnDisable()
- {
- s_ActiveServerCharacters.Remove(this);
- }
-
- public static List GetAllActiveServerCharacters()
- {
- return s_ActiveServerCharacters;
- }
-
public override void NetworkStart()
{
if (!IsServer) { enabled = false; }
diff --git a/Assets/BossRoom/Scripts/Server/Game/Entity/ServerWaveSpawner.cs b/Assets/BossRoom/Scripts/Server/Game/Entity/ServerWaveSpawner.cs
index f4d56bd81..69d113c77 100644
--- a/Assets/BossRoom/Scripts/Server/Game/Entity/ServerWaveSpawner.cs
+++ b/Assets/BossRoom/Scripts/Server/Game/Entity/ServerWaveSpawner.cs
@@ -248,15 +248,9 @@ bool IsAnyPlayerNearbyAndVisible()
// iterate through clients and only return true if a player is in range
// and is not occluded by a blocking collider.
- foreach (KeyValuePair idToClient in NetworkManager.Singleton.ConnectedClients)
+ foreach (var serverCharacter in PlayerServerCharacter.GetPlayerServerCharacters())
{
- if (idToClient.Value.PlayerObject == null)
- {
- // skip over any connection that doesn't have a PlayerObject yet
- continue;
- }
-
- var playerPosition = idToClient.Value.PlayerObject.transform.position;
+ var playerPosition = serverCharacter.transform.position;
var direction = playerPosition - spawnerPosition;
if (direction.sqrMagnitude > squaredProximityDistance)
diff --git a/Assets/BossRoom/Scripts/Server/Game/State/ServerBossRoomState.cs b/Assets/BossRoom/Scripts/Server/Game/State/ServerBossRoomState.cs
index dc1df6054..b2668dc23 100644
--- a/Assets/BossRoom/Scripts/Server/Game/State/ServerBossRoomState.cs
+++ b/Assets/BossRoom/Scripts/Server/Game/State/ServerBossRoomState.cs
@@ -184,12 +184,10 @@ private void OnHeroLifeStateChanged(LifeState prevLifeState, LifeState lifeState
if (lifeState == LifeState.Fainted)
{
// Check the life state of all players in the scene
- foreach (var p in NetworkManager.Singleton.ConnectedClientsList )
+ foreach (var serverCharacter in PlayerServerCharacter.GetPlayerServerCharacters())
{
- if (p.PlayerObject == null) { continue; }
- // if any player is alive just retrun
- var netState = p.PlayerObject.GetComponent();
- if ( netState.NetworkLifeState.Value == LifeState.Alive ) { return; }
+ // if any player is alive just retun
+ if (serverCharacter.NetState && serverCharacter.NetState.NetworkLifeState.Value == LifeState.Alive) { return; }
}
// If we made it this far, all players are down! switch to post game