I´m new to Networking and can´t find the problem on my self.
I made a matchmaking system for my game and it worked well.
But after some changes in my Game it stopped working.
It should create a room if no room is there. Else join a random room.
But it always creates a new room. no errors etc.
here are the scripts that should do the work.
Edit:
broke it down to this script:
using Photon.Pun;
using Photon.Realtime;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PhotonLobby2 : MonoBehaviourPunCallbacks
{
public static PhotonLobby2 lobby;
public GameObject battlebutton;
private void Awake()
{
lobby = this; // create singleton
}
void Start()
{
PhotonNetwork.ConnectUsingSettings();
}
public override void OnConnectedToMaster()
{
Debug.Log("connected to masterserver");
PhotonNetwork.AutomaticallySyncScene = true;
battlebutton.SetActive(true);
}
public void OnBattleButtonClicked()
{
PhotonNetwork.JoinRandomRoom();
}
public override void OnJoinRandomFailed(short returnCode, string message)
{
Debug.Log(message + returnCode);
Debug.Log(" failed to join random game");
CreateRoom();
}
void CreateRoom()
{
PhotonNetwork.CreateRoom("Room");
}
public override void OnCreatedRoom()
{
Debug.Log("Created Room");
base.OnCreatedRoom();
}
public override void OnPlayerEnteredRoom(Player newPlayer)
{
Debug.Log("Entered");
base.OnPlayerEnteredRoom(newPlayer);
}
}
Debug says: No match found32760
It is because the two players join matches in different regions... you can force this in the photon server settings Fill in Dev region and Fixed region with one particular server region that has better ping for you. Make the property Use sure name serve is also checked
I resolved this issue by checking the room properties which first player creates.
There is a variable of Room named "IsOpen". If it is false then second player cannot join the same room. I just set it to true and now its perfectly joining the same room.
Related
When entering the server, the player calls the RPC function that increases the number of players, it works correctly. Another RPC function is responsible for the player's death, but it changes the variable only for one client, the value does not change for the rest.
the script in which the function does not work
using Photon.Pun;
using UnityEngine;
public class PigLifeScript : MonoBehaviour
{
PhotonView view;
private void Start()
{
view = GetComponent<PhotonView>();
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.tag == "WolfPlayer")
{
view.RPC("RemovePlayer", RpcTarget.AllViaServer);
}
}
}
Functions
private int AlivePigs;
public Text AlivePigsTXT;
[PunRPC]
public void AddPlayer()
{
AlivePigs++;
}
[PunRPC]
public void RemovePlayer()
{
AlivePigs--;
}
I tried to call RPC from a separate function, tried to make conditions in the Update method, tried to pass the value to the master client,
So I have a 2D platformer parkour game which holds a timer when player starts level. I have 5 levels and at the end of each level, I want to keep the last time value and display them at the end of the game.
So far, I tried to hold the last time value when player triggers the End portal and store them in an array in the code below. Here are the scripts:
Time Data Manager Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class timeDataManager : MonoBehaviour
{
public string[] timeDataArr;
void Start(){
}
void Update(){
Debug.Log(timeDataArr[SceneManager.GetActiveScene().buildIndex-1]);
}
public void AddTimeData(string timeData, int levelBuildIndex){
timeDataArr[levelBuildIndex-1] = timeData.ToString();
}
}
End Portal Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class EndPortal : MonoBehaviour
{
public AudioSource aSrc;
private int sceneNumber;
public GameObject bgAudio;
public Text scoreText;
string textData;
public timeDataManager tDManager;
void Start(){
sceneNumber = SceneManager.GetActiveScene().buildIndex;
tDManager = GameObject.FindGameObjectWithTag("TimeDataManager").GetComponent<timeDataManager>();
}
void OnTriggerEnter2D(Collider2D col){
if (col.gameObject.tag == "Player"){
aSrc.Play();
Destroy(bgAudio);
textData = scoreText.text;
Debug.Log(textData);
Debug.Log(sceneNumber);
tDManager.AddTimeData(textData,sceneNumber);
SceneManager.LoadScene(sceneBuildIndex:sceneNumber+1);
}
}
}
As I said before, I tried to keep all timer values at the end of each level and store them in an array in my timeDataManager script. But it's not working.
Any ideas on how to fix? Or do you have any other ideas? Thanks a lot for your time.
Issylin's answer is a better solution for your needs but i want to mention couple of things about your code.
One thing about your timeDataArr. If you don't touch it in inspector, you need to initialize it first. So let's say, if you want to hold 5 levels of time data, you need to do something like;
public string[] timeDataArr = new string[5];
or
public class timeDataManager : MonoBehaviour
{
public string[] timeDataArr;
public int sceneAmount_TO_HoldTimeData = 5;
void Start()
{
timeDataArr = new string[sceneAmount_TO_HoldTimeData];
}
}
or
public class timeDataManager : MonoBehaviour
{
public string[] timeDataArr;
public int sceneAmount_NOT_ToHoldTimeData = 1;
void Start()
{
timeDataArr = new string[SceneManager.sceneCountInBuildSettings - sceneAmount_NOT_ToHoldTimeData];
}
}
Another thing is you need to be careful about levelBuildIndex-1. If you call that in first scene,
SceneManager.GetActiveScene().buildIndex
will be 0 and levelBuildIndex-1 will be -1 or in Debug part it will be timeDataArr[-1] but array indexes must start with 0. So it will throw an error.
One more thing, this is not an error or problem. Instead of this part
tDManager = GameObject.FindGameObjectWithTag("TimeDataManager").GetComponent<timeDataManager>();
you can do
tDManager = FindObjectOfType<timeDataManager>();
There are several way to achieve what you're trying to do.
The easier would be to use a static class for such a simple data like the one you're carrying through your game.
using System.Collections.Generic;
public class Time_Data
{
/// TODO
/// Add the members
/// e.g. your time format as string or whatever,
/// the scene index, etc
}
public static class Time_Manager
{
private static List<Time_Data> _times;
public static void Add_Time(in Time_Data new_time)
{
_times.Add(new_time);
}
public static List<Time_Data> Get_Times()
{
return _times;
}
public static void Clear_Data()
{
_times.Clear();
}
}
Use it like any other static methods within your OnTriggerEnter2D call.
Time_Manager.Add( /* your new data here */ );
The other way, if you intend to stay with a game object within your scenes, would be to use the DontDestroyOnLoad method from Unity so your game object which has your script timeDataManager would remain.
Note that in your code, using string[] might be unsafe. For your use of it, consider using a List<string>.
I'm trying to synchronize text in a unit between players, but I'm getting an error.
I just need to sync the text
[1]: https://i.stack.imgur.com/0l98U.png
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Photon.Pun;
using UnityEngine.UIElements;
public class Sync : MonoBehaviourPunCallbacks
{
private PhotonView view;
public Text textGame;
public Text copied;
void Start()
{
view = GetComponent<PhotonView>();
}
public void sync()
{
if(view.IsMine)
view.RPC("ViewAll", RpcTarget.AllBuffered, textGame.text);
}
[PunRPC]
public void ViewAll(string tG)
{
tG = copied.text;
Debug.Log(tG);
}
}```
пппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппппп
The error is telling you that the "view" variable has not been assigned and is therefore null.
To assign it you can make that field public, and in the inspector you
assign the photonView you want, I guess that of the player.
Alternatively you can assign "view" not from the inspector but in a
Start() or Awake() method. If the photonView you want to associate is
on the same GameObject as the script, you can write like this:
void Awake()
{
view = GetComponent();
}
However, the easiest answer is to replace "view" with "photonView".
It will have the same result as the solutions described above, but it will be very simple.
enter code here
public void sync()
{
if(photonView.IsMine)
view.RPC("ViewAll", RpcTarget.AllBuffered, textGame.text);
}
I have not directly given you the simple slogan to make you fully understand the problem and to help you solve it.
public class GameControl : NetworkBehaviour {
public GameObject localPlayer;
[TargetRpc]
public void TargetGetLocalPlayer(NetworkConnection conn)
{
localPlayer = GameObject.Find("Local");
}
public override void OnStartServer()
{
base.OnStartServer();
TargetGetLocalPlayer(connectionToClient);
}
}
i have a script attached to a server object which should be able to grab the local player GameObject (which i denoted by changing it's name to 'Local' once it's spawned in another script) from the client but when i try to call TargetGetLocalPlayer , i get the following error :
Exception in OnStartServer:Object reference not set to an instance of an object at
UnityEngine.Networking.NetworkBehaviour.SendTargetRPCInternal
(UnityEngine.Networking.NetworkConnection conn, UnityEngine.Networking.NetworkWriter writer,
System.Int32 channelId, System.String rpcName) [0x0002e]
i am totally new to networking in unity and i feel like i should have gone with photon instead of unet , it seems like no one is interested in unet anymore and the docs suck at explaining anything and i will be very grateful if anyone could answer me , thanks in advance
I think a better solution would be to attach a script to each player. and make it so that when a "new" player joins it runs a method in your GameControl to add the player to a player list. like this:
//this is on your gameControl.
public List<Player> players;
public void AddPlayer(Player player)
{
players.Add(player);
}
this is working if you have your GameControl as a singleton. if you do not know how to do that check the last piece of code.
//this is on your Player script called player(if you have another name change all
//Player scripts in here to that name
public void Start()
{
GameControl.AddPlayer(this);
}
Or
Instead of making the players list a List you can make it a dictionary and make a key for each player who joins to make it more accesible.
How to make a script a singleton and why.
why:
if you have a manager class/script you always want there to only be ONE instance of it so you can call its methods easily and without problems.
How:
Basically you make it so that Only THIS script can change values and variables in the manager, and other scripts can get/call methods and functions. this makes it easily accesible and you will have less problems.
private static GameControl _GameControl;
private Player player;
public static GameControl gameControl
{
get
{
if(_GameControl == null)
{
Debug.LogError("Game Control is null");
}
return _GameControl;
}
}
void Awake()
{
_GameControl = this;
player = GameObject.Find("Player").GetComponent<Player>();
}
Well i see what you mean, well create a method that can be run by any script like a singleton. then you pass in the gameobject that you want to add like this:
public class GameManager
{
public GameObject _player;
//this is a singleton.
private static GameManager _gm;
public static GameManager gameManager
{
get
{
if(_gm == null)
{
Debug.LogError("Game manager is null");
}
return _gm;
}
}
void awake()
{
_gm = this;
}
void GetPlayer(GameObject player)
{
_player = player;
}
void AddPlayer(GameObject player)
{
//add it to whatever you want to.
}
}
call the method this way:
public class Player : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
GameManager.gameManager.GetPlayer(this.gameObject);
}
}
I am relatively new to Unity and am currently trying to build an multi-user app on Hololens. Currently, I am just trying to get two Hololens to connect over LAN using Unet. When I use one of my Hololens to host the server, my laptop can connect to it during play mode in the Unity editor. However, when I try to use my other Hololens to connect to it, it does not work and I am not sure why. Does anyone else have this problem? And if so, how do you fix it?
Thanks in advance.
Edit: some code
Here's the code for network manager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System;
public class NetworkManager_Custom : NetworkManager
{
public void StartupHost()
{
setPort();
NetworkManager.singleton.StartHost();
}
public void JoinGame()
{
SetIpAddress();
setPort();
NetworkManager.singleton.StartClient();
}
private void SetIpAddress()
{
string Address = "192.168.2.80";
NetworkManager.singleton.networkAddress = Address;
}
private void setPort()
{
NetworkManager.singleton.networkPort = 9001;
}
}
Here's the code for the start-server button
using HoloToolkit.Unity.InputModule;
using UnityEngine;
using UnityEngine.Networking;
public class ok : NetworkBehaviour, IFocusable, IInputClickHandler
{
bool hasFocus;
public NetworkManager_Custom manager;
public void OnFocusEnter()
{
hasFocus = true;
}
public void OnFocusExit()
{
hasFocus = false;
}
public void OnInputClicked(InputClickedEventData eventData)
{
manager.StartupHost();
}
}
Here's the code for joining server as client
using HoloToolkit.Unity.InputModule;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Networking.NetworkSystem;
public class aegf : NetworkBehaviour, IFocusable, IInputClickHandler
{
bool hasFocus;
public NetworkManager_Custom manager;
public void OnFocusEnter()
{
hasFocus = true;
}
public void OnFocusExit()
{
hasFocus = false;
}
public void OnInputClicked(InputClickedEventData eventData)
{
manager.JoinGame();
}
}
It's worth double-checking the capabilties that you've set. Ensure all three of these are selected:
InternetClient
InternetClientServer
PrivateNetworkClientServer
Ref: https://learn.microsoft.com/en-us/uwp/schemas/appxpackage/appxmanifestschema/element-capability