Text variables don't persist in multiple levels - c#

I want to show the player name and the team name in multiple levels. I've created a gameobject with a singleton that calls servidor to load this variables. It works in the first level but not in the others. The gameobject persists but doesn't save the PlayerName and TeamName. How can I get it?
This is my code:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class GlobalControl2 : MonoBehaviour
{
private static GlobalControl2 instance = null;
private Text PlayerName;
private Text TeamName;
void Awake ()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(this.gameObject);
}
else
{
Destroy(this.gameObject);
}
}
public void Start()
{
PlayerName = GameObject.Find ("PlayerName").GetComponent<Text> ();
TeamName = GameObject.Find ("TeamName").GetComponent<Text> ();
new GameSparks.Api.Requests.AccountDetailsRequest ()
.SetDurable(true)
.Send ((response) => {
PlayerName.text = response.DisplayName;
} );
new GameSparks.Api.Requests.GetMyTeamsRequest()
.SetDurable(true)
.Send(teamResp => {
if(!teamResp.HasErrors)
{
foreach(var teams in teamResp.Teams)
{
Debug.Log("Equipo: " + teams.TeamId);
TeamName.text = teams.TeamId;
}
}
} );
}
}

Currently you are trying to persist Scene specific objects over multiple scenes
The data type "Text" is a unity object.
Try using "String" instead, in the example bellow you will see that PersistentPlayerName and PersistentTeamName will be available in the next scene and PlayerName and TeamName will not. This is always the risk that multi-scene singletons have.
Please do take note, that this should not required if PlayerName and TeamName is on the same gameobject as GlobalControl2 (the one you call DontDestroyOnLoad on)
I am not suggesting that you do it exactly as it is typed bellow, but this should be enough to set you on the right path, if not, add a comment and i will explain further.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class GlobalControl2 : MonoBehaviour
{
private static GlobalControl2 instance = null;
private string PersistentPlayerName;
private string PersistentTeamName;
private Text PlayerName;
private Text TeamName;
void Awake ()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(this.gameObject);
}
else
{
Destroy(this.gameObject);
}
}
public void Start()
{
PlayerName = GameObject.Find ("PlayerName").GetComponent<Text> ();
TeamName = GameObject.Find ("TeamName").GetComponent<Text> ();
new GameSparks.Api.Requests.AccountDetailsRequest ()
.SetDurable(true)
.Send ((response) => {
PlayerName.text = PersistentPlayerName = response.DisplayName;
} );
new GameSparks.Api.Requests.GetMyTeamsRequest()
.SetDurable(true)
.Send(teamResp => {
if(!teamResp.HasErrors)
{
foreach(var teams in teamResp.Teams)
{
Debug.Log("Equipo: " + teams.TeamId);
TeamName.text = PersistentTeamName = teams.TeamId;
}
}
} );
}
}

Related

How do I Clear the discord rich presence in unity

When I close the game I want the discord rich presence to clear but it still show that I'm playing the game, this my discord controller:
using Discord;
using UnityEngine;
using UnityEngine.SceneManagement;
public class DiscordController : MonoBehaviour
{
public long applicationID;
[Space]
public string details = "Walking around the world";
public string state = "Current velocity: ";
[Space]
public string largeImage = "game_logo";
public string largeText = "Discord Tutorial";
private long time;
private static bool instanceExists;
public Discord.Discord discord;
Scene scene;
void Awake()
{
// Transition the GameObject between scenes, destroy any duplicates
if (!instanceExists)
{
instanceExists = true;
DontDestroyOnLoad(gameObject);
}
else if (FindObjectsOfType(GetType()).Length > 1)
{
Destroy(gameObject);
}
}
void Start()
{
// Log in with the Application ID
discord = new Discord.Discord(applicationID, (System.UInt64)Discord.CreateFlags.NoRequireDiscord);
time = System.DateTimeOffset.Now.ToUnixTimeMilliseconds();
UpdateStatus();
}
void Update()
{
scene = SceneManager.GetActiveScene();
// Destroy the GameObject if Discord isn't running
try
{
discord.RunCallbacks();
}
catch
{
Destroy(gameObject);
}
}
void LateUpdate()
{
UpdateStatus();
}
void UpdateStatus()
{
// Update Status every frame
try
{
var activityManager = discord.GetActivityManager();
var activity = new Discord.Activity
{
Details = details,
State = state + scene.name,
Assets =
{
LargeImage = largeImage,
LargeText = largeText
},
Timestamps =
{
Start = time
}
};
activityManager.UpdateActivity(activity, (res) =>
{
if (res != Discord.Result.Ok) Debug.LogWarning("Failed connecting to Discord!");
});
}
catch
{
// If updating the status fails, Destroy the GameObject
Destroy(gameObject);
}
}
}
After I leave the game it still shows that I'm playing and I couldn't fin anything on youtube about it
Please help me to resolve this issue, I've tried myself but I couldn't fix it
Discord Image
You can use activityManager.ClearActivity() that can be found in the ActivityManager.
This method will return a Discord.Result via callback
Example:
activityManager.ClearActivity((result) =>
{
if (result == Discord.Result.Ok)
{
Console.WriteLine("Success!");
}
else
{
Console.WriteLine("Failed");
}
});
More information on this topic can be found here.

I have a script which I have used on two objects and, Rigidbody2d.bodytype changes to static but is not changing back to dynamic for one game object

Here is my script code:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ControlSpike : MonoBehaviour
{
private static ControlSpike _instance = null;
public static ControlSpike Instance { get { return _instance; } }
public Rigidbody2D spikeBody;
public void Awake()
{
_instance = null;
if (_instance != null && _instance != this)
{
}
else
{
_instance = this;
}
spikeBody.bodyType = RigidbodyType2D.Static;
}
// Start is called before the first frame update
void Start()
{
spikeBody.bodyType = RigidbodyType2D.Static;
}
// Update is called once per frame
void Update()
{
}
public void DropSpikes()
{
if (DrawingManager.Instance.paths.Contains(DrawingManager.Instance.clone) && VehicleSimpleControl._instance.RacePress)
{
spikeBody.bodyType = RigidbodyType2D.Dynamic;
spikeBody.gravityScale = 10f;
}
}
}
The rigidbody.body type changes bodytype of one gameobject to dynamic but doesnt change the bodytype of the second gameobject to dynamic. Both get changed to static though. What could be wrong?
Thanks in Advance!
So, I created a manager for this in which I created two rigidbodies references. I passed the references of my objects in this manager and it worked. Basically, the code is same I just removed the script from the gameobjects and created a manager for them instead.

error CS0103: The name 'playfabManager' does not exist in the current context

I just started using Unity, to make a small game called flappy duck.
I wanne have an online leaderboard so everyone can beat each others highscore.
I stumbled on this error Assets\scripts\PlayerController.cs(65,9): error CS0103: The name 'playfabManager' does not exist in the current context
I cand cant find anything wrong. BTW i am using a tutorial
from CoCo Code https://www.youtube.com/watch?v=e2RXDso6fWU&t=266s he uses playfab i am trying to
get this working in my own game.
THIS IS THE SCRIPT THAT MAKES THE TEXT DISPLAY THE HIGHSCORE
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HighSScore : MonoBehaviour
{
public Text HighScore;
// Start is called before the first frame update
void Start()
{
HighScore.text = PlayerPrefs.GetInt("highscore").ToString();
}
}
THIS IS THE PLAYFAB MANAGER
using System.Collections.Generic;
using UnityEngine;
using PlayFab;
using PlayFab.ClientModels;
public class PlayFabManager : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Login();
}
void Login()
{
var request = new LoginWithCustomIDRequest
{
CustomId = SystemInfo.deviceUniqueIdentifier,
CreateAccount = true
};
PlayFabClientAPI.LoginWithCustomID(request, OnSuccess, OnError);
}
void OnSuccess(LoginResult result)
{
Debug.Log("Successful login/account create!");
}
void OnError(PlayFabError error)
{
Debug.Log("Error while logging in/creating account!");
Debug.Log(error.GenerateErrorReport());
}
public void SendLeaderboard(int score)
{
var request = new UpdatePlayerStatisticsRequest
{
Statistics = new List<StatisticUpdate>
{
new StatisticUpdate
{
StatisticName = "score",
Value = score
}
}
};
PlayFabClientAPI.UpdatePlayerStatistics(request, OnLeaderboardUpdate, OnError);
}
void OnLeaderboardUpdate(UpdatePlayerStatisticsResult result)
{
Debug.Log("succsessfull send leaderboard");
}
}`
LAST IS THIS THE PLAYERCONTROLLER
were the error is based on line 65
I am trying to send the highscore to the leaderboard in playfab.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class PlayerController : MonoBehaviour
{
[SerializeField] TextMeshProUGUI scoreText;
Rigidbody2D bird;
int score = 0;
bool dead = false;
int highscore = 0;
// Start is called before the first frame update
void Start()
{
bird = transform.GetComponent<Rigidbody2D>();
}
// Update is called once per frame
public void update ()
{
if (Input.GetKeyDown("space") && !dead)
{
bird.velocity = new Vector2(0, 6f);
}
if (Input.GetKeyDown("r"))
{
SceneManager.LoadSceneAsync(SceneManager.GetActiveScene().buildIndex);
}
if (score > highscore)
{
highscore = score;
SendLeaderboard();
PlayerPrefs.SetInt("highscore", score);
}
}
void OnCollisionEnter2D()
{
dead = true;
score = 0;
scoreText.text = "0";
}
void OnTriggerExit2D(Collider2D col)
{
if (col.gameObject.tag == "PointTrigger")
{
score++;
scoreText.text = score.ToString();
}
}
void OnTriggerExit(Collider col)
{
if (col.gameObject.tag == "PointTrigger")
{
score++;
scoreText.text = score.ToString();
}
}
public void SendLeaderboard()
{
playfabManager.SendLeaderboard(highscore);
}
}
I hope someone can help me.
Most probably in PlayerController you wanted to have a
[SerializeField] private PlayFabManager playfabManager;
and either reference it via the Inspector or at runtime via e.g.
private void Awake ()
{
// Try and get the component if it is attached to the same object as this
if(! playfabManager) playfabManager = GetComponent<PlayFabManager>();
// Or try and find it anywhere in the scene
if(! playfabManager) playfabManager = FindObjectOfType<PlayFabManager>();
// Or simply create and attach it to the same object as this one
if(! playfabManager) playfabManager = gameObject.AddComponent<PlayFabManager>();
}
Or - and in my eyes this would be the more correct solution - the PlayerFabManager should not be a MonoBehaviour at all but rather simply do
public class PlayFabManager
{
public void Login()
{
...
}
...
}
And in PlayerController you'd rather do
private readonly PlayFabManager playfabManager = new PlayFabManager();
private void Start ()
{
playfabManager.Login();
}

Creating a sound manager

This is how I currently have my Sound Manager setup for a small RPG and I was just wondering if this was good practice.
What I was trying to go for was to have my two methods (PlayBGMusic and PlaySound) to be "public static" so I would not have to grab the GameObject by tag and the Script in almost all of my other scripts that want to play a sound. If I do make them "public static" then I would have to make my variables the same which takes away from placing anything in the inspector.
public class Sound_Manager : MonoBehaviour {
// Allow the user to decide if music should be on or off.
public bool backgroundMusicOn;
// Allow the user to decide if sound should be on or off.
public bool soundOn;
// The music volume.
[Range(0,1)]
public float musicVolume;
// The sound volume.
[Range(0,1)]
public float soundVolume;
// The Background music to be used for any manipulations.
private AudioSource _bgMusic;
// Play a background song.
public void PlayBGMusic(AudioSource music){
...
}
// Mute Current Background Song.
public void MuteUnMuteBGMusic(){
....
}
// Play a sound.
public void PlaySound(AudioClip sfx, Vector3 location){
...
}
}
Is this a proper way of handling something like this or is there another way that could be more simple?
I think you can't play BGmusic and sound in one GameObject,because every audio must play whith single audion source,this is my code of AudioManager.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class AudioManager : MonoBehaviour
{
public AudioClip[] audioSources;
public GameObject audioPrefabSource;
public Dictionary<string,AudioClip> audioClips;
static GameObject audioPrefab;
static GameObject instance;
static AudioSource musicPlayer;
public static AudioManager audioManager;
Dictionary<string,Audio> aliveSounds;
AudioListener al;
void Awake ()
{
audioManager = this;
al = GetComponent<AudioListener> ();
audioClips = new Dictionary<string, AudioClip> ();
foreach (AudioClip a in audioSources) {
audioClips.Add (a.name, a);
}
instance = this.gameObject;
audioPrefab = audioPrefabSource;
musicPlayer = audio;
aliveSounds = new Dictionary<string, Audio> ();
//DontDestroyOnLoad(gameObject);
}
void Update ()
{
if (!GameSetting.hasMusic) {
musicPlayer.Pause ();
} else {
if (!musicPlayer.isPlaying) {
musicPlayer.Play ();
}
}
if (!GameSetting.hasSound && aliveSounds.Count > 0) {
foreach (Audio a in aliveSounds.Values) {
a.StopSound ();
}
aliveSounds.Clear ();
}
if (!al.enabled) {
al.enabled = true;
}
}
public static void PlaySoundOnce (string name)
{
if (!GameSetting.hasSound) {
return;
}
if (!audioManager.audioClips.ContainsKey (name)) {
return;
}
GameObject go = GameObject.Instantiate (audioPrefab) as GameObject;
go.transform.parent = instance.transform;
Audio a = go.GetComponent<Audio> ();
a.PlaySoundOnce (audioManager.audioClips [name]);
}
public static void PlayMusic (string name)
{
if (!GameSetting.hasMusic) {
return;
}
if (musicPlayer.clip == null || musicPlayer.clip.name != name) {
// musicPlayer.clip = audioManager.audioClips [name];
musicPlayer.clip = Resources.Load ("Audio/" + name, typeof(AudioClip)) as AudioClip;
musicPlayer.Stop ();
musicPlayer.loop = true;
musicPlayer.Play ();
} else {
musicPlayer.loop = true;
musicPlayer.Play ();
}
}
}
There is another class for Audio,it must be made to a audioprefab.
using UnityEngine;
using System.Collections;
public class Audio : MonoBehaviour
{
public void PlaySoundOnce (AudioClip audioClip)
{
StartCoroutine (PlaySoundCoroutine (audioClip));
}
IEnumerator PlaySoundCoroutine (AudioClip audioClip)
{
audio.PlayOneShot (audioClip);
yield return new WaitForSeconds (audioClip.length);
Destroy (gameObject);
}
public void PlaySoundLoop (AudioClip audioClip)
{
audio.clip = audioClip;
audio.loop = true;
audio.Play ();
}
public void StopSound ()
{
audio.Stop ();
Destroy (gameObject);
}
}
Like this,and I ignored audio's position,I used 2D sound.
I recommend turning the sound manager into a singleton class. In that way you can have all the properties in the inspector and use the singleton object to globally access all your properties, even destroying the gameobject completely when not needed .

Need to a Instantiate a prefab in canvas which is in another scene

I am making an achievement system.I have to 2 scene in my game.The first scene is my Main Menu and the other scene is my game scene. I have designed and coded the achievement system in the main menu scene and added a EarnCanvas to my game scene. EarnCanvas will display the achievement that the player has unlocked.
Code i have is only allowing me to link the achievements to a EarnCanvas on the Main Menu scene.i need help to modifier the code or link the two scene so that i can instantiate the unlocked achievement prefab in the EarnCanvas in the game Scene. At the moment no prefab is instantiated or displayed in the EarnCanvas when the player has unlocked an achievement.
Main Menu scene
achievement Manager script:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
public class AchievementManager : MonoBehaviour {
public GameObject achievementPraf;
public Sprite[] sprites;
private AchievementButton activeButton;
public ScrollRect scrollRect;
public GameObject achievementMenu;
public GameObject visualAchievement;
public Dictionary<string, Achievement> achievements = new Dictionary<string, Achievement>();
public Sprite UnlockedSprite;
private static AchievementManager instance;
public static AchievementManager Instance
{
get {
if(instance == null)
{
instance = GameObject.FindObjectOfType<AchievementManager>();
}
return AchievementManager.instance;
}
}
// Use this for initialization
void Start ()
{
//remove before deploy
//PlayerPrefs.DeleteAll();
activeButton = GameObject.Find("Streakbtn").GetComponent<AchievementButton>();
CreateAchievement("Streak", "Press W", "Press W to unlock this achievement", 5, 0);
CreateAchievement("Streak", "Press R", "Press R to unlock this achievement", 5, 0);
CreateAchievement("Streak", "Press All Keys", "Press All Keys to unlock", 5, 0, new string[] { "Press W", "Press R" });
foreach (GameObject achievementList in GameObject.FindGameObjectsWithTag("achievementList"))
{
achievementList.SetActive(false);
}
activeButton.click();
achievementMenu.SetActive(false);
}
// Update is called once per frame
void Update ()
{
if (Input.GetKeyDown(KeyCode.S))
{
achievementMenu.SetActive(!achievementMenu.activeSelf);
}
if(Input.GetKeyDown(KeyCode.W))
{
EarnAchievemnent("Press W");
}
if (Input.GetKeyDown(KeyCode.R))
{
EarnAchievemnent("Press R");
}
}
public void EarnAchievemnent(string title)
{
if(achievements[title].EarnAchievement())
{
GameObject achievement = (GameObject) Instantiate(visualAchievement);
StartCoroutine(HideAchievement(achievement));
//this is where is its giving the parent the gameobject name to find
SetAchievementInfo("EarnCanvas", achievement, title);
}
}
public IEnumerator HideAchievement(GameObject achievement)
{
yield return new WaitForSeconds(3);
Destroy(achievement);
}
public void CreateAchievement(string parent,string title,string description,int points,int spriteIndex,string[] dependencies = null)
{
GameObject achievement = (GameObject)Instantiate(achievementPraf);
Achievement newAchievement = new Achievement(name, description, points, spriteIndex,achievement);
achievements.Add(title, newAchievement);
SetAchievementInfo(parent, achievement,title);
if(dependencies != null)
{
foreach(string achievementTitle in dependencies)
{
Achievement dependency = achievements[achievementTitle];
dependency.Child = title;
newAchievement.AddDependency(dependency);
//Dependency = Press Space <-- Child = Press W
//NewAchievement = Press W --> Press Space
}
}
}
public void SetAchievementInfo(string parent, GameObject achievement, string title)
{
//this where its trying to find a gameobject-(EarnCanvas) to instantiate the unlocked achievement prefab in the Main Menu Scene
achievement.transform.SetParent(GameObject.Find(parent).transform);
achievement.transform.localScale = new Vector3(1, 1, 1);
achievement.transform.localPosition = new Vector3(0, 0, 0);
achievement.transform.GetChild(0).GetComponent<Text>().text = title;
achievement.transform.GetChild(1).GetComponent<Text>().text = achievements[title].Description;
achievement.transform.GetChild(2).GetComponent<Text>().text = achievements[title].Points.ToString();
achievement.transform.GetChild(3).GetComponent<Image>().sprite = sprites[achievements[title].SprintIndex];
}
public void ChangeCategory(GameObject button)
{
AchievementButton achievementButton = button.GetComponent<AchievementButton>();
scrollRect.content = achievementButton.achievementList.GetComponent<RectTransform>();
achievementButton.click();
activeButton.click();
activeButton = achievementButton;
}
}
Main Menu Scene
Achievement Script:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
public class Achievement
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
private string description;
public string Description
{
get { return description; }
set { description = value; }
}
private bool unlocked;
public bool Unlocked
{
get { return unlocked; }
set { unlocked = value; }
}
private int points;
public int Points
{
get { return points; }
set { points = value; }
}
private int sprintIndex;
public int SprintIndex
{
get { return sprintIndex; }
set { sprintIndex = value; }
}
private GameObject achievementRef;
private List<Achievement> dependencies = new List<Achievement>();
private string child;
public string Child
{
get { return child; }
set { child = value; }
}
public Achievement(string name,string description, int points, int sprintIndex, GameObject achievementRef)
{
this.name = name;
this.description = description;
this.unlocked = false;
this.points = points;
this.sprintIndex = sprintIndex;
this.achievementRef = achievementRef;
LoadAchievement();
}
public void AddDependency(Achievement dependency)
{
dependencies.Add(dependency);
}
public bool EarnAchievement()
{
if(!unlocked && !dependencies.Exists(x=> x.unlocked == false))
{
achievementRef.GetComponent<Image>().sprite = AchievementManager.Instance.UnlockedSprite;
SaveAchievement(true);
if(child != null)
{
AchievementManager.Instance.EarnAchievemnent(child);
}
return true;
}
return false;
}
public void SaveAchievement(bool value)
{
unlocked = value;
PlayerPrefs.SetInt(name,value? 1 : 0);
PlayerPrefs.Save();
}
public void LoadAchievement()
{
unlocked = PlayerPrefs.GetInt(name) == 1 ? true : false;
if (unlocked)
{
achievementRef.GetComponent<Image>().sprite = AchievementManager.Instance.UnlockedSprite;
}
}
}
You should use DontDestroyOnLoad method it is very simple way to retain gameobjects over scene changes you just need to add following code to your AchievementManager.
void Awake ()
{
DontDestroyOnLoad (transform.gameObject);
}
You can add this for any gameObject which you do not want to be destroyed upon changing scene.

Categories

Resources