Hello,
I’m making multiplayer game with voxel terrain, and I’m decided to add AI to it, but problem is that voxel chunks are optimized and master client doesn’t have same chunks as player which AI chasing.
To avoid it I instatiate enemy as scene object:
PhotonNetwork.InstantiateSceneObject (prefabName, position, Quaternion.identity, 0, new object[1]);
Enemy has photon view set as takeover, and to find player and assign to him it uses this function:
void GetTarget () {
GameObject newTarget = FindClosestPlayer ();
if (newTarget != null) {
target=newTarget.transform;
PhotonView targetPView = target.GetComponent<PhotonView> ();
if (targetPView.ownerId != m_PhotonView.ownerId) {
m_PhotonView.TransferOwnership (targetPView.ownerId);
}
}
}
Script works, enemies aren’t deleted when their target leaves, but it gives a lot of logs in editor, so i decided to ask you:
Is it the best way to do this? Can I optimize it somehow?
I can hardly say a lot. I don’t know the game really. The basics seem to be OK but what are the errors?
You explained more or less what you do but only vaguely what you want to achieve.
Basically how to make network object doesn’t destroy when client which owns it leaves? Can I move it somehow to another client when player leaves? Or how should I control scene network object by computer which is not master client?
If I make enemy just controlled by master it would fall into black space around chunks.
My scripts works without errors, but it seems to be slow. It changes owner of enemy when it is spawned.
Hmm. There’s always a new use case
PUN is not built with your use case in mind. It’s a quite tricky case, because you need to control the lifetime and the ownership of the GO. Your ownership rule is very game-logic-dependent.
With PUN, what you do is the only way to achieve it, I would say. It automatically defines the owner as the Master Client, unless the ownership gets transferred. PUN also defines that only the Master Client can create GOs which live longer than their creator (player).
If you wanted to, you could dive deeper and use RaiseEvent and event caching to build something that suits your model better. It’s less comfy (no PhotonView relation) but more flexible (you can come up with your own IDs for objects you control)…
RaiseEvent looks too difficult to me, but anyway i’m glad that my script is good way to achieve it.
Maybe when i done basics of my game i will try with raise event.
Thanks!
@tobiass
Another problem.
How should I correctly destroy that object?
Who should do this, master or owner client?
Now i sending rpc to master, and master should destroy enemy, but it didn’t work.
It is something like this:
m_PhotonView.RPC ("DestroyAsMaster", PhotonTargets.MasterClient);
[PunRPC]
void DestroyAsMaster () {
PhotonNetwork.Destroy(gameObject);
}
Now i’m also sending bool which says is this object destroyed in OnPhotonSerializeView function, and every player destroys this enemy using:
Destroy(gameObject);
But this is probably bad idea.
PhotonNetwork.Destroy(gameObject) is a networked method. It tells everyone to destroy the GO that was created with PhotonNetwork.Instantiate.
Please find the Marco Polo Tutorial and other docs on these pages:
@tobiass
When master client use PhotonNetwork.Destroy:
Error
Failed to ‘network-remove’ GameObject. Client is neither owner nor masterClient taking over for owner who left: View (0)15 on Enemy(Clone) (scene)
UnityEngine.Debug:LogError(Object)
NetworkingPeer:RemoveInstantiatedGO(GameObject, Boolean) (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs:2618)
PhotonNetwork:smile:estroy(GameObject) (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonNetwork.cs:2488)
Enemy:smile:estroyAsMaster() (at Assets/Resources/Enemy.cs:82)
System.Reflection.MethodBase:Invoke(Object, Object[ ])
NetworkingPeer:ExecuteRpc(Hashtable, PhotonPlayer) (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs:2220)
NetworkingPeer:OnEvent(EventData) (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs:1905)
When client who owns scene object use PhotonNetwork.Destroy:
Error
Failed to ‘network-remove’ GameObject. Client is neither owner nor masterClient taking over for owner who left: View (0)10 on Enemy(Clone) (scene)
UnityEngine.Debug:LogError(Object)
NetworkingPeer:RemoveInstantiatedGO(GameObject, Boolean) (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs:2618)
PhotonNetwork:smile:estroy(GameObject) (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonNetwork.cs:2488)
Enemy:smile:estroyAsMaster() (at Assets/Resources/Enemy.cs:83)
System.Reflection.MethodBase:Invoke(Object, Object[ ])
NetworkingPeer:ExecuteRpc(Hashtable, PhotonPlayer) (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs:2220)
NetworkingPeer:OnEvent(EventData) (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs:1905)
ExitGames.Client.Photon.PeerBase:smile:eserializeMessageAndCallback(Byte[ ])
ExitGames.Client.Photon.EnetPeer:smile:ispatchIncomingCommands()
ExitGames.Client.Photon.PhotonPeer:smile:ispatchIncomingCommands()
PhotonHandler:Update() (at Assets/Photon Unity Networking/Plugins/PhotonNetwork/PhotonHandler.cs:83)
Should I send ownership back to master client or what?
EDIT: Same when I’m writing:
m_PhotonView.TransferOwnership (PhotonNetwork.masterClient.ID);
before PhotonNetwork.Destroy.