Unity - multiplayer game using mirror - c#

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!

Related

C#: Unity Photon doesn't add physics to the second connection

I am trying to make a multiplayer air hockey game in Unity, but encountered some problems. When the first user creates the room, the hockey puck is spawned along with the first player's mallet (the object you hit the puck with). When the second player connects to the Photon server, their mallet is spawned.
The issue is when the second player hits the puck with his mallet, the Rigidbody physics don't work on the puck. The puck slides right along the mallet, but doesn't bounce off the mallet.
I am new to Unity, so I don't know what part of the code to post. But this is the code where I spawn the items:
private void Start() {
Vector2 puckPosition = new Vector2(0,0);
Vector2 randPos = new Vector2(Random.Range(minX, maxX), Random.Range(minY, maxY));
if(CreateAndJoinRooms.intHold == 0) { // If the user created the room, the result is 0
PhotonNetwork.Instantiate(puckPrefab.name, puckPosition, Quaternion.identity);
}
PhotonNetwork.Instantiate(playerPrefab.name, randPos, Quaternion.identity);
}
Mallet Prefab:
Puck Prefab:
You probably need to add a RigidBodyView component
It sounds like the problem is with Photons object ownership. According to the images, the puck prefabs Ownership Transfer = Fixed, which means it will never change. So it's is spawned and controlled by player 1 (as the Master Client), and player 1 is responsible for moving/controlling it.
In this case, Player 1 spawns the puck, player 2 strikes it and affects its Rigidbody2D, but then the next PhotonView Transform & Rigidbody2D updates are received, which set the location & velocity according to player 1s view, ignoring player 2s impact.
A some possible solutions:
Setup a Photon RPC or Photon Event that Player 2 calls to let the Master Client know an impact has happened and to adjust the physics.
Change the OwnerShip Transfer to Take Over, and when a collision is detected have the colliding player take ownership of the puck.

Lan Multiplayer Scene Change

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

How to make one more try function in a Unity game

I don't know how can I do it. You lose a game, if gameobject falls down and collides with the collider. I want to add a function that asks to the player if he wants another try, if yes it will reverse some time so the gameobject that fall down will be back on the screen and the user is allowed to play once again. Is there some sort of time function/method to do this?
Hope you understand.
void OnCollisionEnter2D(Collision2D col) {
if(col.gameObject.tag=="Collider") {
Vector2 checkpoint = new Vector2(transform.position.x, transform.position.y +5)
}
}
void Reset(){
this.transform.position = checkpoint;
}
I created a child object for that collider. And I moved the child to where I wanted the player to live when I collided with the collider.
Void OnCollisionEnter2D(Collision2D col)
{
if(col.gameobject.tag=="die")
{
checkpoint = col.transform.GetChil(0).position;
}
}
void Reset(){
Player.transform.position = checkpoint;
}
Your error is because you are missing the new keyword before Vector2
When using C# you need to use the new keyword in front of all
constructors. Constructors are like functions that are used to create
new objects (or scructs). They always have the same name as the type
of object you are creating.
So you should write
Vector2 checkpoint = new Vector2(transform.position.x, transform.position.y +5)
instead of:
Vector2 checkpoint = Vector2(transform.position.x, transform.position.y +5)
Edit: Now you edited your question without the error, and since you are still trying to find a method that moves back in time what happened in Unity, I can tell you that that thing doesn't exist. However you can implement it yourself. I would recommend you something like this:
If it is a platform 2D game, like Mario Bros style, you can place in
your scene a sequence of trigger that are activated when the player
go through them.
Then you can have a boolean array with a length n equal to the
number of triggers, and then a matrix nx2 ( number of triggers x
coordinates of each trigger [x,y] ).
Initially all the elements in the array has a false value, and
every time a trigger is activated the correcponding element in the
array changes to true.
When the player dies, it checks all elements in the array, until it
reaches the last true element (this would be the last triggered
activated).
With the index form the previous step you access the matrix of
triggers and you extract both elements (x and y coordinate). Then you
use that value in:
Using your script:
Vector2 checkpoint = new Vector2(xCoordinate, yCoordinate);
There is no in built function to reverse time in unity, this would require unity to record all events up until that point.
But given your example, what you could do is create a 'checkpoint' where the scene is set up in a certain way and objects are in specific positions. Like in Mario where you fall down, it plays some music to show you failed then it puts Mario back in a certain position. Just have a function that changes the player position to the checkpoint position. The same applies to any other gameobject you need to reset.
public void Reset()
{
player.position = checkpoint.position;
}

Respawning 2 player objects at the same time in Unity

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.

Spawn Player at Specific location With Unet

I am trying to spawn 2 Players (host and client) at 2 different locations.
I have no idea how to do this because the player are automatically spawned by the network manager.
I have tried the following but failed horribly :(.
[Command]
void CmdSpawn()
{
var go = (GameObject)Instantiate(
gameObject,
transform.position + new Vector3(0,1,0),
Quaternion.identity);
NetworkServer.SpawnWithClientAuthority(go, connectionToClient);
}
How Can I Spawn Player object at a specific location?
NetworkManager already supports spawn positions.
Just add GameObjects where you want players to spawn and give them the NetworkStartPosition component. NetworkManager will automatically detect the start positions and automatically use them according to your setting of "Player Spawn Method" either "Random" (one spawn position is randomly chosen for every player) or "Round Robin" (player #0 spawns at first position, player #1 at second and so forth).
Is there any problems with changing position in a script for player object? For example you could try adding following script on your player object:
void Start () {
if (isServer) // host runs
{
transform.position = new Vector3(0,0,0);
}
else if (isClient) // client runs
{
transform.position = new Vector3(10,0,10);
}
}
i was facing a similar problem, here is the solution in this thread, read til the end.
http://forum.unity3d.com/threads/which-function-to-override.391076/
Make a GameObject and attach a NetworkStartPosition to it. Then, place it somewhere. If you want more than 1 spawn point, you can CTRL+D that object. Then, go to NetworkManager and select Round Robin for spawning first to first, second to second etc. select Random for random spawn points.

Categories