Photon Syncing Enemies with Other Clients?

Ok So I have Navmesh Agents that Locals move and the AI-Code operate fine. as soon as I implement a Photon Sync code:

	public Vector3 realPosition = Vector3.zero;
		public Vector3 positionAtLastPacket = Vector3.zero;
		public double currentTime = 0.0;
		public double currentPacketTime = 0.0;
		public double lastPacketTime = 0.0;
		public double timeToReachGoal = 0.0;

		void Update ()
		{
		if (!PhotonNetwork.isMasterClient)
			{
				timeToReachGoal = currentPacketTime - lastPacketTime;
				currentTime += Time.deltaTime;
				transform.position = Vector3.Lerp(positionAtLastPacket, realPosition, (float)(currentTime / timeToReachGoal));
			}
		}

		void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
		{
			if (stream.isWriting)
			{
				stream.SendNext((Vector3)transform.position);
			}
			else
			{
				currentTime = 0.0;
				positionAtLastPacket = transform.position;
				realPosition = (Vector3)stream.ReceiveNext();
				lastPacketTime = currentPacketTime;
				currentPacketTime = info.timestamp;
			}
		}
	}

All my Enemy game objects now Converge on one position on all clients rather then moving around the Navemesh.
96943-screen-shot-2017-07-02-at-102947-am.png

My AI code simply moves to selected “Goals” on the map and then attacks a player once in range. (works Fine Without Synccode.)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class SimpleEnemy : Photon.MonoBehaviour {

	public float fireRate = 0.4f;
	private float nextFire = 0.0F;

	public NavMeshAgent agent;
	GameObject[] AgentPoints;
	GameObject currentAgentPoint;
	int index;
	public GameObject EnemyBullet;
	private GameObject AttackTarget;
	private bool UnderAttack;

	//-----------------------------------------------------------------------------------------------------------

	// Use this for initialization
	void Start () {
		if (PhotonNetwork.isMasterClient == true) {
			agent = gameObject.GetComponent<NavMeshAgent> ();

			AgentPoints = GameObject.FindGameObjectsWithTag ("Goal");
			index = Random.Range (0, AgentPoints.Length);
			currentAgentPoint = AgentPoints [index];

			agent.destination = (currentAgentPoint.transform.position);
		} else {
			agent.enabled = false;
		}
	}

	//-----------------------------------------------------------------------------------------------------------
	void Update(){
		if (PhotonNetwork.isMasterClient == true) {
			if (UnderAttack == true) {
				Debug.Log ("Attacked!");
				agent.SetDestination (AttackTarget.transform.position);


				if (Time.time > nextFire && agent.remainingDistance < 10) {
					nextFire = Time.time + fireRate;
					Instantiate (EnemyBullet, this.transform.position, this.transform.rotation);
				}

				if (agent.remainingDistance < 10) {
					agent.Stop ();
				} else {
					agent.Resume ();
				}

				if (agent.remainingDistance > 40) {
					UnderAttack = false;
					AttackTarget = null;
				}
			}

			if (UnderAttack == false) {
				if (agent.remainingDistance < 4) {
					index = Random.Range (0, AgentPoints.Length);
					currentAgentPoint = AgentPoints [index];
				}
			}

		}
	}

	//-----------------------------------------------------------------------------------------------------------



	void OnTriggerEnter (Collider Other){
		if (PhotonNetwork.isMasterClient == true) {
			if (Other.gameObject.tag == ("Player")) {
				AttackTarget = Other.gameObject;
				UnderAttack = true;
			}

			if (Other.gameObject.tag == ("ThisIsMyPlayer")) {
				AttackTarget = Other.gameObject;
				UnderAttack = true;
			}
		}
	}

	//-----------------------------------------------------------------------------------------------------------

}

There’s another way of navmesh ai, where the navmesh agent is what the actual game object is moving toward with the “player movement physics too” so it can steer with the same freedom as an actual player. Coupled with sending simulated inputs

So master client calculates navmesh path, and then while navmesh agent is moving locally, master client ai game objects will steer toward the navmesh agent via simulated inputs that master client sends out to all other clients.

As a result, the other players will receive the commands to move their local AI smoothly without interpolation here.

Of course when Inputs gets dropped in the process sometimes, we need to make sure we check each client’s AI positions with the master to see if they’re off by an error margin. Then simply sync it back. But because most of the time the AI is moving via inputs and not interpolation this sync is not going to have much less jitter on average. If you really needed more smoothness, just do a nice interpolation instead when the distance comparison exceeds the threshold.