This is the script.. in the starting lines you can see the usage of keycodes. I want to add UI buttons for android. When the user tap on that button it acts as Keycode.A or any Keycode which I want and I don't want to change the script. Any solution ? I am totally beginner I don't understand much of this code so don't want to change it. I got it with the free asset 2D Game Kit in which character ellen moves with pc controls. All I want is to change character controls from pc to ui buttons. Please help if I have to change the script I will get a lot of errors which I can't handle so please help.
using UnityEngine;
using UnityEngine.UIElements;
namespace Gamekit2D
{
public class PlayerInput : InputComponent, IDataPersister
{
public static PlayerInput Instance
{
get { return s_Instance; }
}
protected static PlayerInput s_Instance;
public bool HaveControl { get { return m_HaveControl; } }
public InputButton Pause = new InputButton(KeyCode.Escape, XboxControllerButtons.Menu);
public InputButton Interact = new InputButton(KeyCode.E, XboxControllerButtons.Y);
public InputButton MeleeAttack = new InputButton(KeyCode.K, XboxControllerButtons.X);
public InputButton RangedAttack = new InputButton(KeyCode.O, XboxControllerButtons.B);
public InputButton Jump = new InputButton(KeyCode.Space, XboxControllerButtons.A);
public InputAxis Horizontal = new InputAxis(KeyCode.D, KeyCode.A, XboxControllerAxes.LeftstickHorizontal);
public InputAxis Vertical = new InputAxis(KeyCode.W, KeyCode.S, XboxControllerAxes.LeftstickVertical);
[HideInInspector]
public DataSettings dataSettings;
protected bool m_HaveControl = true;
protected bool m_DebugMenuIsOpen = false;
void Awake ()
{
if (s_Instance == null)
s_Instance = this;
else
throw new UnityException("There cannot be more than one PlayerInput script. The instances are " + s_Instance.name + " and " + name + ".");
}
void OnEnable()
{
if (s_Instance == null)
s_Instance = this;
else if(s_Instance != this)
throw new UnityException("There cannot be more than one PlayerInput script. The instances are " + s_Instance.name + " and " + name + ".");
PersistentDataManager.RegisterPersister(this);
}
void OnDisable()
{
PersistentDataManager.UnregisterPersister(this);
s_Instance = null;
}
protected override void GetInputs(bool fixedUpdateHappened)
{
Pause.Get(fixedUpdateHappened, inputType);
Interact.Get(fixedUpdateHappened, inputType);
MeleeAttack.Get(fixedUpdateHappened, inputType);
RangedAttack.Get(fixedUpdateHappened, inputType);
Jump.Get(fixedUpdateHappened, inputType);
Horizontal.Get(inputType);
Vertical.Get(inputType);
if (Input.GetKeyDown(KeyCode.F12))
{
m_DebugMenuIsOpen = !m_DebugMenuIsOpen;
}
}
public override void GainControl()
{
m_HaveControl = true;
GainControl(Pause);
GainControl(Interact);
GainControl(MeleeAttack);
GainControl(RangedAttack);
GainControl(Jump);
GainControl(Horizontal);
GainControl(Vertical);
}
public override void ReleaseControl(bool resetValues = true)
{
m_HaveControl = false;
ReleaseControl(Pause, resetValues);
ReleaseControl(Interact, resetValues);
ReleaseControl(MeleeAttack, resetValues);
ReleaseControl(RangedAttack, resetValues);
ReleaseControl(Jump, resetValues);
ReleaseControl(Horizontal, resetValues);
ReleaseControl(Vertical, resetValues);
}
public void DisableMeleeAttacking()
{
MeleeAttack.Disable();
}
public void EnableMeleeAttacking()
{
MeleeAttack.Enable();
}
public void DisableRangedAttacking()
{
RangedAttack.Disable();
}
public void EnableRangedAttacking()
{
RangedAttack.Enable();
}
public DataSettings GetDataSettings()
{
return dataSettings;
}
public void SetDataSettings(string dataTag, DataSettings.PersistenceType persistenceType)
{
dataSettings.dataTag = dataTag;
dataSettings.persistenceType = persistenceType;
}
public Data SaveData()
{
return new Data<bool, bool>(MeleeAttack.Enabled, RangedAttack.Enabled);
}
public void LoadData(Data data)
{
Data<bool, bool> playerInputData = (Data<bool, bool>)data;
if (playerInputData.value0)
MeleeAttack.Enable();
else
MeleeAttack.Disable();
if (playerInputData.value1)
RangedAttack.Enable();
else
RangedAttack.Disable();
}
void OnGUI()
{
if (m_DebugMenuIsOpen)
{
const float height = 100;
GUILayout.BeginArea(new Rect(30, Screen.height - height, 200, height));
GUILayout.BeginVertical("box");
GUILayout.Label("Press F12 to close");
bool meleeAttackEnabled = GUILayout.Toggle(MeleeAttack.Enabled, "Enable Melee Attack");
bool rangeAttackEnabled = GUILayout.Toggle(RangedAttack.Enabled, "Enable Range Attack");
if (meleeAttackEnabled != MeleeAttack.Enabled)
{
if (meleeAttackEnabled)
MeleeAttack.Enable();
else
MeleeAttack.Disable();
}
if (rangeAttackEnabled != RangedAttack.Enabled)
{
if (rangeAttackEnabled)
RangedAttack.Enable();
else
RangedAttack.Disable();
}
GUILayout.EndVertical();
GUILayout.EndArea();
}
}
}
}
It's not possible. I rather advice you to directly call the functions you want when the button is pressed.
Related
I'm having this problem using Unity's Advertisment. Specifically after watching the video and clicking the X button to close the video, I should give the prize to the player (go to the next level). The problem is that the OnUnityAdsDidFinish function calls if (showResult == ShowResult.Finished) multiple times. What am I doing wrong? how do I call the FindObjectOfType () .LoadNextLevel () function once; ? Thank you in advance
public class UnityAdsInterstitial : MonoBehaviour, IUnityAdsListener
{
private string gameID = "******";
//nome scelto nella DashBoard di Unity
private string interstitialID = "interstitial";
private string myPlacementId = "rewardedVideo";
public int randomHighValue = 30;
private bool TestMode = true;
private bool adsClosed = false;
public Button _button;
private void Awake()
{
_button = GetComponent<Button>();
}
void Start()
{
Debug.Log("Ads start");
_button = GameObject.Find("StartAds").GetComponent<Button>();
_button.interactable = Advertisement.IsReady(myPlacementId);
if (_button) _button.onClick.AddListener(ShowRewardedVideo);
Advertisement.Initialize(gameID, TestMode);
Advertisement.AddListener(this);
if (adsClosed)
{
adsClosed = false;
}
}
public void ShowInterstitial()
{
if (Advertisement.IsReady(interstitialID) )
{
Advertisement.Show(interstitialID);
}
}
public void ShowRewardedVideo()
{
if (Advertisement.IsReady(myPlacementId))
{
Debug.Log("Rewarded video is Ready");
Advertisement.Show(myPlacementId);
}
else
{
Debug.Log("Rewarded video is not ready at the moment! Please try again later!");
}
}
public void HideBanner()
{
Advertisement.Banner.Hide();
}
public void OnUnityAdsReady(string placementdID)
{
if (placementdID == interstitialID)
{
Debug.Log("InterstitialIsReady");
}
if (placementdID == myPlacementId)
{
Debug.Log("RewardedIsReady");
_button.interactable = true;
}
}
public void OnUnityAdsDidFinish(string placementdID, ShowResult showResult)
{
if (showResult == ShowResult.Finished)
{
// Reward the user for watching the ad to completion.
if (!adsClosed)
{
adsClosed = true;
FindObjectOfType<LevelLoader>().LoadNextLevel();
}
}
else if (showResult == ShowResult.Skipped)
{
// Do not reward the user for skipping the ad.
}
else if (showResult == ShowResult.Failed)
{
Debug.LogWarning("The ad did not finish due to an error.");
}
}
public void OnUnityAdsDidError(string message)
{
Debug.Log("OnUnityAdsDidError");
}
public void OnUnityAdsDidStart(string message)
{
Debug.Log("OnUnityAdsDidStart");
}
I would start my investigation by checking the placement id (in case there are more placements)
Checking that the callback is for the proper placement id
if (showResult == ShowResult.Finished && placementId == myPlacementId)
{
// Reward the user for watching the ad to completion.
if (!adsClosed)
{
adsClosed = true;
FindObjectOfType<LevelLoader>().LoadNextLevel();
}
}
The second would be that I only have one active instance of UnityAdsInterstitial. You can check this in debug mode by the reference of the object. If more than one instance starts from somewhere else in your code, then you should just limit to one.
Guys
I've implemented into my Unity project a plugin which can be downloaded at the link (https://github.com/HoseinPorazar/Android-Native-TTS-plugin-for-Unity-3d).
To use it you need:
1-import AndroidNativeTTS.unitypackage into your project
2-create an empty game object and rename it to tts.
3-attach test script and TextToSpeech script to tts game object.
4-add a button and set the on click event to test.Speak().
5-build project for Android platform.
After implementing the plugin to make it work it's necessary to delete in AndroidManifext.xml the line "android:label=NAtive TTS".
AndroidManifest.xml is stored in the directory "Assets\Plugin\Android\androidtts-release.aar"
When I implemented the plugin which is build to use "UK" and "US" locale, I tried to add Russian locale but unfortunately it failed.
Please see the scripts below (Test.cs and TextToSpeach.cs):
test.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class test : MonoBehaviour {
TextToSpeech tts;
void Start()
{
tts = GetComponent<TextToSpeech>();
}
public void Speak()
{
tts.Speak("hello mr hosein porazar kasin", (string msg) =>
{
tts.ShowToast(msg);
});
}
public void ChangeSpeed()
{
tts.SetSpeed(0.5f);
}
public void ChangeLanguage()
{
tts.SetLanguage(TextToSpeech.Locale.UK);
}
public void ChangePitch()
{
tts.SetPitch(0.6f);
}
}
TextToSpeech.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TextToSpeech :MonoBehaviour
{
void Start()
{
}
public enum Locale
{
UK = 0,
US = 1
}
private AndroidJavaObject TTSExample = null;
private AndroidJavaObject activityContext = null;
private Locale _lang;
public Locale Language { get { return _lang; } set { SetLanguage(value); } }
private float _pitch, _speed;
public float Pitch { get{return _pitch;} set { SetPitch(value); } }
public float Speed { get{return _speed;} set { SetSpeed(value); } }
public delegate void OnErrorCallbackHandler(string error);
private OnErrorCallbackHandler _callback;
public TextToSpeech()
{
//Initialize();
}
public TextToSpeech(Locale language)
{
Initialize();
this.Language = language;
SetLanguage(this.Language);
}
public TextToSpeech(Locale language,float speed,float pitch)
{
Initialize();
this.Language = language;
this.Pitch = pitch;
this.Speed = speed;
SetLanguage(this.Language);
SetSpeed(this.Speed);
SetPitch(this.Pitch);
}
public void Speak(string toSay,OnErrorCallbackHandler callback)
{
if (TTSExample == null)
{
Initialize();
}
this._callback = callback;
TTSExample.Call("TTSMEWithCallBack", toSay, gameObject.name, "OnError");
}
public void OnError(string error)
{
if (_callback != null)
{
if (error.Length > 0)
{
_callback.Invoke(error);
}
}
ShowToast(error);
}
public void Speak(string toSay)
{
if (TTSExample == null)
{
Initialize();
}
TTSExample.Call("TTSME", toSay);
}
public void SetLanguage(Locale lan)
{
this._lang = lan;
string[] Language = new string[] {"UK","US" };
if (TTSExample == null)
{
Initialize();
}
TTSExample.Call("SetLang", Language[(int)lan]);
}
public void SetSpeed(float speed)
{
this._speed = speed;
if (TTSExample == null)
{
Initialize();
}
TTSExample.Set<float>("Speed", speed);
}
public void SetPitch(float pitch)
{
this._pitch = pitch;
if (TTSExample == null)
{
Initialize();
}
TTSExample.Set<float>("Pitch", pitch);
}
private void Initialize()
{
if (TTSExample == null)
{
using (AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
activityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity");
}
using (AndroidJavaClass pluginClass = new AndroidJavaClass("ir.hoseinporazar.androidtts.TTS"))
{
if (pluginClass != null)
{
TTSExample = pluginClass.CallStatic<AndroidJavaObject>("instance");
TTSExample.Call("setContext", activityContext);
}
}
}
}
public void ShowToast(string msg)
{
if (TTSExample == null)
{
using (AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
activityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity");
}
using (AndroidJavaClass pluginClass = new AndroidJavaClass("ir.hoseinporazar.androidtts.TTS"))
{
if (pluginClass != null)
{
TTSExample = pluginClass.CallStatic<AndroidJavaObject>("instance");
TTSExample.Call("setContext", activityContext);
activityContext.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
TTSExample.Call("showMessage", msg);
}));
}
}
}
else
{
activityContext.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
TTSExample.Call("showMessage", msg);
}));
}
}
}
I've tried to format following lines to change the language to Russian but it didn't help me:
public enum Locale
{
RU = 0,
US = 1
}
public void SetLanguage(Locale lan)
{
this._lang = lan;
string[] Language = new string[] {"RU","US" };
if (TTSExample == null)
{
Initialize();
}
TTSExample.Call("SetLang", Language[(int)lan]);
}
I also tried to contatct the developer of the plugin but it seems he was last time on github a couple years ago.
I'd really appreciate it if somebody can help me with the issue.
On the plugin homepage, the author says...
I have included 2 languages (UK,and US) if you want to use other
languages you will have to modify plugin ( with Android Studio).
So it seems you will also need to change switch statement at the bottom of the Java code here:
https://github.com/HoseinPorazar/Android-Native-TTS-plugin-for-Unity-3d/blob/master/NativeAndroidTTS/androidtts/src/main/java/ir/hoseinporazar/androidtts/TTS.java
By adding an "RU" case like this...
public void SetLang(String loc){
switch (loc){
case "UK":
if(t1!=null)
t1.setLanguage(Locale.UK);
break;
case "US":
if(t1!=null)
t1.setLanguage(Locale.US);
break;
case "RU":
if(t1!=null)
t1.setLanguage(Locale.RU);
break;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class GameObjectInfo : MonoBehaviour
{
[System.Serializable]
public class GameObjectstInfo
{
public GameObject parent;
public int childrenCount;
public List<Transform> children = new List<Transform>();
}
public string gameObjectsInfo = "";
public string results = "";
public bool addChildren = false;
public GameObjectstInfo[] objectsInfo;
private string previousGameObjectsInfo = "";
// Start is called before the first frame update
void Start()
{
Search();
}
private void Update()
{
if (gameObjectsInfo != "" && gameObjectsInfo != previousGameObjectsInfo)
{
Search();
}
previousGameObjectsInfo = gameObjectsInfo;
Reset();
}
public void Search()
{
if (gameObjectsInfo != "")
{
var foundObjects = FindGameObjectsWithName(gameObjectsInfo);
objectsInfo = new GameObjectstInfo[foundObjects.Length];
if (foundObjects.Length > 0)
{
results = "Found Results";
for (int i = 0; i < foundObjects.Length; i++)
{
objectsInfo[i] = new GameObjectstInfo();
objectsInfo[i].parent = foundObjects[i];
if (addChildren == true)
{
foreach (Transform t in foundObjects[i].GetComponentsInChildren<Transform>(true))
{
objectsInfo[i].childrenCount += 1;
objectsInfo[i].children.Add(t);
}
}
else
{
}
}
}
else
{
results = "No Results";
}
}
}
private void Reset()
{
if (gameObjectsInfo == "")
{
results = "No Results";
objectsInfo = new GameObjectstInfo[0];
}
}
GameObject[] FindGameObjectsWithName(string nameIt)
{
int it = 0;
GameObject[] objArr;
bool b = false;
while (!b)
{
if (GameObject.Find(nameIt))
{
GameObject.Find(nameIt).name = nameIt + it;
it++;
}
else
{
b = true;
}
}
objArr = new GameObject[it];
while (it > 0)
{
it--;
objArr[it] = GameObject.Find(nameIt + it);
objArr[it].name = nameIt;
}
return objArr;
}
}
This is the part where I'm adding or not the children:
if (addChildren == true)
{
foreach (Transform t in foundObjects[i].GetComponentsInChildren<Transform>(true))
{
objectsInfo[i].childrenCount += 1;
objectsInfo[i].children.Add(t);
}
}
else
{
}
But I want to do it also in the Update if the flag addChildren is true and changed to false or false to true make the change and add/remove the children in real time.
Now I need to delete the text in the variable gameObjectsInfo and re type again to make the children changes. But I want that the effect will happen without typing over again. Only when changing the state of the flag addChildren.
If I'm changing the addChildren state re search again with or without the children.
There are ways you can do this by writing your own editor for the class so it'll respond to clicking on the checkbox for that bool, if you are only setting the value of addChildren through code, you can use a property set function, or, the most straight-forward way (if you don't mind waiting until the next frame after changing the value) is to just have an extra bool tracking the previous value:
private bool _lastAddChildren;
public bool addChildren = false;
...
void Start()
{
_lastAddChildren = addChildren;
...
}
private void Update()
{
if ((gameObjectsInfo != "" && gameObjectsInfo != previousGameObjectsInfo)
|| (_lastAddChildren != addChildren))
{
Search();
}
previousGameObjectsInfo = gameObjectsInfo;
_lastAddChildren = addChildren;
Reset();
}
Im using google play services cloud save. I found a tutorial about how to save, but for one thing like just for highscore. I want to save multiple playerprefs, for example I have 3 ability and every one of it is saving in a playerpref so I want to save them in to the cloud and I have gold to buy these abilitys and you can buy the gold with IAP so I want to save gold too in cloud but I have no idea how to save multiple playerprefs can you help me.
My playerprefs is like this
PlayerPrefs.SetInt("Revive", revive);
PlayerPrefs.SetInt("SlowTime", slowTime);
PlayerPrefs.SetInt("Immortal", immortal);
Im changing and saving the gold after IAP purchase
PlayerPrefs.SetInt("Gold", PlayerPrefs.GetInt("Gold") + 250);
This is the Cloud Save Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GooglePlayGames;
using UnityEngine.SocialPlatforms;
using GooglePlayGames.BasicApi;
using GooglePlayGames.BasicApi.SavedGame;
using System.Text;
using System;
public class PlayGamesController : MonoBehaviour
{
public static PlayGamesController Instance { set; get; }
const string Save_Name = "Save";
bool isSaving;
bool isCloudDataLoaded = false;
private void Start()
{
if (Instance == null)
{
DontDestroyOnLoad(gameObject);
Instance = this;
}
else
{
Destroy(gameObject);
}
if (!PlayerPrefs.HasKey(Save_Name))
PlayerPrefs.SetString(Save_Name, "0");
if (!PlayerPrefs.HasKey("IsFirstTime"))
PlayerPrefs.SetInt("IsFirstTime", 1);
LoadLocal();
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder().EnableSavedGames().Build();
PlayGamesPlatform.InitializeInstance(config);
PlayGamesPlatform.Activate();
SignIn();
}
private void SignIn()
{
Social.localUser.Authenticate((success) => {
LoadData();
});
}
public void AddScoreToLeaderboard(string leaderboardId, long score)
{
Social.ReportScore(score, leaderboardId, (bool success) => { });
}
public void OnAchievementClick()
{
if (Social.localUser.authenticated)
{
Social.ShowAchievementsUI();
}
if (!Social.localUser.authenticated)
{
SignIn();
}
}
public void OnLeaderboardClick()
{
if (Social.localUser.authenticated)
{
Social.ShowLeaderboardUI();
}
if (!Social.localUser.authenticated)
{
SignIn();
}
}
#region Saved Games
string GameDataToString()
{
return CloudVariables.highScore.ToString();
}
void StringToGameData(string cloudData, string localData)
{
if(PlayerPrefs.GetInt("IsFirstTime") == 1)
{
PlayerPrefs.SetInt("IsFirstTime", 0);
if (int.Parse(cloudData) > int.Parse(localData))
{
PlayerPrefs.SetString(Save_Name, cloudData);
}
}
else
{
if(int.Parse(localData) > int.Parse(cloudData))
{
CloudVariables.highScore = int.Parse(localData);
AddScoreToLeaderboard(GPGSIds.leaderboard_high_score, CloudVariables.highScore);
isCloudDataLoaded = true;
SaveData();
return;
}
}
CloudVariables.highScore = int.Parse(cloudData);
isCloudDataLoaded = true;
}
void StringToGameData(string localData)
{
CloudVariables.highScore = int.Parse(localData);
}
public void LoadData()
{
if (Social.localUser.authenticated)
{
isSaving = false;
((PlayGamesPlatform)Social.Active).SavedGame.OpenWithManualConflictResolution(Save_Name, DataSource.ReadCacheOrNetwork, true, ResolveConflict, OnSavedGameOpened);
}
else
{
LoadLocal();
}
}
private void LoadLocal()
{
StringToGameData(PlayerPrefs.GetString(Save_Name));
}
public void SaveData()
{
if (!isCloudDataLoaded)
{
SaveLocal();
return;
}
if (Social.localUser.authenticated)
{
isSaving = true;
((PlayGamesPlatform)Social.Active).SavedGame.OpenWithManualConflictResolution(Save_Name, DataSource.ReadCacheOrNetwork, true, ResolveConflict, OnSavedGameOpened);
}
else
{
SaveLocal();
}
}
private void SaveLocal()
{
PlayerPrefs.SetString(Save_Name, GameDataToString());
}
private void ResolveConflict(IConflictResolver resolver, ISavedGameMetadata original, byte[] originalData, ISavedGameMetadata unmerged, byte[] unmergedData)
{
if (originalData == null)
resolver.ChooseMetadata(unmerged);
else if (unmergedData == null)
resolver.ChooseMetadata(original);
else
{
string originalStr = Encoding.ASCII.GetString(originalData);
string unmergedStr = Encoding.ASCII.GetString(unmergedData);
int originalNum = int.Parse(originalStr);
int unmergedNum = int.Parse(unmergedStr);
if(originalNum > unmergedNum)
{
resolver.ChooseMetadata(original);
return;
}
else if (unmergedNum > originalNum)
{
resolver.ChooseMetadata(unmerged);
return;
}
resolver.ChooseMetadata(original);
}
}
private void OnSavedGameOpened(SavedGameRequestStatus status, ISavedGameMetadata game)
{
if(status == SavedGameRequestStatus.Success)
{
if (!isSaving)
LoadGame(game);
else
SaveGame(game);
}
else
{
if (!isSaving)
LoadLocal();
else
SaveLocal();
}
}
private void LoadGame(ISavedGameMetadata game)
{
((PlayGamesPlatform)Social.Active).SavedGame.ReadBinaryData(game, OnSavedGameDataRead);
}
private void SaveGame(ISavedGameMetadata game)
{
string stringToSave = GameDataToString();
PlayerPrefs.SetString(Save_Name, stringToSave);
byte[] dataToSave = Encoding.ASCII.GetBytes(stringToSave);
SavedGameMetadataUpdate update = new SavedGameMetadataUpdate.Builder().Build();
((PlayGamesPlatform)Social.Active).SavedGame.CommitUpdate(game, update, dataToSave, OnSavedGameDataWritten);
}
private void OnSavedGameDataRead(SavedGameRequestStatus status, byte[] savedData)
{
if(status == SavedGameRequestStatus.Success)
{
string cloudDataString;
if (savedData.Length == 0)
cloudDataString = "0";
else
cloudDataString = Encoding.ASCII.GetString(savedData);
string localDataString = PlayerPrefs.GetString(Save_Name);
StringToGameData(cloudDataString, localDataString);
}
}
private void OnSavedGameDataWritten(SavedGameRequestStatus status, ISavedGameMetadata game)
{
}
#endregion /Saved Games
}
I have a problem here with Photon's PUN 2. Sometimes It works, but other times it doesn't. Since the last 2 weeks it isn't working that fine. Before it were better, I joined to the master, and then, to the lobby and It allowed me to list the rooms and join them without any problem. Now, I haven't changed that code that much, I only changed it after the errors started. Now, sometimes it joins a match, but another it doesn't, showing the following error:
JoinRandomRoom failed. Client is not on Master Server or not yet ready to call operations. Wait for callback: OnJoinedLobby or OnConnectedToMaster.
I only have 2 devices to test my online with PUN, but, even if I created a room is not working anymore, it just seems like works randomly. Here's my code if you want to check it:
void Start()
{
PhotonNetwork.ConnectUsingSettings();
}
// Update is called once per frame
void Update()
{
}
public override void OnJoinedLobby()
{
// /* print("Connected to lobby")*/;
}
public override void OnConnectedToMaster()
{
//This shows a popup to let know the player that is connected
//PhotonNetwork.JoinLobby();
base.OnJoinedLobby();
GameObject.Find("IWifi").SetActive(false);
print("Puga");
StatePScript.IsShow = true;
Connected = true;
GameObject.Find("IOk").GetComponent<Image>().color = Color.white;
print("IOKS Value is " + IOKS.Show);
GameObject.Find("StatusText").GetComponent<Text>().text = "Connected!";
GameObject.Find("StatusText").GetComponent<Text>().color = Color.green;
A.Play();
GameObject.Find("StatePanel").GetComponent<Animator>().SetBool("Show", false);
IOKS.Show = false;
GameObject.Find("IOk").GetComponent<Image>().color = new Color(0, 0, 0, 0);
Connected = false;
StatePScript.IsShow = false;
}
I have other photon scripts like this that is the random room code:
using UnityEngine.UI;
using Photon.Pun;
public class RandomBScript : MonoBehaviourPunCallbacks
{
// Use this for initialization
private Button B;
void Start ()
{
B = GetComponent<Button>();
B.onClick.AddListener(Clicker);
}
void Clicker()
{
PhotonNetwork.JoinRandomRoom();
print("Random");
}
public override void OnJoinRandomFailed(short returnCode, string message)
{
base.OnJoinRandomFailed(returnCode, message);
print(message);
}
}
The create room code:
using Photon.Pun;
using Photon.Realtime;
public class CreateRoomS : MonoBehaviourPunCallbacks
{
// Use this for initialization
private Button B;
private InputField IF;
private InputField PlayerField;
public AudioSource A;
void Start ()
{
B = GetComponent<Button>();
PlayerField = GameObject.Find("PlayerInput").GetComponent<InputField>();
IF = GameObject.Find("NameInput").GetComponent<InputField>();
B.onClick.AddListener(Clicker);
}
private void Awake()
{
}
void Clicker()
{
print("Trying To create a room...");
if (IF.text.Length > 0 && IF.text.Length <= 20)
{
int PlayerAmount = Int32.Parse(PlayerField.text);
RoomOptions roompos = new RoomOptions()
{
IsVisible = true, IsOpen = true, MaxPlayers = (byte)PlayerAmount
};
PhotonNetwork.CreateRoom(IF.text, roompos);
print("RoomCreated!");
}
else
{
A.Play();
}
}
public override void OnJoinedRoom()
{
print("We are in a room");
PhotonNetwork.LoadLevel("WaitScene");
}
public override void OnCreateRoomFailed(short returnCode, string message)
{
base.OnCreateRoomFailed(returnCode, message);
}
public override void OnCreatedRoom()
{
base.OnCreatedRoom();
print("We created the room");
}
// Update is called once per frame
public override void OnConnectedToMaster()
{
base.OnConnectedToMaster();
print("Connected to the master");
}
And finally, the list rooms code:
using Photon.Pun;
using Photon.Realtime;
using System.Reflection;
using System;
public class RooManager : MonoBehaviourPunCallbacks
{
// Use this for initialization
public GameObject roomPrefab;
public Sprite Four, Two, Three;
private string RoomName;
private int PlayerAmount;
private int MaxPlayers;
private Image I;
private Vector2 RoomVector;
private bool Lock = false;
public GameObject Content;
private List<RoomInfo> RoomList;
private bool IsntNull = false;
private Dictionary<string, RoomInfo> cachedRoomList;
private Dictionary<string, GameObject> roomListEntries;
private void Awake()
{
GameObject.Find("StatePanel").GetComponent<Animator>().SetBool("Show", true);
cachedRoomList = new Dictionary<string, RoomInfo>();
roomListEntries = new Dictionary<string, GameObject>();
}
void Start ()
{
Content = GameObject.Find("Content").GetComponent<GameObject>();
RoomVector = new Vector2(370, this.transform.position.y);
}
void Rooming()
{
PhotonNetwork.JoinLobby();
}
private void ClearRoomListView()
{
foreach (GameObject entry in roomListEntries.Values)
{
Destroy(entry.gameObject);
}
roomListEntries.Clear();
}
private void UpdateRoomListView()
{
foreach (RoomInfo Item in cachedRoomList.Values)
{
RoomName = Item.Name;
PlayerAmount = Item.PlayerCount;
MaxPlayers = Item.MaxPlayers;
RoomVector.y -= 100;
GameObject RoomPrefab = Instantiate(roomPrefab, RoomVector, transform.rotation) as GameObject;
if (Item.PlayerCount == 0)
{
Destroy(RoomPrefab);
}
print(PhotonNetwork.CurrentLobby.Name);
RoomPrefab.transform.Find("RoomName").GetComponent<Text>().text = RoomName;
RoomPrefab.transform.Find("PlayerInt").GetComponent<Text>().text = PlayerAmount.ToString();
if (Item.PlayerCount == 0)
{
}
if (Item.MaxPlayers == 4)
{
GameObject.Find("IPlayerA").GetComponent<Image>().sprite = Four;
}
else if (Item.MaxPlayers == 2)
{
GameObject.Find("IPlayerA").GetComponent<Image>().sprite = Two;
}
else if (Item.MaxPlayers == 3)
{
GameObject.Find("IPlayerA").GetComponent<Image>().sprite = Three;
}
RoomPrefab.transform.SetParent(Content.transform);
}
}
public override void OnRoomListUpdate(List<RoomInfo> roomList)
{
ClearRoomListView();
UpdateCachedRoomList(roomList);
UpdateRoomListView();
print("Updated");
}
private void UpdateCachedRoomList(List<RoomInfo> roomList)
{
foreach (RoomInfo info in roomList)
{
// Remove room from cached room list if it got closed, became invisible or was marked as removed
if (!info.IsOpen || !info.IsVisible || info.RemovedFromList)
{
if (cachedRoomList.ContainsKey(info.Name))
{
cachedRoomList.Remove(info.Name);
}
continue;
}
// Update cached room info
if (cachedRoomList.ContainsKey(info.Name))
{
cachedRoomList[info.Name] = info;
}
// Add new room info to cache
else
{
cachedRoomList.Add(info.Name, info);
}
}
}
This script instantiates a button for every room in photon's server. If you click one button, you join that room. As I said, sometimes it work and sometimes it doesn't, sometimes it helped to comment the line PhotonNetwork.JoinLobby(), but that means that you wont see the romos. Actually, even with or without the JoinLobby() line, it isn't working that well.