How to keep selected player active and all others inactive when new scene loaded
Hi all,
I am making a game with interchangeable characters. I am having a problem when a new scene is being loaded. If I select character 3, character 1 and 2 become SetActive=false as I want. However if I finish the first level with character 2 or 3 the second scene loads and it automatically reverts to character 1. I have tried to use DoNotDestroyOnLoad in multiple ways but have failed so far. Is this the correct way to go, or is there another method to check which Character GameObject was last active in the previous scene and to keep it on that GameObject.
My Character Gameobject (tagged "player" in Unity) is also destroyed on the next scene so unsure if that is the cause but have another DoNotDestroyOnLoad script for that.
I have attached both scripts. Thanks for any help/guidance.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SelectShip : MonoBehaviour{
public GameObject FakeButtonBuyShip1;
public GameObject RealButtonBuyShip1;
public GameObject FakeButtonBuyShip2;
public GameObject RealButtonBuyShip2;
public GameObject FakeButtonBuyShip3;
public GameObject RealButtonBuyShip3;
public GameObject Ship1, Ship2, Ship3;
public double currentCurrency;
public double engineValueShip2;
public double engineValueShip3;
public static bool turnOffButton = false;
void Awake(){
DonNotDestroyOnLoad(Ship1);
DonNotDestroyOnLoad(Ship2);
DonNotDestroyOnLoad(Ship3);
}
void Update(){
currentCurrency = GlobalCurrency.CurrencyCount;
engineValueShip2 = BuyEngine2.engineValue;
engineValueShip3 = BuyEngine3.engineValue;
if (currentCurrency < engineValueShip2) {
FakeButtonBuyShip2.SetActive(true);
RealButtonBuyShip2.SetActive(false);
}else{
FakeButtonBuyShip2.SetActive(false);
RealButtonBuyShip2.SetActive(true);
}
if (turnOffButton == true){
RealButtonBuyShip2.SetActive(false);
FakeButtonBuyShip2.SetActive(true);
turnOffButton = false;
}
}
public void ClickTheButton1(){
Ship1.gameObject.SetActive(true);
Ship2.gameObject.SetActive(false);
Ship3.gameObject.SetActive(false);
}
public void ClickTheButton2(){
Ship1.gameObject.SetActive(false);
Ship2.gameObject.SetActive(true);
Ship3.gameObject.SetActive(false);
}
public void ClickTheButton3(){
Ship1.gameObject.SetActive(false);
Ship2.gameObject.SetActive(false);
Ship3.gameObject.SetActive(true);
}
}
//// DoNotDestroyOnLoad//
{
void Awake() {
GameObject[] objects = GameObject.FindGameObjectsWithTag("Player");
if (objects.Length > 3)
Destroy(this.gameObject);
else
Object.DontDestroyOnLoad(this.gameObject);
Answer by RustyCrow · Aug 12, 2019 at 07:17 PM
What you are looking for is a Game manger the unity tutorial isn't the best to understand the concept but hopefully you will get the idea.
its essentially combines stuff that you tried with DontDestroyOnLoad and Global logic, check out Singelton patter (Again not the best example for new people so dont get scared, alot of good youtube vids on game mangers and stuff).
This will allow you to save the "State" of your character since the game manger will continue to the next scene. From here it will depend on your " character state/select system" which might pose a whole different set of issues. So try to understand the game manger first, its a pretty complex issue for new people so, take it 1 step at a time.
Edit: I would also recommend to watching sacredgeometry video on how to save a state in a Scriptable object. Which would save your state even after testing/playing. But since you asked for "on new scene load" this might give you some unwanted results since stuff is saved so just keep that in mind.
But since you asked for "on new scene load" this might give you some unwanted results since stuff is saved so just keep that in $$anonymous$$d.
How so?
Answer by Dawdlebird · Aug 08, 2019 at 10:51 AM
For persistence throughout gameplay I personally like to use static variables (and to some extend static classes, so not to have to rely on instances of these classes or variables, since I need only the one global instance), but having for example a gameobject you keep around using DontDestroyOnLoad should also suffice. Either way; I'd put all those available players in a list or array, and have the static in or some int on your persistent gameobject store the array index of your selected player. From the way you describe your game; have you considered creating a scriptableobject containing a list with all available players and a single integer containing the selected player? Scriptable-objects also live outside the scene and that integer will remain what you set it throughout gameplay. You can easily add new available players to such a list, and it being an asset makes it not rely on being edited inside any scene. Your player select could then just look at that scriptable object and populate the selection menu with all available players in the array for example.
Thanks for your reply. I just wanted to let you know that I am fairly new to Unity so did not understand some bit. I will do some reading into Arrays but from what I understand, I can use an Array of int (say 1-10 for 10 characters) and assign each number to a character Gameobject. Would this help transition between scenes? Thanks
No, not an array of integers. It kind of depends: if your various players are prefabs you can use an array of gameobjects that you fill up with those prefabs. If you use a class (like a player data script) that stores a player name, thumbnail, and such info, you can simply make an array of that class. Scriptable objects are ideal here, because it allows you to just make an asset with this array that then hold reference to all player prefabs (or their player data scripts) so you always have access to this object. Then you could have an int on this same scriptable object that holds your active player index. Whenever you load a new level you just make sure there is a reference to that scriptable object in that level and you check what the active player index is and use that to instantiate the player (or activate it, or whatever system you use) from the array under that index. Does this make sense?
Sorry for being a novice, I am making a clicker/idle game. I will be reading up the things you have mentioned and how to implement them on my way home. I have made a prefab of the player which includes a name and image and as my script above (which is printed as text?) suggests, I used a button to select the player and then this activates that particular Gameobject while deactivating all the others.
From my understanding I guess you are firstly advising that I could create a script with an array of different players and also include in the script differing player attributes such as how much points each player gives per click or automatically (via Coroutine) etc. Secondly use an int system, so somehow int =1 references player 1 index and so on. And then when a new scene is loaded, have a script to check which player was active via the index.
I have read about arrays briefly and with a bit more reading I think I may understand it. Is there a particular topic/method I should read about to use int to make active player indexes.
Thanks again for your help.
I marked you down because this is an anti pattern. It can/ will cause issues if you aren't careful.
If you are going to use static members like this at least use a thread safe singleton pattern.
What am I supposed to write the entire game manager? I didn't implement any static stuff or singleton stuff in there, if you bothered to read the code. I just provided some sample code to point in the direction he could take this. But glad to know taking out an hour of my time to provide such suggestions is not appreciated around here, I'll not make that mistake again. Also; aren't people free to choose whatever pattern they like? Every pattern has risks, and I would assume people read up on the ones they use. Singletons work great for stuff like gamemanagers that need to persist throughout gameplay and of which there should only be one at all times.
I didnt mark you down for the code example I marked you down for your original answer and was letting you know that your singleton class was not a singleton as an aside so na$$anonymous$$g it one is a little confusing for anyone that reads it.
"For persistence throughout gameplay I personally like to use static variables (and to some extend static classes, so not to have to rely on instances of these classes or variables, since I need only the one global instance), "
i.e. thats not a good use for a static class.
I understand @sacredgeometry that you are trying to make sure the right information is presented, but let's not downvote answers that are trying, regardless if the answer is correct or not. This forum is for learning for everyone and I learn a lot because people ask questions for problems I haven't encountered and through figuring out their solution for them, I learn a lot about coding and design patterns, so please understand that if you see a flaw with the logic in an answer, give the constructed feedback but don't downvote, this really isn't that type of egotistical debate fodder forum and I don't think anyone wants that energy here. ---------- I have been on here for about a year and more active in the past couple months, but downvoting a response because it has errors or flaws is rude; this is supposed to be a safe learning environment and I have posted absolute BS in the past and had people with much higher reputation tell me discreetly what I did wrong; downvoting an answer with flaws (or because maybe it isn't the "best" or "most optimal") just makes you look weak and insecure; you can be that 'cool dude (or girl, not sexist)' who helps out OP and other people who post answers rather than try to be the only right one while ostracizing yourself from a harmonious and generally non-hostile community. ---------- One last thing; I get on this forum to pass the time at a call center job I work at, I don't have access to a compiler that has $$anonymous$$onoBehaviour loaded into it and certainly don't have access to Unity at work, so I will post a lot of stuff that isn't tested and using a generic C# compiler mainly for formatting, not for compiling, so I know I put a lot of stuff that is generally right, but might have a syntax error or not return a value on a return methods or have an if statement that is redundant, so consider that not all of us are answering with tools that can provide plug and play solutions, that maybe the OP will have to tweak or learn a little themselves. ---------- At the end of the day, let's keep this forum fun and let's all learn from each other.
I'm sorry but thats the literal use of the down vote. It's there to rank questions and answers based on their objective correctness, presentation etc.
Thats literally how stack style answers websites work. It isn't rude. $$anonymous$$aybe, I would suggest growing a thicker skin if you think that way.
It's not personal and shouldn't be read as personal. It is to stack rank answers to expedite the process of finding useful information. Thats literally all.
Answer by sacredgeometry · Aug 12, 2019 at 05:42 PM
Example:
I will upload a video to show its use
Player Type
public enum PlayerType
{
PlayerType1,
PlayerType2,
PlayerType3
}
Player Component
public class Player : MonoBehaviour
{
public List<GameObject> Prefabs;
private PlayerType _type;
public PlayerType Type
{
get
{
return _type;
}
set
{
var index = (int)_type;
var prefab = Prefabs.ElementAtOrDefault(index);
if(prefab != null)
{
prefab.SetActive(false);
_type = value;
index = (int)_type;
prefab = Prefabs.ElementAtOrDefault(index);
prefab.SetActive(true);
Preferences.Type = _type;
}
}
}
public PlayerPreferences Preferences;
void Awake()
{
Type = Preferences.Type;
}
}
Player Preferences
[CreateAssetMenu(fileName = "PlayerPreferences", menuName = "Custom/PlayerPreferences")]
public class PlayerPreferences : ScriptableObject
{
public PlayerType Type;
}
Thanks for taking the time to write the script and doing a video explanation. I will go through it to try and better understand your script when I am free. Thanks
That's quite alright, you are very welcome.
I have been busy with work so have not had a chance to work on my game in a while. I just wanted to again thank you for that video and the explanation. I really liked the use of Enums and the na$$anonymous$$g system which will help keep track of objects better. I was wondering, if I could link the the change to a button rather than the space button, so I would have 3 buttons each corresponding to one of the colours.