Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
0
Question by MikGames · Oct 03, 2016 at 05:58 AM · multiplayerphotonspawnpointssynchronize

How to create several spawnpoints without spawning at the same place in Photon

Hello,

yes I know there's a similar question to this already, but it's not the same question, because I'm trying to spawn players at several spawnpoints and not objects.

So this is my code:

 using System.Collections.Generic;


 public Transform[] spawns;
 public int amountThings = 2;
 public int i = 0;

 void Start()
 {
     Connect();
 }

 void Connect ()
 {
     PhotonNetwork.ConnectUsingSettings(verNum);
     Debug.Log("Connecting...");
 }

 public void spawnPlayer()
 {
     List<Transform> freeSpawnPoints = new List<Transform>(spawns);

         int index = Random.Range(0, freeSpawnPoints.Count);
         for (i = 0; i < amountThings; i++)
         {
             if (freeSpawnPoints.Count <= 0)

                 Debug.LogError("Not enough spawnpoints!!!!!!!!!");

             Transform pos = freeSpawnPoints[index];

             freeSpawnPoints.RemoveAt(index); // remove the spawnpoint from our temporary list
             GameObject pl = PhotonNetwork.Instantiate(playerPref.name, pos.position, pos.rotation, 0) as GameObject;

             pl.GetComponent<RigidbodyFPSWalker>().enabled = true;
             pl.GetComponent<RigidbodyFPSWalker>().fpsCam.SetActive(true);

             RigidbodyFPSWalker.speed = 10.0f;
             SimpleSmoothMouseLook.disabled = false;

             pl.GetComponent<Animations>().enabled = true;
         }
  }

The players are still spawning at the same place. Every player should has an own spawn place.

So I think, that the list of the spawnpoints must be synchronized to the other players. How can I synchronize it to the others?

I'll be very happy about an helpful answer. Thank you for reading.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by ChristianSimon · Oct 04, 2016 at 11:42 AM

With the logic above you have to synchronize the original structure ('spawns'). So whenever a player spawn you remove one entry from the copy created within the spawnPlayer() function. You need to apply this change to the original structure too and share this event with all others active and upcoming players. since this seems somehow too complicated I want to make another suggestion you might think about.

In short: Master Clients sets spawn position for himself and all upcoming players. In detail: Master Client creates a structure containing all available spawn points at the beginning. When OnJoinedRoom() is called he selects one of these points, creates his character from prefab and removes the spawn point entry from the list. Most likely before. Whenever OnPhotonPlayerConnected(...) is called (another players joined the room) the Master Client selects another spawn position and stores it in the custom room properties as key-value-pair (e.g. userId and spawn position). OnPhotonCustomRoomPropertiesChanged(...) will be called and the client can check the spawn position allocated to his userId.

However, when going with this attempt (Master Clients selects spawn positions for other players), there are additional options for solving this problem.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image MikGames · Oct 14, 2016 at 02:37 PM 0
Share

How do I apply the changes to the original list?

avatar image MikGames · Nov 27, 2016 at 05:27 PM 0
Share

I will try this in the next days. I'm sitting on this many weeks already. I hope I will get a solution in the following week.

avatar image
0

Answer by MikGames · Dec 03, 2016 at 08:50 PM

So now I have this code and my question is how do I get values from the Hashtable for a specific player?:

 public void OnPhotonPlayerConnected()
     {
         DebugConsole.Log("Player " + PhotonNetwork.player.name + " joined.");

         if (PhotonNetwork.isMasterClient) 
         {
             List<Transform> freeSpawnPoints = new List<Transform>(spawns);
             int index = Random.Range(0, freeSpawnPoints.Count);
             Transform pos = freeSpawnPoints[index];

             Hashtable t = new Hashtable();
             t.Add("Player", PhotonNetwork.player.name);
             t.Add("Location", pos);

             PhotonNetwork.room.SetCustomProperties(t);
         }
         else
         {
              RoomOptions roomOptions = new RoomOptions();
              string pos = (string) PhotonNetwork.room.customProperties[RoomProperty.Location]; <-- ??????????
              spawnPlayer(pos);
         }
     }

 public void OnJoinedRoom()
 {
     isConnected = true;

     if (PhotonNetwork.isMasterClient)
     {
         List<Transform> freeSpawnPoints = new List<Transform>(spawns);
         int index = Random.Range(0, freeSpawnPoints.Count);
         DebugConsole.Log("SpawnPoints: " + freeSpawnPoints.Count);
         DebugConsole.Log("index: " + index);

         if (freeSpawnPoints.Count <= 0)
         {
             DebugConsole.Log("Not enough spawnpoints!!!!!!!!!", "error");
         }
         else
         {
             Transform pos = freeSpawnPoints[index];
             DebugConsole.Log("Pos: " + pos + pos.position + pos.rotation);
             freeSpawnPoints.RemoveAt(index);
             spawnPlayer(pos);
         }
     }
 }

@ChristianSimon

Comment
Add comment · Show 16 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image ChristianSimon · Dec 05, 2016 at 09:43 AM 1
Share

Is the connecting player network instantiated (PhotonNetwork.Instantiate(...)) or manually instantiated on each client? The following is for the first case.

The callback OnPhotonPlayerConnected needs a parameter in order to work as expected. It is void OnPhotonPlayerConnected(PhotonPlayer newPlayer). Additionally when this callback is executed, the room properties might not be updated when you try to get them in the 'else' case.

$$anonymous$$aybe in this case you should use player properties ins$$anonymous$$d of room properties.

 void OnPhotonPlayerConnected(PhotonPlayer newPlayer)
 {
     if (PhotonNetwork.is$$anonymous$$asterClient)
     {
         // Select Spawn Position and add to Hashtable
 
         newPlayer.SetCustomProperties(Hashtable propertiesToSet, null, false);
     }
 }

Then you need a callback to handle the change of the properties: void OnPhotonPlayerPropertiesChanged(object[] playerAndUpdatedProps). In this object[] you receive a PhotonPlayer object at index 0 and a Hashtable at index 1. When this function is called, check if object[0].ID equals PhotonNetwork.player.ID. In that case you are on the new connected client and can call PhotonNetwork.Instantiate with the received position.

Hopefully this is somehow understandable.

In short: Client joins room -> OnPhotonPlayerConnected(...) is called and $$anonymous$$asterClient selects Spawn position and sets Custom Player Properties -> Changes are received by all clients, but only matching client will proceed and calls PhotonNetwork.Instantiate(...).

avatar image MikGames ChristianSimon · Dec 05, 2016 at 07:25 PM 0
Share

So now I've changed my code. The "OnPhotonPlayerPropertiesChanged" method looks like this:

 public void OnPhotonPlayerPropertiesChanged(object[] playerAndUpdatedProps)
 {
     PhotonPlayer player = playerAndUpdatedProps[0] as PhotonPlayer;
     Hashtable t = playerAndUpdatedProps[1] as Hashtable;

     Debug.Log("photonplayer.id: " + player.ID + " photonid: " + PhotonNetwork.player.ID);

     if ((player.ID.Equals(PhotonNetwork.player.ID))
     {
         DebugConsole.Log("True");
         Debug.Log(t);
         string position = (string) t[1];
         DebugConsole.Log("pos:" + position);
         Debug.Log(position);
         DebugConsole.Log(player.name);

         Transform pos = (Transform) t[0];
         spawnPlayer(pos);
     }
 }

The "OnPhotonPlayerConnected":

public void OnPhotonPlayerConnected(PhotonPlayer newPlayer) { DebugConsole.Log("Player " + newPlayer + " joined."); DebugConsole.Log("Is not $$anonymous$$asterClient");

     if (PhotonNetwork.is$$anonymous$$asterClient) 
     {
         //Spawnpoint aussuchen und "pos" setzen
         List<Transform> freeSpawnPoints = new List<Transform>(spawns);
         int index = Random.Range(0, freeSpawnPoints.Count);
         Transform pos = freeSpawnPoints[index];
         freeSpawnPoints.RemoveAt(index);
         DebugConsole.Log("FreeSpawnPoints: " + freeSpawnPoints.Count);

         //Hashtable
         Hashtable t = new Hashtable();
         t.Add("Loc", pos);

         //Für den neuen Spieler den Spawnpunkt definieren
         newPlayer.SetCustomProperties(t, null, false);
     }
 }

$$anonymous$$y problem now is, that "player.id" is equals 1 while the "PhotonNetwork.player.ID" is equals 2. I don't find any solution for this for a while.,..

@ChristianSimon

avatar image ChristianSimon MikGames · Dec 08, 2016 at 09:41 AM 0
Share

$$anonymous$$y problem now is, that "player.id" is equals 1 while the "PhotonNetwork.player.ID" is equals 2. I don't find any solution for this for a while.,..

This is correct if you use network instantiation now. Ins$$anonymous$$d of your spawnPlayer(...) function [I don't know what happens inside] you can call PhotonNetwork.Instantiate(...) to create the player object at the given position across the network. This also makes sure, that Ownership and other properties are set correctly. The condition (player.ID == PhotonNetwork.player.ID) prevents other players from creating the object, too.

Show more comments
avatar image MikGames · Dec 23, 2016 at 05:00 PM 0
Share

Hello @ChristianSimon,

thank you for the detailed answer and for the source code.

$$anonymous$$y problem is further on that the PhotonPlayer.ID not equals the Photon ID.

Here is a picture about it: http://imgur.com/4xfpgT5

And here's another picture, with a "Can't serialize" exception: http://i.imgur.com/BqpNW$$anonymous$$f.png

So everytime the PhotonPlayer.ID is equals one and with every join the Photon ID gets up.

P.S.: Are you german?

avatar image ChristianSimon MikGames · Jan 03, 2017 at 09:25 AM 1
Share

Hi,

sorry for the late response, I haven't been in office the last two weeks.

Can you share me your latest source code so I can check on that? This might be easier solving the problem.

Some words on the "Can't serialize" exception: by default PUN is not able to serialize Unity's Transform objects as far as I know. This is the reason why I only used a Vector3 object to tell the new client his spawn position. However when adding the spawn data to the Hashtable, you can also add Rotation (Quaternion) and Scale (Vector3) data to it ins$$anonymous$$d of using the Transform object itself. To be honest I'm currently not sure if a Quaternion will work. If this also throws an exception you can use an array with four elements representing the Quaternion.

And yes, I'm german. :)

avatar image ChristianSimon ChristianSimon · Jan 09, 2017 at 09:06 AM 1
Share

Hey,

ich habe jetzt ausgehend von deinem Sourcecode ein paar Änderungen vorgenommen. Das Ganze funktioniert soweit in meinem relativ leerem Testprojekt. Hier der aktualisierte Code: http://pastebin.com/2$$anonymous$$5Xuf9h

Show more comments
avatar image ChristianSimon MikGames · Jan 12, 2017 at 09:45 AM 1
Share

Wenn ein Spieler das Spiel verlässt, kannst du das mit Hilfe des callbacks void OnPhotonPlayerDisconnected(PhotonPlayer otherPlayer) { ... } erkennen und darauf reagieren. In deinem Fall macht das entsprechend nur der $$anonymous$$asterClient. Du kannst über otherPlayer.customProperties nun wieder auf die Properties zugreifen, die du vorher für "Position" und "Rotation" gespeichert hast und diese Daten dann "zurückführen". Problem ist, dass man keine Transform Objekte per Code erzeugen kann (soweit ich das gerade weiß). Das heißt, dass man das Ganze etwas anders angehen muss. Dazu fallen mir spontan zwei $$anonymous$$öglichkeiten ein.

1) Die ursprüngliche "spawns" Liste nicht bearbeiten, sondern immer nur auf einer $$anonymous$$opie davon. Dadurch kannst du immer wieder auf alle Spawnpunkte zugreifen und kannst bei einem Spielerdisconnect von "spawns" in "spawnsWorkingCopy" kopieren.

2) Ein neues GameObject erzeugen und dessen Transform $$anonymous$$omponente anpassen. Dann hast du nach einiger Zeit allerdings zahlreiche unnütze Objekte herumliegen, die sich irgendwann negativ auf die Performance auswirken können (außer du entfernst die Vorherigen).

avatar image MikGames ChristianSimon · Jan 15, 2017 at 03:48 PM 0
Share

Okay also: Ich habe nun den folgenden Code:

 public void OnPhotonPlayerDisconnected(PhotonPlayer player)
 {
     if (PhotonNetwork.is$$anonymous$$asterClient)
     {
         Hashtable ht = player.CustomProperties;

         Vector3 position = (Vector3)ht["Position"];
         Quaternion rotation = (Quaternion)ht["Rotation"];
         int index = (int)ht["index"];

         List<Transform> freeSpawnPoints = new List<Transform>(spawns);
         freeSpawnPoints.Insert(index, position); //Funktioniert nicht
     }
 }

Aber ich kann "freeSpawnPoints.Insert(index, position);" nicht benutzen, da ja ein Transform Objekt benötigt wird. Ich habe gerade keine Ahnung, wie ich das nun machen könnte, da man ja keine Transform Objekte per Code erstellen kann.

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

How to identify players on Photon Unity? 2 Answers

How can I Instantiate only one GameObject Using PhotonNetwork. 0 Answers

Sync movements Photon 0 Answers

Raycast over Photon 0 Answers

Bolt and PUN in same Unity project?? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges