I have a options menu on 1 scene but when you load into the game (Switch scene) then come back (Switch scene) it loses all the settings. I was trying to do it with DontDestroyOnLoad and could not get it to work an i could not figure out how to read and write a text file. What is the best way to keep all the settings?
Image: Here
In Unity, you can save and load settings via the PlayerPrefs class. This is a static class which means you can access settings anywhere in your Unity script files.
Example usage:
// Set the player name preference
PlayerPrefs.SetString("player_name", "Darian Benam");
// Save all the preferences
PlayerPrefs.Save();
// Load the player name from the preferences
string playerName = PlayerPrefs.GetString("player_name"); // According to this example, the value of the string will be "Darian Benam"
Reloading the settings in the menu scene will need to be done in the Start() method of your script. You will just need to set the values of your GUI components to the return value of the getter methods in the PlayerPrefs class.
Related
Hello!
I'm making a game and I want to add a tutorial(walkthrough) at the beginning of the game.
So, I created a scene where I have all the information and now I just want to show it once after the game was launched and never show it again.
I have already search on the internet for the information. I only found some info about PlayerPrefs and I don't really know how to use it.
Thank you for your time!
You can set variable in PlayerPrefs like this:
PlayerPrefs.SetInt("IsFirstRun", 1);
and then you can check if the variable exists:
if(PleyerPrefs.HasKey("IsFirstRun")) // show the scene
This is how your script would look:
void Start()
{
if(!PleyerPrefs.HasKey("IsFirstRun"))
{
// open scene
PlayerPrefs.SetInt("IsFirstRun", 1);
}
}
I have the following GUI:
As can be seen - this dialog has a title and two buttons.
The dialog title is label that i control using a property in a Dialog script, and the buttons are represented as OptionsButton.
What I want to do is to control these values from scripts, so if I set the title from the inspector - it'll be visible in editor mode and in play mode as initial value. Same deal goes to the texture - so if I'll set the texture from the inspector (not with Unity built-in inspector field but in my custom field) - it'll update both editor and play mode.
Lets take a better example with the title: for the title, I have the following property:
[TabGroup("Game Objects")]
[Required]
public GameObject dialogTitleObject;
/// <summary>
/// Gets or sets the dialog title.
/// </summary>
/// <value>The dialog title.</value>
public string Title
{
get { return this.dialogTitleObject.GetComponent<UILabel>().text; }
set { this.dialogTitleObject.GetComponent<UILabel>().text = value; }
}
So, at runtime I do able to modify this value successfully. However - I want to have the following inspector:
And it should be able to modify the value in the Editor Mode (not in Play Mode) the value will be modified accordingly.
Right now I can't do such thing and even if i type in the inspector textbox - nothing will happen.
Thanks for any help!
So, after few days of reading and tweaking, I came to the solution I posted in this public gist: https://gist.github.com/YahavGB/dea6289a9bd6e6fba82885abbd8da820 .
Basically, I've used a getter and setter methods instead of actual C# properties. Then I created a drawer that sync between the field and the methods.
Finally, to make sure i dont add extra fields, as I just needed to "forward" the call, and not to actually add another variable, I added a macro check for UNITY_EDITOR. Thus I do add another field ( :( ) but just in the editor and not in the actual production game.
I hope this solution will aid someone in the future.
So basic you need build a Custom Inspector
https://unity3d.com/learn/tutorials/topics/interface-essentials/building-custom-inspector
This will bind unity to variable.
I'm Working on a game, and i want to create a mute button. So i wrote a script for that and i attach this script into a gameObject that don't destroy on load.
I link the script with a UI Button present in a main menu. This UI button is destroy when i'm changing scenes.
when i start my game, and i click on the button, the audio turns off, and when i click back, it turns on.
But when i change to another scene, and i go back to the main menu, my script doesn't have the UI Button attach to it. so when i touch the button the audio doesn't change is behavior
I would like to know if it's possible to maintain the link between the UI Button and the script (attach to a normal GameObject), even if the UI Button is destroyed?
i tried this:
ButtonGameObject = GameObject.Find("UI Button");
but it doesn't work.
How can i fix that?
Thanks a lot.
There are many ways to work around this, but here's one:
Step 1: If you haven't already done so, implement a weak singleton pattern on your mute script (let's call it MuteScript.cs for now).
private static MuteScript singleton {get; private set;}
private void Awake() {
if (singleton == null) singleton = this;
[whatever other stuff you were already doing in Awake()]
}
public static void ToggleMute(Graphic graphic)
{
singleton._ToggleMute(graphic);
}
private void _ToggleMute(Graphic graphic)
{
[whatever code you were running in your original mute method]
}
Step 2: Attach a simple script to your UI button:
public class MuteButton: MonoBehaviour
{
Graphic myGraphic;
private void Awake() {
myGraphic = GetComponent<Graphic>();
}
public void OnClick() {
MuteScript.ToggleMute(myGraphic);
//I assume you want to do something like change the colour of the button when
//the player toggles it. Passing the Graphic to the MuteScript is the easiest
//way of doing this. If you really want to keep your code clean, though,
//I recommend expanding the MuteButton class with methods to take care of
//the UI side of things.
}
}
Step 3: In Unity Editor, setup your button to call its own OnClick() method, not the MuteScript method.
-
Now when you click the button, it will call the static MuteScript.ToggleMute(), which accesses the static-cached singleton reference, which in turn points back to your original object.
Singletons and static accessors are great for efficiency in Unity because they save you from having to call expensive search functions like FindObjectsOfType(). The only gotcha is that you have to be careful about not having multiple copies of a singleton-class object lying around, especially when using DontDestroyOnLoad().
So a better approach rather than having a script search and grab the component is to use a PlayerPrefs class from Unity. Essentially, it will hold onto all important aspects of the game and auto fill information.
This is a great tool for a lot of user customization aspects of a game. When using this, have a script (sceneController would be a good name) that will run when the scene starts (create a blank object at 0,0,0) and then under void Start() have the script grab the mute/unmute button: GameObject.Find("MuteButton") or (my favorite) give it a tag called MuteButton and run: GameOject.FindWithTag("MuteButton"). Also once you get a link to the button, add a listener to it for when the button is pressed.
Also store the sound manager in a gameController that will be passed throughout the game. This would control the soundManager and have access to that. So sceneManager will also need a reference to gameManager.
Using a script that is just for player preferences (a controller if you will) is a better way to organize and contain any preferences for the users. Just better clarity and separation.
Example
SceneController Object Script
class SceneController {
GameObject muteButton;
void Start() {
muteButton = GameObject.FindWithTag("muteButton");
muteButton.AddListener(muteButtonCheck);
}
void muteButtonClick() {
if (PlayerPrefs.GetInt("playerMute")) {
// If 1 (on)
// Set sound off
PlayerPref.SetInt("playerMute", 0);
} else {
// It's 0 (off)
// Set sound on
PlayerPrefs.SetInt("playerMute", 1);
}
}
}
void OnMouseDown() {
SceneManager.LoadScene ("Scene2");
}
I have tried every conceivable method. The method posted has worked for me using GameObjects with colliders. Instead, this time I am using a button on a 2D canvas. It does not work in this context.
How do I load a new scene using a button in a canvas? I have tried so many different things. This should be simple.
Thanks for any advice.
Here (link: Unity page) you can find a video tutorial how to use Button on canvas in UnityGUI. It's for Unity 4.6 but its really simillar to newest (5.3.1).
It's quite simple. U can make a script with public method e.g
public void LoadScene2()
{
SceneManager.LoadScene ("Scene2");
}
Attach this script to some GameObject e.g Controller. And add event in Button inspector.
In my opinion there is a better solution for the one shown by #Paweł Marecki
I use this in my projects.
OK so you will simply create a script called ButtonManager and inside it you can make a method like this
public void ChangeToScene(string sceneName)
{
Application.LoadLevel(sceneName);
OR
SceneManager.LoadScene(sceneName);
}
Now you have your canvas button, you will select it and look for "Event Trigger"
(i got this image from google to help) add a new mouse down event.
Create an empty GameObject on your Scene, name it "ButtonManager" and drag it onto the event box.
Now you need to click that dropDown list and find your "ChangeToScene" method.
You will see that an editor field appears below, type your desired scene name and hit play :P
This way you will always use this script when you want to change scenes.
You can add other methods and add functionality, but the beautiful part is that you dont need to create a method each time the name of the scene changes.
I've created a custom window with a range of buttons. When a game objects are selected, and a button is pressed, the myPrefab value of the MyScript component of the selected game objects are set to a particular prefab (according to which button is pressed).
This is working up until the point where I press play. I may have 10 game objects with the MyScript component, and using the buttons set each of them to contain a particular prefab. In the inspector, I can see the prefab value has updated for each of the game objects.
However, as soon as I press the play button, any modifications made by the buttons is undone.
To clarify, if I set the prefab in the inspector, then with a button, it will revert to the one set in the inspector. If I simply set it by the inspector, it won't revert. If it is by default null, and only set by the buttons, it will revert to null. (Only the button results are being reverted).
Could anyone work out why this is the case? Is there some sort of confirm or save method I should be calling to "lock in" my choice?
Simply add "EditorUtility.SetDirty(component);" after the value is modified.
This marks the object as needing to be stored (instead of simply being the value shown in the editor).
In the inspector, things are marked as dirty as soon as you change them. Changing them through other editors like this however, means that the the object must manually be marked as dirty.
if (GUI.Button(rectangle, GUIContent.none))
{
foreach (GameObject go in Selection.gameObjects)
{
MyScript component = go.GetComponent<MyScript>();
if (component == null)
continue;
component.myPrefab = firstPrefab;
EditorUtility.SetDirty(component);
}
}