I am new to unity and currently trying to make a LAN multiplayer RPG game.
FYI, I have followed the official unity lan multiplayer guide and everything went well.
https://unity3d.com/learn/tutorials/topics/multiplayer-networking/introduction-simple-multiplayer-example
So far I got the players to load in and they are able to move. I wrote the following code below (under the void update routine) so that when the player is moving, it will randomize a number between 1 & 50 every 1 second and if the number is 25, we have randomly "encountered an enemy". When any player encounters an enemy I made it so everyone on the network goes to the "battle scene".
if (Input.GetKey("up") || Input.GetKey("down") || Input.GetKey("left") || Input.GetKey("right"))
{
if (Time.time > NextActionTime)
{
NextActionTime = Time.time + Period;
EnemyEncounter = Random.Range(1, 50);
if (EnemyEncounter == 25)
{
NetworkManager.singleton.ServerChangeScene("Scene2");
}
}
}
The code above works fine but I am not sure how, instead of loading everyone, to load only certain players into the battle scene.
For example:
Players enter a name before Hosting/Finding LAN game
Player 1 = Joe
Player 2 = Bob
Player 3 = Billy
Player 4 = Jim
On a preset label/text that loads the text in it saying "Joe,Billy". Now when ANY player finds an encounter, I want to ONLY load the players name "Joe" and "Billy" to the next scene while the others do not.
Is this possible? Any kind of help will be greatly appreciated.
Thanks All
I was trying different ideas and I got 2 different approaches:
1-As I already tell on the comments, try to nest lobbyManagers
2-"Fake" the scene split on lobbys
1.Nested Lobbys
Concept:
First Scene, MainLobby, 4 players enter, and go to the second scene
Second Scene, MainGame+SecondLobby, there are 4 players that comes from the first scene, but now 2 of them wants to go the third scene, so they use the SecondLobby to matchmake again.
Third Scene, SecondGame.
This is the best aproach I think if we are talking about performance, but it's elaborate cause:
-Actual Unity NetworkLobby uses singleton pattern, so you need to code the singleton parts again.
-LobbyManagers are builded with the DontDestroyOnLoad, so you were charging another lobby on your next scene.
-I don't really know if you can go back from third scene to second one :S
2.Fake Scenes
Well, welcome to "dirty tricks", the second concept is to:
First Scene, MainLobby, 4 players enter, and go to the second scene
Second Scene, MainGame, there are 4 players that comes from the first scene, but now 2 of them wants to go the third scene.
Third Scene, SecondGame.
But instead of "matchmake" again, what we do is to add the scene as an additive scene, but on different coordenates, and move the 2 players that wants to battle on the thirdScene. So the players will think that they are on different scene, but they aren't they are just being move. Thinks to get in mind:
-Maybe you don't really need to use the additive scene, just build on the same scene, on different coordenates. (https://docs.unity3d.com/ScriptReference/SceneManagement.LoadSceneMode.Additive.html)
-Think that they still be 4 networked players on the same scene, so maybe you want to "disable" some networkMessages, to only affect certain players on certain "scenes". (https://docs.unity3d.com/ScriptReference/Networking.NetworkClient.Send.html)
But if you achieve some other approach let me know, it really gives interesting game design stuff! :D
Related
I'm new to unity and C# and I have a few questions. Here's the context:
I've created 7 different scenes which are basically different mini-games. My goal is the following: At the start, the participant selects mode 1 or mode 2. If they chose mode 1, scenes 1,2 and 3 should be played next. If they choose mode 2, scenes 2,4,5,6,7 should be played next. At the end of the mini-games, I want to show the participant's score for all mini-games with visual graphics.
So here are my questions:
How can I set my game in such a way that when the participant selects 'mode 1', the specific scenes 1, 2 and 3 are played? Or if they select 'mode 2', scenes 2, 4, 5, 6, and 7 are played? And is their a way to make them play in a random order ?
How can I save the scores of every mini-game so I can access them at the end and use the scores to make graphics ?
For the scene order, I did somethig like this:
void Start()
{
RandNum = Random.Range(0, 8);
if (RandNum == 0)
{
SceneManager.LoadScene(MiniGame1);
}
if (RandNum == 1)
{
SceneManager.LoadScene(MiniGame2);
}
if (RandNum == 2)
{
SceneManager.LoadScene(MiniGame3);
}
...etc. Would this work?
And for the score saves, when I searched online, I found that I could use PlayPrefs.SetIn("Score mini-game 1", score1) for example. Is this a good method? and if so, how would I retrieve this information at the end ?
Thank you so much for your help :)
To get your score from PlayerPrefs use PlayerPrefs.GetInt
For Scene loading sequence you can create some ScriptableObject with level queue presets (like int arrays for each mode).
For overall architecture I would create some gameobject that will be preserved through all game lifecycle (i.e. not being destroyed after new scene is loaded) and use that gameobject to hold your game manager. For that use DontDestroyOnLoad. But this method may be not ideal for your case, so give it some thoughts before choosing some approach.
enter image description hereI'm using mirror for local server between multiply gamePlayers.
I have a problem sync non players objects.
I want each Player to have a button to be able to rool two dices and that the player on host will be able to see what client do and apposite. I'm still confused , don't know when to use [Command] and [ClientRpc]
btw, I create my dices like that, and called this on the method OnStartServer():
GameObject newPrize = Instantiate(prizePrefab.gameObject, spawnPosition, Quaternion.identity);
// add this game object to all clients
NetworkServer.Spawn(newPrize);
Thank you so much!
I am trying to build a MiniMax algorithm for my chess game. To run the algorithm the game needs to destroy and respawn game objects multiple times between updates. The problem is that the Void Start function only runs the first time I spawn the object. When destroying the object and spawning it again during the same update the Void Start does not take effect.
The problem is with my Chess Pieces. I have a parent class for all pieces called Pices.cs and a bunch of child classes for the specific piece. The Pices.cs class has a char inherited and updated with Void Start by the other piece classes. The default is 'F' and then in Void start in the King class it will be updated to 'K', in Void start in queen class it will be updated to 'Q', and so on...
An example of the problem in action during one update of the game state:
if I have two ponds which is able to take the enemy queen. I would like to take the enemy queen with my first pond, reverse the move and Instantiate the queen back, then destroy the queen with my other pond, reverse the move and Instantiate the queen back, the do something totally different. But when the queen gets instantiated the second time doing this update the identification char is 'F' and not 'Q' as I wish.
The Relevant Code and notes:
All movement in-game is handled by Board_Manager.cs
Droning.cs = Queen pice in my language
Reverse move(){...} reset the game stage to start and dose all moves again except for the last one
Endgame(){...} Destroy all pice game objects and Instantiate them on the start position
The current move notation is as follows:
1. Piece Letter, 2. from x, 3. from y, 4. to x, 5. to y, 6. Death piece letter (if no pice died then -)
Picture of relevant pices.cs code 1
Picture of relevant Queen.cs code
Picture of ReversMove() in Board_Manager.cs
Picture of MiniMax base algorithem
Print of resulting move notation
I know this is a bit convoluted but I hope some of you understand the problem and can help me out here. This is part of my examination so I would really like to get this fixed (:
In my game I have several levels, each one has 6 scenes, the scenes names are: Scene 1, Scene 2, Scene 3 ...etc...
When the player lose, the current scene should be restarted, so I used this code:
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
I didn't use "(...)GetActiveScene().name);" because the scenes names are repeated on each level.
The problem I have is when the player lose in level2 (scene 6), the scene 6 of level1 is loaded instead of restarting scene 6 of level2. Do you know what's the problem in my code?
Maybe not an answer to why this happens in your specific case but two suggestions I would prefer:
Just a workaround but how about naming your scenes properly instead like e.g. Level1_Scene1, Level2_Scene3 etc
so they are all uniquely identifiable using GetActiveScene().name
Alternatively you could also try using GetActiveScene().path (which is allways unique) since LoadScene takes
Name or path of the Scene to load.
I am creating an arena style battle game in Unity and I am having a problem with respawning players. Here's how it works right now.
When a player is killed it is put into a list of killed players to be respawned and it's player object is destroyed. The game then loops thru the list of killed players and selects a random available spawn point then respawns the player there. An available spawn point is any spawn point that is not triggered by a player being inside it's spawn area.
The problem comes when 2 players die at the same time, or at least extremely close to the same time and the randomly selected spawn point ends up to be the same because it didn't have enough time to process as triggered. When this happens all of unity crashes and I have to restart it completely.
I assume that in order to fix this, I need to keep Unity from spawning them at the same time, but I thought that would be fixed by looping thru the list. How should I actually go about spawning 2 players that die at the same time more safely?
This is the classic queue example the same thing happens in multi threaded applications. Two things you can do here:
Diversion of concern
Remove the conflict from beginning
In the first method you create an script outside of your player script for example in the arena it self and create a method there to select the next spawning point. This can be ordinal instead of random and each player upon death asks the script to select the next spawning point for it and no conflict over one point.
In the second method each player will have it's own spawning point for example an offset from the spawning points defined in the arena. For example player 1 will have offset zero and spawn right on spawning point then player two will have offset 1 which will spawn 1 unit off of the spawning point.
I prefer the first method if the number of players are limited. If you have many players then the queue might be a bother.
Hope it helps :)
I figured out my problem and I'm able to keep it with random spawn points. The problem didn't apparently have to do with 2 players dying at the same time so much as it had to do with a player dying while on a spawnpoint. When this happens it would not run the OnTriggerLeave() method and therefore would not count as an available spawnpoint even tho nothing was there.
I fixed it by having each spawnpoint hold a list of all the game objects that were triggering it which would change as players entered and exited the space. Then when a player was killed, it would check each spawnpoint's list to see if it contained the player's game object. If it found a match then I untrigger the spawnpoint and it appears as available.
A better approach to this which I am going to do instead is to check the list to see if there are any gameobjects in the spawnpoint's list and it should only be available if there are none. Because the current way doesn't account for other objects also triggering the point.