Prevent Empty Game Room in Unity Network Lobby from Destroying - c#

Software: Unity 2018.1
Language: C# 4
Plugin: Network Lobby
Problem/Question:
I have my Unity Network Lobby setup and working. I'm trying to prevent the Game Room from Destroying when all players leave the room or disconnect so that it can always be returned to at a later time.
Attempts:
I tried changing int i = 0 to into i = -1 (Didn't work, no affect)
I tried changing if (p != null) to if (p == null) (Didn't work, no affect)
I tried silencing the code as well with 'Command, /'. (Didn't work, no affect)
Here's the Code:
public override void OnLobbyServerPlayerRemoved(NetworkConnection conn, short playerControllerId)
{
for (int i = 0; i < lobbySlots.Length; ++i)
{
LobbyPlayer p = lobbySlots[i] as LobbyPlayer;
if (p != null)
{
p.RpcUpdateRemoveButton();
p.ToggleJoinButton(numPlayers + 1 >= minPlayers);
}
}
}
public override void OnLobbyServerDisconnect(NetworkConnection conn)
{
for (int i = 0; i < lobbySlots.Length; ++i)
{
LobbyPlayer p = lobbySlots[i] as LobbyPlayer;
if (p != null)
{
p.RpcUpdateRemoveButton();
p.ToggleJoinButton(numPlayers >= minPlayers);
}
}
}
Complete Code:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using UnityEngine.Networking;
using UnityEngine.Networking.Types;
using UnityEngine.Networking.Match;
using System.Collections;
namespace Prototype.NetworkLobby
{
public class LobbyManager : NetworkLobbyManager
{
static short MsgKicked = MsgType.Highest + 1;
static public LobbyManager s_Singleton;
[Header("Unity UI Lobby")]
[Tooltip("Time in second between all players ready & match start")]
public float prematchCountdown = 5.0f;
[Space]
[Header("UI Reference")]
public LobbyTopPanel topPanel;
public RectTransform mainMenuPanel;
public RectTransform lobbyPanel;
public LobbyInfoPanel infoPanel;
public LobbyCountdownPanel countdownPanel;
public GameObject addPlayerButton;
protected RectTransform currentPanel;
public Button backButton;
public Text statusInfo;
public Text hostInfo;
//Client numPlayers from NetworkManager is always 0, so we count
(throught connect/destroy in LobbyPlayer) the number
//of players, so that even client know how many player there is.
[HideInInspector]
public int _playerNumber = 0;
//used to disconnect a client properly when exiting the matchmaker
[HideInInspector]
public bool _isMatchmaking = false;
protected bool _disconnectServer = false;
protected ulong _currentMatchID;
protected LobbyHook _lobbyHooks;
void Start()
{
s_Singleton = this;
_lobbyHooks = GetComponent<Prototype.NetworkLobby.LobbyHook>();
currentPanel = mainMenuPanel;
backButton.gameObject.SetActive(false);
GetComponent<Canvas>().enabled = true;
DontDestroyOnLoad(gameObject);
SetServerInfo("Offline", "None");
}
public override void OnLobbyClientSceneChanged(NetworkConnection conn)
{
if (SceneManager.GetSceneAt(0).name == lobbyScene)
{
if (topPanel.isInGame)
{
ChangeTo(lobbyPanel);
if (_isMatchmaking)
{
if (conn.playerControllers[0].unetView.isServer)
{
backDelegate = StopHostClbk;
}
else
{
backDelegate = StopClientClbk;
}
}
else
{
if (conn.playerControllers[0].unetView.isClient)
{
backDelegate = StopHostClbk;
}
else
{
backDelegate = StopClientClbk;
}
}
}
else
{
ChangeTo(mainMenuPanel);
}
topPanel.ToggleVisibility(true);
topPanel.isInGame = false;
}
else
{
ChangeTo(null);
Destroy(GameObject.Find("MainMenuUI(Clone)"));
//backDelegate = StopGameClbk;
topPanel.isInGame = true;
topPanel.ToggleVisibility(false);
}
}
public void ChangeTo(RectTransform newPanel)
{
if (currentPanel != null)
{
currentPanel.gameObject.SetActive(false);
}
if (newPanel != null)
{
newPanel.gameObject.SetActive(true);
}
currentPanel = newPanel;
if (currentPanel != mainMenuPanel)
{
backButton.gameObject.SetActive(true);
}
else
{
backButton.gameObject.SetActive(false);
SetServerInfo("Offline", "None");
_isMatchmaking = false;
}
}
public void DisplayIsConnecting()
{
var _this = this;
infoPanel.Display("Connecting...", "Cancel", () => { _this.backDelegate(); });
}
public void SetServerInfo(string status, string host)
{
statusInfo.text = status;
hostInfo.text = host;
}
public delegate void BackButtonDelegate();
public BackButtonDelegate backDelegate;
public void GoBackButton()
{
backDelegate();
topPanel.isInGame = false;
}
// ----------------- Server management
public void AddLocalPlayer()
{
TryToAddPlayer();
}
public void RemovePlayer(LobbyPlayer player)
{
player.RemovePlayer();
}
public void SimpleBackClbk()
{
ChangeTo(mainMenuPanel);
}
public void StopHostClbk()
{
if (_isMatchmaking)
{
matchMaker.DestroyMatch((NetworkID)_currentMatchID, 0, OnDestroyMatch);
_disconnectServer = true;
}
else
{
StopHost();
}
ChangeTo(mainMenuPanel);
}
public void StopClientClbk()
{
StopClient();
if (_isMatchmaking)
{
StopMatchMaker();
}
ChangeTo(mainMenuPanel);
}
public void StopServerClbk()
{
StopServer();
ChangeTo(mainMenuPanel);
}
class KickMsg : MessageBase { }
public void KickPlayer(NetworkConnection conn)
{
conn.Send(MsgKicked, new KickMsg());
}
public void KickedMessageHandler(NetworkMessage netMsg)
{
infoPanel.Display("Kicked by Server", "Close", null);
netMsg.conn.Disconnect();
}
//===================
public override void OnStartHost()
{
base.OnStartHost();
ChangeTo(lobbyPanel);
backDelegate = StopHostClbk;
SetServerInfo("Hosting", networkAddress);
}
public override void OnMatchCreate(bool success, string extendedInfo, MatchInfo matchInfo)
{
base.OnMatchCreate(success, extendedInfo, matchInfo);
_currentMatchID = (System.UInt64)matchInfo.networkId;
}
public override void OnDestroyMatch(bool success, string extendedInfo)
{
base.OnDestroyMatch(success, extendedInfo);
if (_disconnectServer)
{
StopMatchMaker();
StopHost();
}
}
//allow to handle the (+) button to add/remove player
public void OnPlayersNumberModified(int count)
{
_playerNumber += count;
int localPlayerCount = 0;
foreach (PlayerController p in ClientScene.localPlayers)
localPlayerCount += (p == null || p.playerControllerId == -1) ? 0 : 1;
addPlayerButton.SetActive(localPlayerCount < maxPlayersPerConnection && _playerNumber < maxPlayers);
}
// ----------------- Server callbacks ------------------
//we want to disable the button JOIN if we don't have enough player
//But OnLobbyClientConnect isn't called on hosting player. So we override the lobbyPlayer creation
public override GameObject OnLobbyServerCreateLobbyPlayer(NetworkConnection conn, short playerControllerId)
{
GameObject obj = Instantiate(lobbyPlayerPrefab.gameObject) as GameObject;
LobbyPlayer newPlayer = obj.GetComponent<LobbyPlayer>();
newPlayer.ToggleJoinButton(numPlayers + 1 >= minPlayers);
for (int i = 0; i < lobbySlots.Length; ++i)
{
LobbyPlayer p = lobbySlots[i] as LobbyPlayer;
if (p != null)
{
p.RpcUpdateRemoveButton();
p.ToggleJoinButton(numPlayers + 1 >= minPlayers);
}
}
return obj;
}
public override void OnLobbyServerPlayerRemoved(NetworkConnection conn, short playerControllerId)
{
for (int i = 0; i < lobbySlots.Length; ++i)
{
LobbyPlayer p = lobbySlots[i] as LobbyPlayer;
if (p != null)
{
p.RpcUpdateRemoveButton();
p.ToggleJoinButton(numPlayers + 1 >= minPlayers);
}
}
}
public override void OnLobbyServerDisconnect(NetworkConnection conn)
{
for (int i = 0; i < lobbySlots.Length; ++i)
{
LobbyPlayer p = lobbySlots[i] as LobbyPlayer;
if (p != null)
{
p.RpcUpdateRemoveButton();
p.ToggleJoinButton(numPlayers >= minPlayers);
}
}
}
public override bool OnLobbyServerSceneLoadedForPlayer(GameObject lobbyPlayer, GameObject gamePlayer)
{
//This hook allows you to apply state data from the lobby-player to the game-player
//just subclass "LobbyHook" and add it to the lobby object.
if (_lobbyHooks)
_lobbyHooks.OnLobbyServerSceneLoadedForPlayer(this, lobbyPlayer, gamePlayer);
return true;
}
// --- Countdown management
public override void OnLobbyServerPlayersReady()
{
bool allready = true;
for(int i = 0; i < lobbySlots.Length; ++i)
{
if(lobbySlots[i] != null)
allready &= lobbySlots[i].readyToBegin;
}
if(allready)
StartCoroutine(ServerCountdownCoroutine());
}
public IEnumerator ServerCountdownCoroutine()
{
float remainingTime = prematchCountdown;
int floorTime = Mathf.FloorToInt(remainingTime);
while (remainingTime > 0)
{
yield return null;
remainingTime -= Time.deltaTime;
int newFloorTime = Mathf.FloorToInt(remainingTime);
if (newFloorTime != floorTime)
{//to avoid flooding the network of message, we only send a notice to client when the number of plain seconds change.
floorTime = newFloorTime;
for (int i = 0; i < lobbySlots.Length; ++i)
{
if (lobbySlots[i] != null)
{//there is maxPlayer slots, so some could be == null, need to test it before accessing!
(lobbySlots[i] as LobbyPlayer).RpcUpdateCountdown(floorTime);
}
}
}
}
for (int i = 0; i < lobbySlots.Length; ++i)
{
if (lobbySlots[i] != null)
{
(lobbySlots[i] as LobbyPlayer).RpcUpdateCountdown(0);
}
}
ServerChangeScene(playScene);
}
// ----------------- Client callbacks ------------------
public override void OnClientConnect(NetworkConnection conn)
{
base.OnClientConnect(conn);
infoPanel.gameObject.SetActive(false);
conn.RegisterHandler(MsgKicked, KickedMessageHandler);
if (!NetworkServer.active)
{//only to do on pure client (not self hosting client)
ChangeTo(lobbyPanel);
//backDelegate = StopClientClbk;
SetServerInfo("Client", networkAddress);
}
}
public override void OnClientDisconnect(NetworkConnection conn)
{
base.OnClientDisconnect(conn);
ChangeTo(mainMenuPanel);
}
public override void OnClientError(NetworkConnection conn, int errorCode)
{
ChangeTo(mainMenuPanel);
infoPanel.Display("Cient error : " + (errorCode == 6 ? "timeout" : errorCode.ToString()), "Close", null);
}
}
}

I think that you have to re-think the concept.
If you want to keep a "reference" to the last scene, you should save the state of your scene in some static manner (json?) or at least in a variable-gameObject.
You won't to keep "OnDestroyOnLoad" your scene, cause it's a waste of resources.
But, if you still want, I'll recommend you to use the additive way to load scenes. So you load the new scene into additive way, and disable the objects of the last scene.
Additive Mode: https://docs.unity3d.com/ScriptReference/SceneManagement.LoadSceneMode.Additive.html
Disable GameObjects: https://docs.unity3d.com/ScriptReference/GameObject.SetActive.html

Related

how to make a Delaunay triangulation in unity

So I'm trying to make my own Delaunay triangulation maker fist I need to make triangular in my code. I do this by finding 3 obj and adding them to a list. Know there are two things I do not know how to do first I need to see if that obj is on the list next. I need to do that for every obj.
[System.Serializable]
public class tringle
{
public GameObject GameOBJ_0, GameOBJ_1, GameOBJ_2;
private Vector3 pos_0;
private Vector3 pos_1;
private Vector3 pos_2;
public Vector3 midpoint;
public void SetGameOBJ_0(GameObject setOBj_0)
{
GameOBJ_0 = setOBj_0;
}
public void SetGameOBJ_1(GameObject setOBj_1)
{
GameOBJ_1 = setOBj_1;
}
public void SetGameOBJ_2(GameObject setOBj_2)
{
GameOBJ_2 = setOBj_2;
}
public void SetPos()
{
pos_0= GameOBJ_0.transform.localPosition;
pos_1= GameOBJ_1.transform.localPosition;
pos_2= GameOBJ_2.transform.localPosition;
FindMidPoint();
}
public void FindMidPoint()
{
midpoint = new Vector3((pos_0.x + pos_1.x + pos_2.x)/3,0, (pos_0.z + pos_1.z + pos_2.z) / 3);
}
}
and
foreach (GameObject room in Rooms)
{
for (int i = 0; i < Rooms.Length / 3; i++)
{
if (TRINGLE[i].GameOBJ_0 != room && TRINGLE[i].GameOBJ_1 != room && TRINGLE[i].GameOBJ_2 != room)
{
foreach (tringle item in TRINGLE)
{
if (!TRINGLE.Contains(item)) TRINGLE.Add(item);
}
}
}
}`
public GameObject GameOBJ_0, GameOBJ_1, GameOBJ_2;
private Vector3 pos_0;
private Vector3 pos_1;
private Vector3 pos_2;
public Vector3 midpoint;
public void SetGameOBJ_0(GameObject setOBj_0)
{
GameOBJ_0 = setOBj_0;
}
public void SetGameOBJ_1(GameObject setOBj_1)
{
GameOBJ_1 = setOBj_1;
}
public void SetGameOBJ_2(GameObject setOBj_2)
{
GameOBJ_2 = setOBj_2;
SetPos();
}
public void SetPos()
{
pos_0= GameOBJ_0.transform.localPosition;
pos_1= GameOBJ_1.transform.localPosition;
pos_2= GameOBJ_2.transform.localPosition;
FindMidPoint();
}
public void FindMidPoint()
{
midpoint = new Vector3((pos_0.x + pos_1.x + pos_2.x)/3,0, (pos_0.z + pos_1.z + pos_2.z) / 3);
}
void Update()
{
foreach (GameObject room in Rooms)
{
if(i < triglenuber)
{
foreach (tringle item in TRINGLE)
{
if (!OBJPos.Contains(room))
{
if (TRINGLE[i].GameOBJ_0 == null)
{
OBJPos.Add(room);
TRINGLE[i].SetGameOBJ_0(room);
}
else if (TRINGLE[i].GameOBJ_1 == null)
{
OBJPos.Add(room);
TRINGLE[i].SetGameOBJ_1(room);
}
else if (TRINGLE[i].GameOBJ_2 == null)
{
OBJPos.Add(room);
TRINGLE[i].SetGameOBJ_2(room);
}
else
{
i++;
}
}
}
}
}

TransformTileProvider:No location marker transform specified Unity error

I am getting this error when I am trying to run a game using a Mapbox prefab: TransformTileProvider: No location marker transform specified.
UnityEngine.Debug:LogError(Object) Mapbox.Unity.Map.TileProviders.RangeAroundTransformTileProvider:OnInitialized()
If I change OnIntialized to public I get a whole bunch of other errors.
Here is the code:
using System.Collections.Generic;
using Mapbox.Map;
using UnityEngine;
namespace Mapbox.Unity.Map.TileProviders
{
public class RangeAroundTransformTileProvider : AbstractTileProvider
{
[SerializeField] private RangeAroundTransformTileProviderOptions _rangeTileProviderOptions;
private bool _initialized = false;
private UnwrappedTileId _currentTile;
private bool _waitingForTargetTransform = false;
public override void OnInitialized()
{
if (Options != null)
{
_rangeTileProviderOptions = (RangeAroundTransformTileProviderOptions)Options;
}
else if (_rangeTileProviderOptions == null)
{
_rangeTileProviderOptions = new RangeAroundTransformTileProviderOptions();
}
if (_rangeTileProviderOptions.targetTransform == null)
{
Debug.LogError("TransformTileProvider: No location marker transform specified.");
_waitingForTargetTransform = true;
}
else
{
_initialized = true;
}
_currentExtent.activeTiles = new HashSet<UnwrappedTileId>();
_map.OnInitialized += UpdateTileExtent;
_map.OnUpdated += UpdateTileExtent;
}
public override void UpdateTileExtent()
{
if (!_initialized) return;
_currentExtent.activeTiles.Clear();
_currentTile = TileCover.CoordinateToTileId(_map.WorldToGeoPosition(_rangeTileProviderOptions.targetTransform.localPosition), _map.AbsoluteZoom);
for (int x = _currentTile.X - _rangeTileProviderOptions.visibleBuffer; x <= (_currentTile.X + _rangeTileProviderOptions.visibleBuffer); x++)
{
for (int y = _currentTile.Y - _rangeTileProviderOptions.visibleBuffer; y <= (_currentTile.Y + _rangeTileProviderOptions.visibleBuffer); y++)
{
_currentExtent.activeTiles.Add(new UnwrappedTileId(_map.AbsoluteZoom, x, y));
}
}
OnExtentChanged();
}
public override void UpdateTileProvider()
{
if (_waitingForTargetTransform && !_initialized)
{
if (_rangeTileProviderOptions.targetTransform != null)
{
_initialized = true;
}
}
if (_rangeTileProviderOptions != null && _rangeTileProviderOptions.targetTransform != null && _rangeTileProviderOptions.targetTransform.hasChanged)
{
UpdateTileExtent();
_rangeTileProviderOptions.targetTransform.hasChanged = false;
}
}
public override bool Cleanup(UnwrappedTileId tile)
{
bool dispose = false;
dispose = tile.X > _currentTile.X + _rangeTileProviderOptions.disposeBuffer || tile.X < _currentTile.X - _rangeTileProviderOptions.disposeBuffer;
dispose = dispose || tile.Y > _currentTile.Y + _rangeTileProviderOptions.disposeBuffer || tile.Y < _currentTile.Y - _rangeTileProviderOptions.disposeBuffer;
return (dispose);
}
}
}
**The camera must be looking at "something" **
Step 1: Abstract Map: General / Extend options: "Range Around Transform".
Step 2: Abstract Map: General / Extend options / Target Transform: "PlayerTarget(Transform)"
Source: https://answers.unity.com/questions/1592263/how-can-i-solve-this-problem-using-mapbox-in-unity.html

Scene is Loading in Unity but unable to Load Scene in Android

My Game is working perfectly in Unity but when I export apk tp Android Mobile 2nd Scene doesn't load properly and does not work.
Please look at the image. It is the second Scene and not loaded properly and the Run button is not working which is working perfectly in unity play mode.
enter image description here
CODES ARE BELOW
SCENE 1 CODE#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
#if UNITY_ANALYTICS
using UnityEngine.Analytics;
#endif
#if UNITY_PURCHASING
using UnityEngine.Purchasing;
#endif
public class StartButton : MonoBehaviour
{
public void StartGame()
{
if (PlayerData.instance.ftueLevel == 0)
{
PlayerData.instance.ftueLevel = 1;
PlayerData.instance.Save();
#if UNITY_ANALYTICS
AnalyticsEvent.FirstInteraction("start_button_pressed");
#endif
}
#if UNITY_PURCHASING
var module = StandardPurchasingModule.Instance();
#endif
SceneManager.LoadScene("main");
}
}
SCENE 2 CODE#
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
#if UNITY_ANALYTICS
using UnityEngine.Analytics;
#endif
/// <summary>
/// State pushed on the GameManager during the Loadout, when player select player, theme and accessories
/// Take care of init the UI, load all the data used for it etc.
/// </summary>
public class LoadoutState : AState
{
public Canvas inventoryCanvas;
[Header("Char UI")]
public Text charNameDisplay;
public RectTransform charSelect;
public Transform charPosition;
[Header("Theme UI")]
public Text themeNameDisplay;
public RectTransform themeSelect;
public Image themeIcon;
[Header("PowerUp UI")]
public RectTransform powerupSelect;
public Image powerupIcon;
public Text powerupCount;
public Sprite noItemIcon;
[Header("Accessory UI")]
public RectTransform accessoriesSelector;
public Text accesoryNameDisplay;
public Image accessoryIconDisplay;
[Header("Other Data")]
public Leaderboard leaderboard;
public MissionUI missionPopup;
public Button runButton;
public GameObject tutorialBlocker;
public GameObject tutorialPrompt;
public MeshFilter skyMeshFilter;
public MeshFilter UIGroundFilter;
public AudioClip menuTheme;
[Header("Prefabs")]
public ConsumableIcon consumableIcon;
Consumable.ConsumableType m_PowerupToUse = Consumable.ConsumableType.NONE;
protected GameObject m_Character;
protected List<int> m_OwnedAccesories = new List<int>();
protected int m_UsedAccessory = -1;
protected int m_UsedPowerupIndex;
protected bool m_IsLoadingCharacter;
protected Modifier m_CurrentModifier = new Modifier();
protected const float k_CharacterRotationSpeed = 45f;
protected const string k_ShopSceneName = "shop";
protected const float k_OwnedAccessoriesCharacterOffset = -0.1f;
protected int k_UILayer;
protected readonly Quaternion k_FlippedYAxisRotation = Quaternion.Euler (0f, 180f, 0f);
public override void Enter(AState from)
{
tutorialBlocker.SetActive(!PlayerData.instance.tutorialDone);
tutorialPrompt.SetActive(false);
inventoryCanvas.gameObject.SetActive(true);
missionPopup.gameObject.SetActive(false);
charNameDisplay.text = "";
themeNameDisplay.text = "";
k_UILayer = LayerMask.NameToLayer("UI");
skyMeshFilter.gameObject.SetActive(true);
UIGroundFilter.gameObject.SetActive(true);
// Reseting the global blinking value. Can happen if the game unexpectedly exited while still blinking
Shader.SetGlobalFloat("_BlinkingValue", 0.0f);
if (MusicPlayer.instance.GetStem(0) != menuTheme)
{
MusicPlayer.instance.SetStem(0, menuTheme);
StartCoroutine(MusicPlayer.instance.RestartAllStems());
}
runButton.interactable = false;
runButton.GetComponentInChildren<Text>().text = "Loading...";
if(m_PowerupToUse != Consumable.ConsumableType.NONE)
{
//if we come back from a run and we don't have any more of the powerup we wanted to use, we reset the powerup to use to NONE
if (!PlayerData.instance.consumables.ContainsKey(m_PowerupToUse) || PlayerData.instance.consumables[m_PowerupToUse] == 0)
m_PowerupToUse = Consumable.ConsumableType.NONE;
}
Refresh();
}
public override void Exit(AState to)
{
missionPopup.gameObject.SetActive(false);
inventoryCanvas.gameObject.SetActive(false);
if (m_Character != null) Addressables.ReleaseInstance(m_Character);
GameState gs = to as GameState;
skyMeshFilter.gameObject.SetActive(false);
UIGroundFilter.gameObject.SetActive(false);
if (gs != null)
{
gs.currentModifier = m_CurrentModifier;
// We reset the modifier to a default one, for next run (if a new modifier is applied, it will replace this default one before the run starts)
m_CurrentModifier = new Modifier();
if (m_PowerupToUse != Consumable.ConsumableType.NONE)
{
PlayerData.instance.Consume(m_PowerupToUse);
Consumable inv = Instantiate(ConsumableDatabase.GetConsumbale(m_PowerupToUse));
inv.gameObject.SetActive(false);
gs.trackManager.characterController.inventory = inv;
}
}
}
public void Refresh()
{
PopulatePowerup();
StartCoroutine(PopulateCharacters());
StartCoroutine(PopulateTheme());
}
public override string GetName()
{
return "Loadout";
}
public override void Tick()
{
if (!runButton.interactable)
{
bool interactable = ThemeDatabase.loaded && CharacterDatabase.loaded;
if(interactable)
{
runButton.interactable = true;
runButton.GetComponentInChildren<Text>().text = "Run!";
//we can always enabled, as the parent will be disabled if tutorial is already done
tutorialPrompt.SetActive(true);
}
}
if(m_Character != null)
{
m_Character.transform.Rotate(0, k_CharacterRotationSpeed * Time.deltaTime, 0, Space.Self);
}
charSelect.gameObject.SetActive(PlayerData.instance.characters.Count > 1);
themeSelect.gameObject.SetActive(PlayerData.instance.themes.Count > 1);
}
public void GoToStore()
{
UnityEngine.SceneManagement.SceneManager.LoadScene(k_ShopSceneName, UnityEngine.SceneManagement.LoadSceneMode.Additive);
}
public void ChangeCharacter(int dir)
{
PlayerData.instance.usedCharacter += dir;
if (PlayerData.instance.usedCharacter >= PlayerData.instance.characters.Count)
PlayerData.instance.usedCharacter = 0;
else if(PlayerData.instance.usedCharacter < 0)
PlayerData.instance.usedCharacter = PlayerData.instance.characters.Count-1;
StartCoroutine(PopulateCharacters());
}
public void ChangeAccessory(int dir)
{
m_UsedAccessory += dir;
if (m_UsedAccessory >= m_OwnedAccesories.Count)
m_UsedAccessory = -1;
else if (m_UsedAccessory < -1)
m_UsedAccessory = m_OwnedAccesories.Count-1;
if (m_UsedAccessory != -1)
PlayerData.instance.usedAccessory = m_OwnedAccesories[m_UsedAccessory];
else
PlayerData.instance.usedAccessory = -1;
SetupAccessory();
}
public void ChangeTheme(int dir)
{
PlayerData.instance.usedTheme += dir;
if (PlayerData.instance.usedTheme >= PlayerData.instance.themes.Count)
PlayerData.instance.usedTheme = 0;
else if (PlayerData.instance.usedTheme < 0)
PlayerData.instance.usedTheme = PlayerData.instance.themes.Count - 1;
StartCoroutine(PopulateTheme());
}
public IEnumerator PopulateTheme()
{
ThemeData t = null;
while (t == null)
{
t = ThemeDatabase.GetThemeData(PlayerData.instance.themes[PlayerData.instance.usedTheme]);
yield return null;
}
themeNameDisplay.text = t.themeName;
themeIcon.sprite = t.themeIcon;
skyMeshFilter.sharedMesh = t.skyMesh;
UIGroundFilter.sharedMesh = t.UIGroundMesh;
}
public IEnumerator PopulateCharacters()
{
accessoriesSelector.gameObject.SetActive(false);
PlayerData.instance.usedAccessory = -1;
m_UsedAccessory = -1;
if (!m_IsLoadingCharacter)
{
m_IsLoadingCharacter = true;
GameObject newChar = null;
while (newChar == null)
{
Character c = CharacterDatabase.GetCharacter(PlayerData.instance.characters[PlayerData.instance.usedCharacter]);
if (c != null)
{
m_OwnedAccesories.Clear();
for (int i = 0; i < c.accessories.Length; ++i)
{
// Check which accessories we own.
string compoundName = c.characterName + ":" + c.accessories[i].accessoryName;
if (PlayerData.instance.characterAccessories.Contains(compoundName))
{
m_OwnedAccesories.Add(i);
}
}
Vector3 pos = charPosition.transform.position;
if (m_OwnedAccesories.Count > 0)
{
pos.x = k_OwnedAccessoriesCharacterOffset;
}
else
{
pos.x = 0.0f;
}
charPosition.transform.position = pos;
accessoriesSelector.gameObject.SetActive(m_OwnedAccesories.Count > 0);
AsyncOperationHandle op = Addressables.InstantiateAsync(c.characterName);
yield return op;
if (op.Result == null || !(op.Result is GameObject))
{
Debug.LogWarning(string.Format("Unable to load character {0}.", c.characterName));
yield break;
}
newChar = op.Result as GameObject;
Helpers.SetRendererLayerRecursive(newChar, k_UILayer);
newChar.transform.SetParent(charPosition, false);
newChar.transform.rotation = k_FlippedYAxisRotation;
if (m_Character != null)
Addressables.ReleaseInstance(m_Character);
m_Character = newChar;
charNameDisplay.text = c.characterName;
m_Character.transform.localPosition = Vector3.right * 1000;
//animator will take a frame to initialize, during which the character will be in a T-pose.
//So we move the character off screen, wait that initialised frame, then move the character back in place.
//That avoid an ugly "T-pose" flash time
yield return new WaitForEndOfFrame();
m_Character.transform.localPosition = Vector3.zero;
SetupAccessory();
}
else
yield return new WaitForSeconds(1.0f);
}
m_IsLoadingCharacter = false;
}
}
void SetupAccessory()
{
Character c = m_Character.GetComponent<Character>();
c.SetupAccesory(PlayerData.instance.usedAccessory);
if (PlayerData.instance.usedAccessory == -1)
{
accesoryNameDisplay.text = "None";
accessoryIconDisplay.enabled = false;
}
else
{
accessoryIconDisplay.enabled = true;
accesoryNameDisplay.text = c.accessories[PlayerData.instance.usedAccessory].accessoryName;
accessoryIconDisplay.sprite = c.accessories[PlayerData.instance.usedAccessory].accessoryIcon;
}
}
void PopulatePowerup()
{
powerupIcon.gameObject.SetActive(true);
if (PlayerData.instance.consumables.Count > 0)
{
Consumable c = ConsumableDatabase.GetConsumbale(m_PowerupToUse);
powerupSelect.gameObject.SetActive(true);
if (c != null)
{
powerupIcon.sprite = c.icon;
powerupCount.text = PlayerData.instance.consumables[m_PowerupToUse].ToString();
}
else
{
powerupIcon.sprite = noItemIcon;
powerupCount.text = "";
}
}
else
{
powerupSelect.gameObject.SetActive(false);
}
}
public void ChangeConsumable(int dir)
{
bool found = false;
do
{
m_UsedPowerupIndex += dir;
if(m_UsedPowerupIndex >= (int)Consumable.ConsumableType.MAX_COUNT)
{
m_UsedPowerupIndex = 0;
}
else if(m_UsedPowerupIndex < 0)
{
m_UsedPowerupIndex = (int)Consumable.ConsumableType.MAX_COUNT - 1;
}
int count = 0;
if(PlayerData.instance.consumables.TryGetValue((Consumable.ConsumableType)m_UsedPowerupIndex, out count) && count > 0)
{
found = true;
}
} while (m_UsedPowerupIndex != 0 && !found);
m_PowerupToUse = (Consumable.ConsumableType)m_UsedPowerupIndex;
PopulatePowerup();
}
public void UnequipPowerup()
{
m_PowerupToUse = Consumable.ConsumableType.NONE;
}
public void SetModifier(Modifier modifier)
{
m_CurrentModifier = modifier;
}
public void StartGame()
{
if (PlayerData.instance.tutorialDone)
{
if (PlayerData.instance.ftueLevel == 1)
{
PlayerData.instance.ftueLevel = 2;
PlayerData.instance.Save();
}
}
manager.SwitchState("Game");
}
public void Openleaderboard()
{
leaderboard.displayPlayer = false;
leaderboard.forcePlayerDisplay = false;
leaderboard.Open();
}
}
When you are building an APK file it can be splited to APK + OBB.
So, it is possible that you are trying to load a scene that is absent in your APK. You need to force the creation of the APK without the OBB. To do it you need to check Player Settings in Android, go to Publishing Settings and uncheck Split Application Binary.

trying to save and load a value in c# unity but having trouble

I am trying to get part of my game working but having trouble solving this problem!
I have boosters that remove game pieces if the user has enough in game coins to use. It is working to an extent and once a booster has been used the coins will decrement but upon exiting and reloading the game it does not update the correct value!
For example, the boosters can be used at a cost of 50 coins, if I have 200 coins and use 4 boosters the value updates to 0 and this works. However if I restart then the value of 200 is still there!
I have a coin manager script set up with playerprefs that gives the user 50 coins after each level, this is linked to the booster script.
Booster class:
public class Booster : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler {
Image m_image;
RectTransform m_rectXform;
Vector3 m_startPosition;
Board m_board;
Tile m_tileTarget;
public static GameObject ActiveBooster;
public Text instructionsText;
public string instructions = "drag over game piece to remove";
public bool isEnabled = false;
public bool isDraggable = false;
public bool isLocked = false;
public List<CanvasGroup> canvasGroups;
public UnityEvent boostEvent;
public int boostTime = 15;
//coin test
CoinManager coinManager;
private void Awake()
{
m_image = GetComponent<Image> ();
m_rectXform = GetComponent<RectTransform> ();
m_board = Object.FindObjectOfType<Board> ().GetComponent<Board> ();
coinManager = GameObject.Find ("CoinManager").GetComponent<CoinManager> ();
}
void Start ()
{
EnableBooster (false);
}
public void EnableBooster(bool state)
{
isEnabled = state;
if (state)
{
DisableOtherBoosters ();
Booster.ActiveBooster = gameObject;
}
else if(gameObject == Booster.ActiveBooster)
{
Booster.ActiveBooster = null;
}
m_image.color = (state) ? Color.white : Color.gray;
if (instructionsText != null)
{
instructionsText.gameObject.SetActive (Booster.ActiveBooster != null);
if (gameObject == Booster.ActiveBooster)
{
instructionsText.text = instructions;
}
}
}
void DisableOtherBoosters()
{
Booster[] allBoosters = Object.FindObjectsOfType<Booster> ();
foreach (Booster b in allBoosters)
{
if (b != this)
{
b.EnableBooster (false);
}
}
}
public void ToggleBooster()
{
EnableBooster (!isEnabled);
}
public void OnBeginDrag (PointerEventData eventData)
{
if (isEnabled && isDraggable && !isLocked)
{
m_startPosition = gameObject.transform.position;
EnableCanvasGroups (false);
}
}
public void OnDrag (PointerEventData eventData)
{
if (isEnabled && isDraggable && !isLocked && Camera.main != null)
{
Vector3 onscreenPosition;
RectTransformUtility.ScreenPointToWorldPointInRectangle (m_rectXform, eventData.position,
Camera.main, out onscreenPosition);
gameObject.transform.position = onscreenPosition;
RaycastHit2D hit2D = Physics2D.Raycast (onscreenPosition, Vector3.forward, Mathf.Infinity);
if (hit2D.collider != null)
{
m_tileTarget = hit2D.collider.GetComponent<Tile> ();
}
else
{
m_tileTarget = null;
}
}
}
public void OnEndDrag (PointerEventData eventData)
{
if (isEnabled && isDraggable && !isLocked)
{
gameObject.transform.position = m_startPosition;
EnableCanvasGroups (true);
if (m_board != null && m_board.isRefilling)
{
return;
}
if (m_tileTarget != null)
{
if (boostEvent != null)
{
boostEvent.Invoke (); //can do things here like play a sound effect
}
EnableBooster (false);
m_tileTarget = null;
Booster.ActiveBooster = null;
}
}
}
void EnableCanvasGroups(bool state)
{
if (canvasGroups != null && canvasGroups.Count > 0)
{
foreach (CanvasGroup cGroup in canvasGroups)
{
if (cGroup != null)
{
cGroup.blocksRaycasts = state;
}
}
}
}
public void RemoveOneGamePiece()
{
if (m_board != null && m_tileTarget != null)
{
if (coinManager.currentCoinCount >= 50)
{
m_board.ClearAndRefillBoard (m_tileTarget.xIndex, m_tileTarget.yIndex);
coinManager.AddCoins (-50);
coinManager.SetCoinCount();
coinManager.ShowCoinCount ();
}
}
}
public void AddTime()
{
if (GameManager.Instance != null)
{
if (coinManager.currentCoinCount >= 50){
GameManager.Instance.AddTime (boostTime);
coinManager.AddCoins (-50);
coinManager.SetCoinCount();
coinManager.ShowCoinCount ();
}
}
}
public void DropColorBomb() //big bomb
{
if (m_board != null && m_tileTarget != null)
{
if (coinManager.currentCoinCount >= 50)
{
m_board.MakeColorBombBooster (m_tileTarget.xIndex, m_tileTarget.yIndex);
coinManager.AddCoins (-50);
coinManager.SetCoinCount();
coinManager.ShowCoinCount ();
}
}
}
}
CoinManager class:
public class CoinManager : Singleton<CoinManager>{
// reference to the UI Text element
public Text coinText;
// current number of coins earned during gameplay
public int currentCoinCount = 0;
// because we don't have a key set, we should create it and initialize its value to 0
public void InitCoinCount()
{
if (!PlayerPrefs.HasKey("TotalCoins"))
{
PlayerPrefs.SetInt("TotalCoins",0);
}
}
// returns the number of coins stored in PlayerPrefs
public int GetCoinCount()
{
if (PlayerPrefs.HasKey("TotalCoins"))
{
return PlayerPrefs.GetInt("TotalCoins");
}
// if we don't have the key set, so return 0
return 0;
}
// sets a number of coins into PlayerPrefs if the current coin count is greater
public void SetCoinCount()
{
if (PlayerPrefs.HasKey("TotalCoins"))
{
int oldCoins = PlayerPrefs.GetInt("TotalCoins");
if (currentCoinCount > oldCoins)
{
PlayerPrefs.SetInt("TotalCoins", currentCoinCount);
}
}
}
// display the coin count as a TextUI
public void ShowCoinCount()
{
if (coinText != null)
{
coinText.text = currentCoinCount.ToString();
}
}
//new method for oldcoin count
public void AddCoins(int coins)
{
currentCoinCount = currentCoinCount + coins;
}
}
// sets a number of coins into PlayerPrefs if the current coin count is greater
Well, this comment basically tells you the problem. If the coin count isn't greater than what was saved previously, it doesn't save!
Change this:
// sets a number of coins into PlayerPrefs if the current coin count is greater
public void SetCoinCount()
{
if (PlayerPrefs.HasKey("TotalCoins"))
{
int oldCoins = PlayerPrefs.GetInt("TotalCoins");
if (currentCoinCount > oldCoins)
{
PlayerPrefs.SetInt("TotalCoins", currentCoinCount);
}
}
}
To this:
// sets a number of coins into PlayerPrefs
public void SetCoinCount()
{
PlayerPrefs.SetInt("TotalCoins", currentCoinCount);
}

GUI text created during runtime is not visible

I am using the DebugConsole script to show the debug output on screen.It works perfectly but appears at the top left corner. I want it to appear inside a panel where I have created a window and a GUI text element and the script gives this option as well. I see the gui text formed as an element in the project console, but is not visible.
I do have a GUI layer
My gui text element is the direct child of a canvas
Camera is set to screen space overlay. I tried worldspace , still not visible.
My code:
namespace OctopartApi
{
using Newtonsoft.Json;
using RestSharp;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine;
using System.Net;
using UnityEngine.UI;
public class KeywordSearch1 : MonoBehaviour
{
public InputField mainInputField;
public Canvas can;
public Text infoText;
public float x, y;
void Start () {
mainInputField.onEndEdit.AddListener(delegate {LockInput(mainInputField); });
}
void LockInput(InputField input)
{
ExecuteSearch (input.text);
}
public void ExecuteSearch(string inp)
{
// -- your search query --
string query = inp;
string octopartUrlBase = "http://octopart.com/api/v3";
string octopartUrlEndpoint = "parts/search";
string apiKey = "57af648b";
// Create the search request
var client = new RestClient(octopartUrlBase);
var req = new RestRequest(octopartUrlEndpoint, Method.GET)
.AddParameter("apikey", apiKey)
.AddParameter("q", query)
.AddParameter("start", "0")
.AddParameter("limit", "10");
var resp = client.Execute(req);
string octojson = resp.Content;
RootOb rr = JsonUtility.FromJson<RootOb> (octojson);
string hhts = (rr.hits).ToString();
hhts = hhts + rr.user_currency;
infoText.horizontalOverflow = HorizontalWrapMode.Overflow;
infoText.verticalOverflow = VerticalWrapMode.Overflow;
infoText.text = hhts;
// sendR (inp);
// Perform the search and obtain results
/* var resp = client.Execute(req);
var search_response = JsonConvert.DeserializeObject<dynamic>(resp.Content);
Console.WriteLine (search_response);
// Print the number of hits and results
Console.WriteLine("Number of hits: " + search_response["hits"]);
Debug.Log(search_response ["hits"]+"OCTO");
foreach (var result in search_response["results"])
{
var part = result["item"];
Debug.Log(part["brand"]["name"] + "OCTO" + part["mpn"]+part["octopart_url"]);
DebugConsole.Log (part ["brand"] ["name"] + "-- " + part ["mpn"]+" " +part["octopart_url"]);
}*/
}
// -- your API key -- (https://octopart.com/api/register)
private const string APIKEY = "57af648b";
}
}
DebugConsole script :
using UnityEngine;
using System.Collections;
public class DebugConsole : MonoBehaviour
{
public GameObject DebugGui = null; // The GUI that will be duplicated
public Vector3 defaultGuiPosition = new Vector3(0.01F, 0.98F, 0F);
public Vector3 defaultGuiScale = new Vector3(0.5F, 0.5F, 1F);
public Color normal = Color.green;
public Color warning = Color.yellow;
public Color error = Color.red;
public int maxMessages = 30; // The max number of messages displayed
public float lineSpacing = 0.02F; // The amount of space between lines
public ArrayList messages = new ArrayList();
public ArrayList guis = new ArrayList();
public ArrayList colors = new ArrayList();
public bool draggable = true; // Can the output be dragged around at runtime by default?
public bool visible = true; // Does output show on screen by default or do we have to enable it with code?
public bool pixelCorrect = false; // set to be pixel Correct linespacing
public static bool isVisible
{
get
{
return DebugConsole.instance.visible;
}
set
{
DebugConsole.instance.visible = value;
if (value == true)
{
DebugConsole.instance.Display();
}
else if (value == false)
{
DebugConsole.instance.ClearScreen();
}
}
}
public static bool isDraggable
{
get
{
return DebugConsole.instance.draggable;
}
set
{
DebugConsole.instance.draggable = value;
}
}
private static DebugConsole s_Instance = null; // Our instance to allow this script to be called without a direct connection.
public static DebugConsole instance
{
get
{
if (s_Instance == null)
{
s_Instance = FindObjectOfType(typeof(DebugConsole)) as DebugConsole;
if (s_Instance == null)
{
GameObject console = new GameObject();
console.AddComponent<DebugConsole>();
console.name = "DebugConsoleController";
s_Instance = FindObjectOfType(typeof(DebugConsole)) as DebugConsole;
DebugConsole.instance.InitGuis();
}
}
return s_Instance;
}
}
void Awake()
{
s_Instance = this;
InitGuis();
}
protected bool guisCreated = false;
protected float screenHeight =-1;
public void InitGuis()
{
float usedLineSpacing = lineSpacing;
screenHeight = Screen.height;
if(pixelCorrect)
usedLineSpacing = 1.0F / screenHeight * usedLineSpacing;
if (guisCreated == false)
{
if (DebugGui == null) // If an external GUIText is not set, provide the default GUIText
{
DebugGui = new GameObject();
DebugGui.AddComponent<GUIText>();
DebugGui.name = "DebugGUI(0)";
DebugGui.transform.position = defaultGuiPosition;
DebugGui.transform.localScale = defaultGuiScale;
}
// Create our GUI objects to our maxMessages count
Vector3 position = DebugGui.transform.position;
guis.Add(DebugGui);
int x = 1;
while (x < maxMessages)
{
position.y -= usedLineSpacing;
GameObject clone = null;
clone = (GameObject)Instantiate(DebugGui, position, transform.rotation);
clone.name = string.Format("DebugGUI({0})", x);
guis.Add(clone);
position = clone.transform.position;
x += 1;
}
x = 0;
while (x < guis.Count)
{
GameObject temp = (GameObject)guis[x];
temp.transform.parent = DebugGui.transform;
x++;
}
guisCreated = true;
} else {
// we're called on a screensize change, so fiddle with sizes
Vector3 position = DebugGui.transform.position;
for(int x=0;x < guis.Count; x++)
{
position.y -= usedLineSpacing;
GameObject temp = (GameObject)guis[x];
temp.transform.position= position;
}
}
}
bool connectedToMouse = false;
void Update()
{
// If we are visible and the screenHeight has changed, reset linespacing
if (visible == true && screenHeight != Screen.height)
{
InitGuis();
}
if (draggable == true)
{
if (Input.GetMouseButtonDown(0))
{
if (connectedToMouse == false && DebugGui.GetComponent<GUIText>().HitTest((Vector3)Input.mousePosition) == true)
{
connectedToMouse = true;
}
else if (connectedToMouse == true)
{
connectedToMouse = false;
}
}
if (connectedToMouse == true)
{
float posX = DebugGui.transform.position.x;
float posY = DebugGui.transform.position.y;
posX = Input.mousePosition.x / Screen.width;
posY = Input.mousePosition.y / Screen.height;
DebugGui.transform.position = new Vector3(posX, posY, 0F);
}
}
}
//+++++++++ INTERFACE FUNCTIONS ++++++++++++++++++++++++++++++++
public static void Log(string message, string color)
{
DebugConsole.instance.AddMessage(message, color);
}
//++++ OVERLOAD ++++
public static void Log(string message)
{
DebugConsole.instance.AddMessage(message);
}
public static void Clear()
{
DebugConsole.instance.ClearMessages();
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//---------- void AddMesage(string message, string color) ------
//Adds a mesage to the list
//--------------------------------------------------------------
public void AddMessage(string message, string color)
{
messages.Add(message);
colors.Add(color);
Display();
}
//++++++++++ OVERLOAD for AddMessage ++++++++++++++++++++++++++++
// Overloads AddMessage to only require one argument(message)
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public void AddMessage(string message)
{
messages.Add(message);
colors.Add("normal");
Display();
}
//----------- void ClearMessages() ------------------------------
// Clears the messages from the screen and the lists
//---------------------------------------------------------------
public void ClearMessages()
{
messages.Clear();
colors.Clear();
ClearScreen();
}
//-------- void ClearScreen() ----------------------------------
// Clears all output from all GUI objects
//--------------------------------------------------------------
void ClearScreen()
{
if (guis.Count < maxMessages)
{
//do nothing as we haven't created our guis yet
}
else
{
int x = 0;
while (x < guis.Count)
{
GameObject gui = (GameObject)guis[x];
gui.GetComponent<GUIText>().text = "";
//increment and loop
x += 1;
}
}
}
//---------- void Prune() ---------------------------------------
// Prunes the array to fit within the maxMessages limit
//---------------------------------------------------------------
void Prune()
{
int diff;
if (messages.Count > maxMessages)
{
if (messages.Count <= 0)
{
diff = 0;
}
else
{
diff = messages.Count - maxMessages;
}
messages.RemoveRange(0, (int)diff);
colors.RemoveRange(0, (int)diff);
}
}
//---------- void Display() -------------------------------------
// Displays the list and handles coloring
//---------------------------------------------------------------
void Display()
{
//check if we are set to display
if (visible == false)
{
ClearScreen();
}
else if (visible == true)
{
if (messages.Count > maxMessages)
{
Prune();
}
// Carry on with display
int x = 0;
if (guis.Count < maxMessages)
{
//do nothing as we havent created our guis yet
}
else
{
while (x < messages.Count)
{
GameObject gui = (GameObject)guis[x];
//set our color
switch ((string)colors[x])
{
case "normal": gui.GetComponent<GUIText>().material.color = normal;
break;
case "warning": gui.GetComponent<GUIText>().material.color = warning;
break;
case "error": gui.GetComponent<GUIText>().material.color = error;
break;
}
//now set the text for this element
gui.GetComponent<GUIText>().text = (string)messages[x];
//increment and loop
x += 1;
}
}
}
}
}// End DebugConsole Class

Categories