- Home /
MP randomly generated levels, other player see's a different one than server host?
Like the title says, I just added a Mp mode to my game. It works, but the only thing tis that levels are randomly generated so now each player sees a different world. Here's my generation script:
using System.Collections;
public class LevelGenMP : MonoBehaviour {
public int MaxObjects;
public int MaxRange;
public GameObject[] Objects;
public Vector3[] VObjects;
// Use this for initialization
void Start () {
}
void StartingServer(){
if(Network.isServer){
if(PlayerPrefs.GetString("World Size") == "Small"){
for(int i = 0; i < 35; i++){
//Instantiate(Objects[Random.Range(0, Objects.Length - 1)], new Vector3(Random.Range(-MaxRange, MaxRange), this.transform.position.y, Random.Range(-MaxRange, MaxRange)), Quaternion.identity);
GameObject newThing = (GameObject) GameObject.Instantiate(Objects[Random.Range(0, Objects.Length - 1)], new Vector3(Random.Range(-150, 150), this.transform.position.y, Random.Range(-MaxRange, MaxRange)), Quaternion.identity);
newThing.transform.parent = this.transform;
VObjects[i] = newThing.transform.position;
}
}
if(PlayerPrefs.GetString("World Size") == "Medium"){
for(int i = 0; i < 70; i++){
//Instantiate(Objects[Random.Range(0, Objects.Length - 1)], new Vector3(Random.Range(-MaxRange, MaxRange), this.transform.position.y, Random.Range(-MaxRange, MaxRange)), Quaternion.identity);
GameObject newThing = (GameObject) GameObject.Instantiate(Objects[Random.Range(0, Objects.Length - 1)], new Vector3(Random.Range(-250, 250), this.transform.position.y, Random.Range(-MaxRange, MaxRange)), Quaternion.identity);
newThing.transform.parent = this.transform;
VObjects[i] = newThing.transform.position;
}
}
if(PlayerPrefs.GetString("World Size") == "Large"){
for(int i = 0; i < 70; i++){
//Instantiate(Objects[Random.Range(0, Objects.Length - 1)], new Vector3(Random.Range(-MaxRange, MaxRange), this.transform.position.y, Random.Range(-MaxRange, MaxRange)), Quaternion.identity);
GameObject newThing = (GameObject) GameObject.Instantiate(Objects[Random.Range(0, Objects.Length - 1)], new Vector3(Random.Range(-250, 250), this.transform.position.y, Random.Range(-MaxRange, MaxRange)), Quaternion.identity);
newThing.transform.parent = this.transform;
VObjects[i] = newThing.transform.position;
}
}else{
for(int i = 0; i < 35; i++){
//Instantiate(Objects[Random.Range(0, Objects.Length - 1)], new Vector3(Random.Range(-MaxRange, MaxRange), this.transform.position.y, Random.Range(-MaxRange, MaxRange)), Quaternion.identity);
GameObject newThing = (GameObject) GameObject.Instantiate(Objects[Random.Range(0, Objects.Length - 1)], new Vector3(Random.Range(-150, 150), this.transform.position.y, Random.Range(-MaxRange, MaxRange)), Quaternion.identity);
newThing.transform.parent = this.transform;
VObjects[i] = newThing.transform.position;
}
}
}
if(Network.isClient){
SetLevelFromMaster(VObjects);
}
}
[RPC]
void SetLevelFromMaster(Vector3[] Positions){
for(int i = 0; i < 35; i++){
GameObject newThing = (GameObject) GameObject.Instantiate(Objects[Random.Range(0, Objects.Length - 1)], new Vector3(VObjects[i].x, VObjects[i].y, VObjects[i].z), Quaternion.identity);
newThing.transform.parent = this.transform;
}
}
}
Here's the connection code(direct connect code)
using UnityEngine;
using System.Collections;
public class ConnectionGUI : MonoBehaviour {
public string remoteIP= "127.0f.0.1f";
public int remotePort= 25000;
public int listenPort= 25000;
public bool useNAT= true;
public string yourIP= "";
public string yourPort= "";
public GameObject Level;
void Awake (){
Level = GameObject.Find("level");
if (FindObjectOfType(typeof(MasterServerGUI))){
this.enabled = false;
}
if(FindObjectOfType(typeof(UDPConnectionGUI)))
this.enabled = false;
}
void OnGUI (){
if (Network.peerType == NetworkPeerType.Disconnected){
// If not connected
if (GUI.Button (new Rect(10,10,100,30),"Connect"))
{
// Connecting to the server
Network.Connect(remoteIP, remotePort);
Level.SendMessage("StartingServer");
Debug.Log("Server = " + Network.isServer + " Client = " + Network.isClient);
}
if (GUI.Button (new Rect(10,50,100,30),"Start Server")){
// Creating server
Network.InitializeServer(8 ,listenPort, false);
// Notify our objects that the level and the network is ready
foreach (GameObject go in FindObjectsOfType(typeof(GameObject))){
go.SendMessage("OnNetworkLoadedLevel", SendMessageOptions.DontRequireReceiver);
}
Level.SendMessage("StartingServer");
Debug.Log("Server = " + Network.isServer + " Client = " + Network.isClient);
}
remoteIP = GUI.TextField(new Rect(120,10,100,20),remoteIP);
remotePort = int.Parse(GUI.TextField(new Rect(230,10,40,20),remotePort.ToString()));
}else{
// If connected
// Getting your ip address and port
yourIP = Network.player.ipAddress;
yourPort = Network.player.port.ToString();
GUI.Label(new Rect(140,20,250,40),"IP Adress: "+yourIP+":"+yourPort);
if (GUI.Button (new Rect(10,10,100,50),"Disconnect")){
// Disconnect from the server
Network.Disconnect(200);
}
}
}
void OnConnectedToServer (){
// Notify our objects that the level and the network is ready
foreach (GameObject go in FindObjectsOfType(typeof(GameObject)))
go.SendMessage("OnNetworkLoadedLevel",
SendMessageOptions.DontRequireReceiver);
}
void OnDisconnectedFromServer (){
if (this.enabled != false)
Application.LoadLevel(Application.loadedLevel);
else{
//NetworkLevelLoad _NetworkLevelLoad = FindObjectOfType(typeof(NetworkLevelLoad));
NetworkLevelLoad _NetworkLevelLoad = FindObjectOfType(typeof(NetworkLevelLoad)) as NetworkLevelLoad;
_NetworkLevelLoad.OnDisconnectedFromServer();
}
}
}
and here's the game: https://dl.dropbox.com/u/85846965/OGAM/january/Webplayer/Webplayer.html
Okay. Now, did you try copying the generated level from the host to the clients?
How would I do that? Sorry, just getting into networking.
Answer by jernkuan · Jan 25, 2013 at 09:17 AM
I would think you should be sending a seed for the random generator function, instead of the coordinate of each game object. Since the random functions are basically PRNG which requires an initial seed. This would reduce the network traffic across your clients.
http://gamedev.stackexchange.com/questions/46993/transmit-map-vs-transmit-seed
What I'm wondering is: 1. How would I use this for the instiate code 2. How would I send the seed to the client from the server
All that's saying is that you need to set your random seed before you generate, and send that same seed across.
int seed = Random.Range(1, 999999999);
Random.seed = seed;
By using an RPC call as is demonstrated immediately below this comment, and having a NetworkView attached to the Game Object that you're sending RPCs across to. You'd just send your seed ins$$anonymous$$d of an array of Vec3s.
http://docs.unity3d.com/Documentation/Components/net-UnityNetworkElements.html
http://docs.unity3d.com/Documentation/Components/net-RPCDetails.html
Tried it, but I need to store the x and position of each object so I'll stick with vector3. Other answer is so close, it's just that the client has a separate script than the server host, making all the vector3 positions 0,0,0. How would I make them share the same script ins$$anonymous$$d?
Scroll down just slightly and it should smack you in the face.
if (Network.isServer)...
Answer by iwaldrop · Jan 22, 2013 at 06:39 AM
You're going to need the server to communicate the placement of objects to it's clients. I imagine the best way to do this in your case is to cache and send an array of Vector3s to connecting clients. Once they receive them then you can build the level according to the master's 'blueprint'.
[RPC]
void SetLevelFromMaster(Vector3[] positions)
{
foreach (Vector3 v in positions)
{
//Instantiate GOs just as your above code shows.
}
}
If you have several different types of blocks then it's best to have an enumeration or other index schema that you can use to refer to each one as and send it in the call as an int[]. Hope that works for ya!
How would I go about only running the generation code for the server host? I'm thinking I do that then use this to generate the level for connecting players.
Wow! You mentioned your game was working, so I assumed that you'd already conquered this step.
If you're using Unity Networking the check is 'Network.isServer'.
if (Network.isServer)
{
// do server stuff
}
else
{
// do client stuff
}
EDIT: And you're right; you want the server to generate the level first and provide it to the clients. You should implement a hook for clients to request it from the Server as well as a method that the Clients listen to, as these calls are executed only on the target machine.
new to networking, mostly followed a tutorial. I'll try this when I get home
Not working, server host dosen't generate the level anymore:
using UnityEngine;
using System.Collections;
public class LevelGen$$anonymous$$P : $$anonymous$$onoBehaviour {
public int $$anonymous$$axObjects;
public int $$anonymous$$axRange;
public GameObject[] Objects;
public Vector3[] ObjPos;
// Use this for initialization
void Start () {
if(Network.isServer){
if(PlayerPrefs.GetString("World Size") == "Small"){
for(int i = 0; i < 35; i++){
//Instantiate(Objects[Random.Range(0, Objects.Length - 1)], new Vector3(Random.Range(-$$anonymous$$axRange, $$anonymous$$axRange), this.transform.position.y, Random.Range(-$$anonymous$$axRange, $$anonymous$$axRange)), Quaternion.identity);
GameObject newThing = (GameObject) GameObject.Instantiate(Objects[Random.Range(0, Objects.Length - 1)], new Vector3(Random.Range(-150, 150), this.transform.position.y, Random.Range(-$$anonymous$$axRange, $$anonymous$$axRange)), Quaternion.identity);
newThing.transform.parent = this.transform;
ObjPos[i] = newThing.transform.position;
}
}
if(PlayerPrefs.GetString("World Size") == "$$anonymous$$edium"){
for(int i = 0; i < 70; i++){
//Instantiate(Objects[Random.Range(0, Objects.Length - 1)], new Vector3(Random.Range(-$$anonymous$$axRange, $$anonymous$$axRange), this.transform.position.y, Random.Range(-$$anonymous$$axRange, $$anonymous$$axRange)), Quaternion.identity);
GameObject newThing = (GameObject) GameObject.Instantiate(Objects[Random.Range(0, Objects.Length - 1)], new Vector3(Random.Range(-250, 250), this.transform.position.y, Random.Range(-$$anonymous$$axRange, $$anonymous$$axRange)), Quaternion.identity);
newThing.transform.parent = this.transform;
ObjPos[i] = newThing.transform.position;
}
}
if(PlayerPrefs.GetString("World Size") == "Large"){
for(int i = 0; i < 70; i++){
//Instantiate(Objects[Random.Range(0, Objects.Length - 1)], new Vector3(Random.Range(-$$anonymous$$axRange, $$anonymous$$axRange), this.transform.position.y, Random.Range(-$$anonymous$$axRange, $$anonymous$$axRange)), Quaternion.identity);
GameObject newThing = (GameObject) GameObject.Instantiate(Objects[Random.Range(0, Objects.Length - 1)], new Vector3(Random.Range(-250, 250), this.transform.position.y, Random.Range(-$$anonymous$$axRange, $$anonymous$$axRange)), Quaternion.identity);
newThing.transform.parent = this.transform;
ObjPos[i] = newThing.transform.position;
}
}
}else{
SetLevelFrom$$anonymous$$aster(ObjPos);
}
}
[RPC]
void SetLevelFrom$$anonymous$$aster(Vector3[] positions){
foreach (Vector3 v in positions){
for(int i = 0; i < 70; i++){
//Instantiate(Objects[Random.Range(0, Objects.Length - 1)], new Vector3(Random.Range(-$$anonymous$$axRange, $$anonymous$$axRange), this.transform.position.y, Random.Range(-$$anonymous$$axRange, $$anonymous$$axRange)), Quaternion.identity);
GameObject newThing = (GameObject) GameObject.Instantiate(Objects[Random.Range(0, Objects.Length - 1)], new Vector3(Random.Range(-250, 250), this.transform.position.y, Random.Range(-$$anonymous$$axRange, $$anonymous$$axRange)), Quaternion.identity);
newThing.transform.parent = this.transform;
ObjPos[i] = newThing.transform.position;
}
}
}
}
Was this not working already as a Network Game? I'm confused, because you said it was working. So...if you're converting a working game into a network game then you need to do several things; first of which is probably read a tutorial or download a networked project and look at example code.
You need to initialize a server for Network.isServer to return true, e.g.,
Network.InitializeServer(8,8008, false);
Your answer
![](https://koobas.hobune.stream/wayback/20220613091349im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Unity networking tutorial? 6 Answers
Multiple world spaces? 0 Answers
[Networking]How to call a command function from a UI element(a button) 2 Answers
Networking Player Nametag 1 Answer
Client can't spawn GameObject's 0 Answers