Hello, I have been using Nav Mesh to make the zombies for my FPS game, and I plan on making this game multiplayer. However, the tutorial I consulted for this doesn’t take multiplayer into account, so I improvised my own way for this.
Basically, the enemy has an AI script for it so when a player is within range it pursues them. Simple enough. But, to keep track of that player, I need a reference to it, so in the tutorial I mentioned they made another script called Player Manager and referenced the variable from that script into the Start() method for the AI script. Here is the Player Manager, it is very simple and small:
public class PlayerManager : MonoBehaviour
{
#region Singleton
public static PlayerManager Instance;
void Awake()
{
Instance = this;
}
#endregion
[Header("Main References")]
public GameObject Player;
}
So, to make sure the Player Manager keeps track of all players in the game, I turned the GameObject Player into a list:
public GameObject Player;
→ public List<GameObject> PlayerList = new List<GameObject>();
But if it is a list, then the AI script has to reference a list instead of a variable, and then keep track of all the elements in the list so it can find the actual players. I used for() statements and an integer that kept track of the number of players, so it did everything based on how many players are in the game. Here is the code(this one is big):
void Start ()
{
InPursuit = false;
Agent = gameObject.GetComponent<NavMeshAgent>();
PlayerNum = PlayerManager.Instance.PlayerList.Capacity;
Player.Capacity = PlayerNum;
for (int i = 0; i < PlayerNum; i++)
{
Player.Insert(i, PlayerManager.Instance.PlayerList[i].transform);
}
}
void Update ()
{
Search();
}
void Search ()
{
for (int i = 0; i < PlayerNum; i++)
{
float DistanceFromPlayer = Vector3.Distance(Player[i].position, transform.position);
if (DistanceFromPlayer <= RawDetection && !InPursuit)
{
ChaseTarget(i);
}
}
}
void ChaseTarget (int TargetNum)
{
InPursuit = true;
Agent.SetDestination(Player[TargetNum].position);
Vector3 Direction = (Player[TargetNum].position - transform.position).normalized;
Quaternion LookRotation = Quaternion.LookRotation(new Vector3(Direction.x, 0, Direction.z));
transform.rotation = Quaternion.Slerp(transform.rotation, LookRotation, Time.deltaTime * 5f);
}
But I feel like this isn’t ideal. The Search method is called every single frame, and for every single player. So if there are 8 players online, that for() statement inside Search() function runs 8 times per frame! FOR EVERY SINGLE ZOMBIE IN THE GAME!! This is going to destroy the game and blow up a computer that is running it.
What would be the best way to do this? I heard arrays are faster, but I gotta use lists otherwise I can’t change their size. I thought about tags but they also seem to be slow, and it would have to call them each frame anyway. Is there a way for the enemy knowing the player is there without cluttering the Update() function?
Also, I couldn’t test this because I didn’t implement multiplayer yet, but I am pretty sure the way this script works the enemies will keep cycling between players instead of focusing on a single one. I kind of fixed that by making the InPursuit boolean, but now enemies will always follow the same player, even after it stopped chasing them. Any ideas how to fix this?