Hello everyone,
I’m relatively new to unity and new to this forum. I developed games using XNA and Actionscript 3.0 but Unity is a whole different concept. Anyway I want to Instantiate syncronized objects without using Network.Instantiate. I’ve completed Leepo’s great tutorial about networking, but it didn’t help with this. I’ve set up network connections, players can either start a server or connect.
With these piece of codes, a player can observe the server’s movements. Actually it seems odd to me, because I call instantiate twice but there is only one instance of the prefab and it can only be controlled by the server. Thanks in advance.
Edit: I got this error. [quote]
Reload Assembly called from managed code directly. This will cause a crash. You should never refresh assets in synchronous mode or enter playmode synchronously from script code.
UnityEditor.BuildPlayerWindow:BuildPlayerAndRun()
[/quote]
What JRavey said; need to see more. As it stands you’re just locally instantiating things, and then you showed a SetPosition RPC that, without showing us how your using it, really doesn’t help at all.
If you’re not going to use Network.Instantiate your going to have to instantiate objects with an RPC sent to all other players (and call the function normally locally, AllBuffered is a little janky); just using Instantiate when a player connects and/or a server is initialized is only going to instantiate that object for that player, not across the network.
Once you work that out, if you want different players to have control over different objects, without Network.Instantiate you’re going to need to either manually allocate networkview ID’s or figure out some other solution for the server to keep track of what object belongs to what network player.
Thank you for your responses, my post wasn’t clear but yours are clear enough to let me understand that I’m doing it all wrong. I’ve started a new test project and these are my two classes.
Spawn.cs
using UnityEngine;
using System.Collections;
public class Spawn : MonoBehaviour {
public Transform player;
public ArrayList playerScripts = new ArrayList();
void OnServerInitialized()
{
SpawnPlayer(Network.player);
}
void OnPlayerConnected(NetworkPlayer newPlayer)
{
//NetworkViewID viewID = Network.AllocateViewID();
SpawnPlayer(newPlayer);
}
void SpawnPlayer(NetworkPlayer newPlayer)
{
int playerNumber = System.Int32.Parse(newPlayer + "");
Transform newTransform = Network.Instantiate(player, Vector3.zero, Quaternion.identity, playerNumber) as Transform;
NetworkView newNetworkView = newTransform.networkView;
playerScripts.Add(newTransform.GetComponent<Player>());
newNetworkView.RPC("SetPlayer", RPCMode.AllBuffered, newPlayer);
}
}
Player.cs (This class is a component of the object which also has the networkView component)
using UnityEngine;
using System.Collections;
public class Player : MonoBehaviour {
public NetworkPlayer owner;
float lastClientHInput = 0;
float lastClientVInput = 0;
float serverCurrentHInput = 0;
float serverCurrentVInput = 0;
void Awake()
{
if (Network.isClient)
{
enabled = false;
}
}
[RPC]
void SetPlayer(NetworkPlayer player)
{
owner = player;
if (player == Network.player)
{
enabled = true;
}
}
// Update is called once per frame
void Update()
{
if (owner != null Network.player == owner)
{
float hInput = Input.GetAxis("Horizontal");
float vInput = Input.GetAxis("Vertical");
if (lastClientHInput != hInput || lastClientVInput != vInput)
{
lastClientHInput = hInput;
lastClientVInput = vInput;
if (Network.isServer)
{
SendMovementInput(hInput, vInput);
}
else if (Network.isClient)
{
networkView.RPC("SendMovementInput", RPCMode.Server, hInput, vInput);
}
}
}
if (Network.isServer || Network.player == owner)
{
Vector3 moveDirection = new Vector3(serverCurrentHInput, 0.0f, serverCurrentVInput);
float speed = 5;
transform.Translate(speed * moveDirection * Time.deltaTime);
}
}
[RPC]
void SendMovementInput(float hInput, float vInput)
{
serverCurrentHInput = hInput;
serverCurrentVInput = vInput;
}
void OnSerializeNetwork(BitStream stream, NetworkMessageInfo info)
{
if (stream.isWriting)
{
Vector3 pos = transform.position;
stream.Serialize(ref pos);
}
else
{
Vector3 posReceive = Vector3.zero;
stream.Serialize(ref posReceive);
transform.position = posReceive;
}
}
}
This project works but as you see I’m using Network.Instantiate. To use Instantiate, I understood that I should allocate viewIDs manually and assign them to the networkviews but I’m not sure how and where. Thanks in advance.
There’s really nothing inherently wrong with using Network.Instantiate, is there a particular reason you want to avoid using it? I would advise against using it for things like projectiles and particle effects, as those things don’t require player control and thus, can just be instantiated locally for other clients via an RPC call, but I still use Network.Instantiate for things like player spawns and enemy AI spawns. I see no reason to reinvent the wheel.
The only issue I’ve run into is Network.Instantiate is essentially a buffered RPC call, but Network.Destroy is not, so if you spawn enemies or players that later get Network.Destroyed and then a new client connects, a crapton of players and enemies are going to spawn that should be dead, because the spawn got buffered and the destroy did not.
These issues however can be easily remedied by making sure you clean up your RPC’s by organizing them in groups and using RemoveRPCsInGroup periodically, as well as overloading any Network.Destroy’s inside buffered RPC calls.
As I said before I’m new to unity, multiplayer, networking etc. I’m a new member of a unity game developer group, the lead programmer told me about the instability of Network.Istantiate according to his experience and asked me to do it that way(without Network.Instantiate). I did not question much maybe I should but actually I really want to accomplish the job, that’s the real reason. Any tips, links or responses are well appreciated. Thanks again.
I’ve figured out a working example, but there are problems. This example can synchronize player positions but I think I can’t remove the RPCs. If a player disconnects and connects again a new viewID is allocated and I got these errors.
Spawner object has Spawn.cs script and a networkView component
using UnityEngine;
using System.Collections;
public class Spawn : MonoBehaviour
{
// Use this for initialization
//void Start ()
//{
//}
// Update is called once per frame
//void Update ()
//{
//}
public Transform playerPrefab;
ArrayList scriptList = new ArrayList();
void OnServerInitialized()
{
NetworkViewID viewID = Network.AllocateViewID();
Debug.Log(viewID);
networkView.RPC("SpawnPlayer", RPCMode.AllBuffered, viewID, Network.player);
}
void OnPlayerConnected(NetworkPlayer player)
{
NetworkViewID viewID = Network.AllocateViewID();
Debug.Log(viewID);
networkView.RPC("SpawnPlayer", RPCMode.AllBuffered, viewID, player);
}
void OnPlayerDisconnected(NetworkPlayer player)
{
foreach (Player script in scriptList)
{
if (player == script.owner)
{
script.networkView.RPC("Kill", RPCMode.All);
Network.RemoveRPCs(script.gameObject.networkView.viewID);
Network.Destroy(script.gameObject);
scriptList.Remove(script);
break;
}
}
}
void OnDisconnectedFromServer(NetworkDisconnection info)
{
Application.LoadLevel(0);
}
// RPC functions
[RPC]
void SpawnPlayer(NetworkViewID viewID, NetworkPlayer player)
{
GameObject playerClone = Instantiate(playerPrefab, Vector3.zero, Quaternion.identity) as GameObject;
NetworkView newView = playerClone.GetComponent<NetworkView>();
scriptList.Add(playerClone.GetComponent<Player>());
newView.viewID = viewID;
newView.RPC("SetPlayer", RPCMode.AllBuffered, player);
}
}
Player object has the Player.cs script and a networkView component
using UnityEngine;
using System.Collections;
public class Player : MonoBehaviour
{
// Use this for initialization
//void Start ()
//{
//}
public NetworkPlayer owner;
// Update is called once per frame
void Update ()
{
if (Network.player == owner)
{
float hInput = Input.GetAxis("Horizontal");
if (hInput != 0)
{
RePosition(hInput);
networkView.RPC("RePosition", RPCMode.Others, hInput);
}
}
void OnGUI()
{
//GUILayout.Label(" " + networkView.viewID.ToString());
}
[RPC]
void RePosition(float input)
{
transform.Translate(5 * input * Time.deltaTime, 0.0f, 0.0f);
}
[RPC]
void SetPlayer(NetworkPlayer player)
{
owner = player;
}
}