I have an object with a networkView and a NetworkRigidBody component attached to it, and set the networkView’s observed property to the “NetworkRigidBody” script. If I have another script e.g. “TurretAI” which contains the health of the object, team, the current rotation of the top part of the turret, etc., am I supposed to add another networkView component to that object and observe the TurretAI script? Would I do this for every script I want to have communicate via network on the object?
A networkview can only observe 1 script or component. So unless you are using RPC to send, yes you will 1 per script or component. If you are sending data through RPC, you can use any networkview attached to the object.
Would there be a big performance hit on the network if I have for example… 5 networkviews on 1 object? (not that I intend to have that many)
Amount of data sent will affect the network, nothing else
I have been having some trouble getting more than one networkview working properly in my situation. For example, I am instantiating an object server side, and then informing all clients of this object to instantiate it, while, passing along the networkviewID from the server side that has been allocated to this object:
My original code with 1 networkview
[RPC]
void SpawnMissileRequest(Vector3 position, Quaternion rotation, Vector3 force, NetworkViewID owner, string team, string weaponName, int lockonTargetID)
{
//allocate the networkviewid for the networkview
NetworkViewID nView = Network.AllocateViewID();
//pass the information to the clients
networkView.RPC("SpawnMissile", RPCMode.All, position, rotation, force, nView, owner, team, weaponName, lockonTargetID);
}
[RPC]
void SpawnMissile(Vector3 position, Quaternion rotation, Vector3 force, NetworkViewID nVid, NetworkViewID owner, string team, string weaponName, int lockonTargetID)
{
GameObject projectile = weaponManager.FindWeapon(weaponName).projectile;
GameObject instantiatedProjectile = (GameObject)Instantiate(projectile, position, rotation);
NetworkView nView = (NetworkView)instantiatedProjectile.GetComponent(typeof(NetworkView));
nView.viewID = nVid;
}
Now, the problem I am having is, if my object has 2 networkViews, then I need to allocate 2 networkViewID’s on the server and pass those through the RPC to the clients right?. I have tried to do it like this (keep in mind this is in a different function but the idea is the same):
example code on object with 2 networkviews (my attempt does not work - need help)
NetworkView[] nwViews;
nwViews = t.model.GetComponents<NetworkView>();
//get all the networkviews in this object and assign them a viewID
foreach(NetworkView nwView in nwViews){
nwView.networkView.viewID = Network.AllocateViewID();
}
networkView.RPC("PlaceStructure", RPCMode.All, structure, position, rotation, nwViews, owner, setTeam);
void PlaceStructure(string structure, Vector3 position, Quaternion rotation, NetworkView[] nVid, NetworkViewID owner, string setTeam){
instantiatedStructure = (GameObject)Instantiate(structureToPlace.model, position, rotation);
foreach (NetworkView nView in nVid){
//not sure why nVid is null...
}
}
This unfortunately did not work since nVid is empty in the “PlaceStructure” function for some reason, and I’m not sure if this is even the right way of doing it. How would this be done?
You are sending NetworkViews instead of the id’s :
nwViews = t.model.GetComponents<NetworkView>();
And there may be more errors but it’s up to you to debug your code.
That’s one of the issues I had and can’t figure out how to do it. I tried doing something like:
NetworkViewID[] networkViewsIDS = null;
int i = 0;
foreach(NetworkView nwView in nwViews){
networkViewsIDS[i] = Network.AllocateViewID();
i++;
}
And then I tried to send the networkViewIDS array…
But I always get the “Object reference not set” error on the line I try to allocate the networkViewID. I even tried to put before that line:
networkViewsIDS[i] = new NetworkViewID();
And I still got the “Object reference not set” error.
I also realised you cannot send arrays via RPC call… I am out of ideas, and the only solution is to send each networkviewID on a seperate RPC call, but that will extermely complicate things for me. I am stumped…
I can’t be the only one with this problem? How is everyone else instantiating objects via server which have multiple network views in an authoratative server setting??
Network.Instantiate
Also, why do you need multiple networkviews?
That’s one of the issues I had and can’t figure out how to do it.
A couple problems I see (with the two network view approach you showed above).
NetworkView[] nwViews;
nwViews = t.model.GetComponents<NetworkView>();
//get all the networkviews in this object and assign them a viewID
foreach(NetworkView nwView in nwViews){
nwView.networkView.viewID = Network.AllocateViewID();
}
networkView.RPC("PlaceStructure", RPCMode.All, structure, position, rotation, nwViews, owner, setTeam);
One, and someone already mentioned this, is that you are trying to pass in an array of NetworkView objects instead of NetworkViewID objects.
Another problem is that when you assign the network views here:
foreach(NetworkView nwView in nwViews){
nwView.networkView.viewID = Network.AllocateViewID();
}
When you call nwView.networkView there, you are basically getting the first NetworkView component attached to that GameObject, which in this case is the same GameObject. This causes you to allocate two view ID’s to the same networkview, leaving the other one unassigned.
To make things simpler, I wouldn’t pass these in as an array (EDIT: Yeah, you can’t actually do that anyway; I didn’t think so), I would pass them in individually and then assign them to the correct NetworkView component (the one that observes the correct property). Or to manually assign both the viewID and the observed component.
Your foreach statement for assigning them should just be :
foreach(NetworkView nwView in nwViews){
nwView.viewID = Network.AllocateViewID();
}
I have a turret in my case. I have a networkview attached the root most gameobject of my turret (which is updating the position/rotation etc. of the entire object), along with a networkrigidbody script. So that networkview is observing the networkrigidbody script. But, the problem came when I also wanted to sync the top of the turret (because it rotates), therefore I needed a way to have another networkview watch that transform and sync it.
I would like to thank you for your answers, and as raveren had pointed out, you cannot send an array of networkviewIDs, you need to do a seperate call for each (which in my case wouldnt work). So my solution was to modify the networkrigidbody script. basically I did this:
* My solution to this as of now *
...
void Start(){
...
turretAI = transform.GetComponent<TurretAI>();
...
}
...
if (stream.isWriting)
{
Vector3 pos = rigidbody.position;
Quaternion rot = rigidbody.rotation;
Vector3 velocity = rigidbody.velocity;
Vector3 angularVelocity = rigidbody.angularVelocity;
stream.Serialize(ref pos);
stream.Serialize(ref velocity);
stream.Serialize(ref rot);
stream.Serialize(ref angularVelocity);
if (turretAI != null){
Quaternion TurretTop_rot = turretAI.turretTop.transform.rotation;
stream.Serialize(ref TurretTop_rot);
}
}
// Read data from remote client
else
{
Vector3 pos = Vector3.zero;
Vector3 velocity = Vector3.zero;
Quaternion rot = Quaternion.identity;
Vector3 angularVelocity = Vector3.zero;
stream.Serialize(ref pos);
stream.Serialize(ref velocity);
stream.Serialize(ref rot);
stream.Serialize(ref angularVelocity);
if (turretAI != null){
Quaternion TurretTop_rot = Quaternion.identity;
stream.Serialize(ref TurretTop_rot);
turretAI.turretTop.transform.rotation = TurretTop_rot;
}
...
Basically what I’m doing is checking to see if I can get the “TurretAI” compomnent from the current object, if I can, then that means I can send the “turretTop” rotation values.
Probably not the best way, but it’s going to have to do for now as this has caused me too much headache already.
I am not using Network.Instantiate as I am keeping track of all items via my own object management system.
This was one of my possible solutions by setting the observed and viewID of each networkview. But I still had to somehow reference the same object somehow on the client side to do this properly, at the time I didn’t know of a reliable way of doing that.