#GameObject is moving only if no player is looking at it

15 messages · Page 1 of 1 (latest)

spare dome
#

Hello! I'm trying to implement an enemy in my game that moves only if no player is looking at it. As usual, if only one player played the game, everything worked fine, but implementing the multiplayer part has some bugs.

What I want: An enemy is instantiated in the scene, it roams, it finds the closest player and goes to it. If the enemy is visible in any of the player's cameras, it stops. If it has stopped for more than 10 seconds it dissapears and appears again after some time.

With what I have right now the only problems are that the clients can't stop the enemy if they are looking at it and sometimes, if the host is looking at the enemy for 10 seconds, the enemy dissapears for the host but not for the client(only sometimes this happens).

I want to use a bool for this (isRaycasted) and right now I'm using CMD and RPC's to sync the state. I also tried hook on the bool but still the same outcome like now. If the host is looking at the enemy, the bool is synced over everyone, but if the client is looking at the enemy, the bool is updated only locally and not for everyone else. I've left the important parts of the script down below if anyone has any idea. Thank you!

https://pastie.io/vbcxhj.cs

EDIT: Forgot to say that this with the cmd in the update was added only to test. I also added a coroutine that runs every second for this script to not overload the network with CMD's but still the same outcome.

glad skiff
#

You're mixing up client and server activity here. Simplify by doing it all server side from the enemy's POV.

  • Give the enemy a sphere trigger collider with some reasonable "detection range" that adds / removes player game objects from a list via OnTriggerEnter / Exit (with [ServerCallback]). Disable that collider in the enemy prefab, and enable in OnStartServer override.
  • Set layers and physics matrix so the trigger only fires for players, not the ground / buildings / etc.
  • On some interval, have the enemy raycast all the players in its list for "line of sight" check. If any return true for that check, stop patrolling, and after some delay recheck line of sight to determine if it should disappear (Unspawn) or resume patrolling. No Cmd / Rpc needed.
  • don't forget null checks when iterating the list, in case a player object is destroyed because it disconnected. You could add some code to OnStopServer on players to iterate enemies and remove themselves from their respective lists, or perhaps use linq in the enemy script to Remove null entries from the list before iterating.
spare dome
#

The map I have is a house that is relatively small. Is it needed to create a detection range? I've already done the roaming and chasing part and it's working fine. The only problem I got is with the Renderer.isVisible and the LineCast.

Also there is a collider on the AI that triggers something on the player when they collide.

I've somehow managed to sync a bool from each player if they are looking at the monster and if they should stop it but I'm having an issue with the ```foreach (GameObject player in alivePlayersScript.alivePlayersList)


Since one player is looking at the AI and other is not, it's continuously setting the AI raycasted and not and it's moving and stopping very fast.

How can I avoid this? If one player is looking at the monster, others can't set the isRaycasted to false anymore
glad skiff
#

Again - having the clients control the enemy like this is making it harder than it needs to be. I can't see your screen, so didn't know this was in a house. You can skip the detection range part and just do the line of sight checks from enemy to player on server.

spare dome
glad skiff
#

Again - doing this client side is misguided. You're just making it harder for no reason.

#

client camera isn't relevant, really, although it's generally better to just have a scene camera that the local player grabs instead of having a camera on the player prefab

#

You really need to get your head out of single player / client-driven thinking. Server-driven is just easier.

spare dome
#

Yeah, I was thinking this will be a problem. Alright, I will make everything server sided and remove the .isVisible for now to make it work with LineCast only and after I get it done I'll try to add the .isVisible again.

Probably I will be back here in a bit CryInside
Thank you!

glad skiff
spare dome
#

A situation like the AI from Lethal Company, if you know what I mean.

glad skiff
#

if you really want to check "looking at" vs "line of sight" you can do a secondary check if line of sight is true to verify the player is facing the right direction to enemy on server.

spare dome
# glad skiff if you really want to check "looking at" vs "line of sight" you can do a seconda...

This is what I did first time but in reverse. I checked if the player is looking at the AI and if he was looking I was line casting so it will not use that much resources.

But the big problem is that I am using foreach and if one player was looking at the AI and other player was not looking the AI was moving and stoping.

Also this happens with linecast after removing the looking at part. I have a foreach with a list of all players that is inside the game and I line cast from the AI to the players. One player is behind a wall and the other isn't. The monster is still moving and stopping towards the player. Idk if I specified that this function is in Update()

Is there a way that if he found a player with the linecast and the bool isRaycasted was set, it will not override it until is needed?