A pause menu using a button and click - c#

I'd like to know how I can pause and unpause menu from the same button using the mouse pointer when I click on it.
Lets say I have this. C#
void Update () {
if (Button_Pause.OnPointerClick()) {
if(!active){
PauseGame();
}
else{
ResumeGame();
}
active = !active;
}
}
public void PauseGame()
{
Button_Pause = Button_Pause.GetComponent<Button> ();
Canvas_PauseMenu.enabled = true;
Button_Exit.enabled = true;
Button_Pause.enabled = true;
}
public void ResumeGame()
{
Canvas_PauseMenu.enabled = false;
Button_Exit.enabled = false;
Button_Pause.enabled = false;
}
In the first line, where I call the OnPointerClick I'm just guessing because I don't know what to do. What I've searched around, using click to show something it's having a TimeScale or something like that.
¿Can anyone help moi? Please.

Add a listener for your button and in your pause script set timescale to zero to pause the game
[SerializeField] private Button MyButton = null; // assign in the editor
void Start() { MyButton.onClick.AddListener(() => { pause();});
}
void pause(){
if (Time.timeScale == 1)
{
Time.timeScale = 0;
}
else
{
Time.timeScale = 1;
}
}

I managed to solve the issue. It might not be efficient but it does what I need.
I created 2 buttons in the same place. Those buttons are represented with different sprites (Pause & Play). "Pause" is visible since the start. When I click on it, the menu pops up, the "Pause" stop being active and the "Play" sprite button activates and pops up too. When I click on it, I unpause and goes back to the "Pause" sprite visible in the screen.
void Start () {
Canvas_PauseMenu = Canvas_PauseMenu.GetComponent<Canvas> ();
Button_Pause = Button_Pause.GetComponent<Button> ();
Button_Resume = Button_Resume.GetComponent<Button> ();
Canvas_PauseMenu.enabled = false;
Button_Resume.enabled = false;
Button_Resume.gameObject.SetActive (false);
}
// Update is called once per frame
public void PauseTest () {
if(!active){
PauseGame();
}
else{
ResumeGame();
}
}
public void BackToMainMenu()
{
Application.LoadLevel (0);
}
public void PauseGame()
{
Canvas_PauseMenu.enabled = true;
Button_Exit.enabled = true;
Button_Pause.enabled = false;
Button_Pause.gameObject.SetActive (false);
Button_Resume.enabled = true;
Button_Resume.gameObject.SetActive (true);
active = true;
Time.timeScale = 0;
}
public void ResumeGame()
{
Canvas_PauseMenu.enabled = false;
Button_Exit.enabled = false;
Button_Pause.enabled = true;
Button_Pause.gameObject.SetActive (true);
Button_Resume.enabled = false;
Button_Resume.gameObject.SetActive (false);
active = false;
Time.timeScale = 1;
}

Related

Character movement stops on every second "Resume" button press

Im fairly new to Unity and I am trying to make a Pause overlay for my game. Currently Resume does not resume the character movement half of the time. So the first time I pause the game and click resume the overlay is disabled but I will not be able to move, but if I press escape again and then Resume it works fine on the second try. One thing to note is that it works as intended if I press escape while in the pause menu and the logic is exactly the same. Here is my C# script:
public class PauseGame : MonoBehaviour
{
public GameObject Canvas;
bool pausedGame = false;
// Make sure pause screen is not active on game start
void Start()
{
Canvas.GetComponent<Canvas>().enabled = false;
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
if (pausedGame == false)
{
Time.timeScale = 0;
Canvas.GetComponent<Canvas>().enabled = true;
pausedGame = true;
}
else
{
Time.timeScale = 1;
Canvas.GetComponent<Canvas>().enabled = false;
pausedGame = false;
}
}
}
public void Resume()
{
Time.timeScale = 1;
Canvas.GetComponent<Canvas>().enabled = false;
pausedGame = false;
}
public void MainMenu()
{
SceneManager.LoadScene("MainMenu");
}
}
Let me know if I should add screenshots of my components.
Found the solution to this! For some reason the FirstPersonAIO controller did not get unpaused when I resumed the game. Where player is a public variable I added these two lines to my code and it fixed my problem:
controllerScript = player.GetComponent<FirstPersonAIO>();
controllerScript.ControllerPause();

Unity 3d Animation

I m a newbie to Unity3d and was just playing with unity animation, i was trying to implement 2 Main UI Button such as when either of them is pressed it should check the condition whether a animation is already played before by 2nd button available if yes then remove those gameobject from scene using reverse animation else play the default animation attach to the particular button.
Problem is out of 6 case only 4 are getting operational 2 of them are not executing (marked in the code as Case Not Operational)
Animation anim;
private bool isOpen = false;
private bool open = false;
// Start is called before the first frame update
void Start()
{
anim = GetComponent<Animation>();
//isOpen = false;
//open = false;
}
// Update is called once per frame
void Update()
{
}
void OnGUI()
{
isOpen = GUI.Toggle(new Rect(50, 50, 200, 100), isOpen, "IsOpen");
open = GUI.Toggle(new Rect(65, 65, 200, 100), open, "Open");
}
public void ButtonControl()
{
string name = EventSystem.current.currentSelectedGameObject.name;
if (name == "Main Button 1")
{
if (isOpen == false && open == false)
{ Debug.Log("False False 1");
Anim1();
isOpen = true;
}
else if (isOpen == false && open == true) // case not operational
{ Debug.Log("False True 2");
ReverseAnim_2();
open = false;
Anim1();
isOpen = true;
}
else if(isOpen == true)
{
Debug.Log("True 3");
ReverseAnim_1();
isOpen = false;
}
}
else if (name == "Main Button 2")
{
if (open == false && isOpen == false)
{ Debug.Log("False False 4");
Anim2();
open = true;
}
else if(open == false && isOpen == true) // case not operational
{ Debug.Log("False True 5");
ReverseAnim_1();
isOpen = false;
Anim2();
open = true;
}
else if(open == true)
{
Debug.Log("True 6");
ReverseAnim_2();
open = false;
}
}
}
void ReverseAnim_1()
{
anim["1"].speed = -1;
anim["1"].time = anim["1"].length;
anim.Play();
}
void Anim1()
{
anim["1"].speed = 1;
anim.Play();
}
void Anim2()
{
anim["2"].speed = 1;
anim.Play();
}
void ReverseAnim_2()
{
anim["2"].speed = -1;
anim["2"].time = anim["2"].length;
anim.Play();
}
The problem is that you have two Main_B2 scripts and they are each tracking their own values for the isOpen and open fields.
One solution for this could be to make the fields static so that they are in common across all instances of Main_B2.
Animation anim;
private static bool isOpen = false;
private static bool open = false;
If you do this, your code should work as intended - each instance of Main_B2 would then be referring to the same fields whenever they reference isOpen or open.
With that said, static fields can get kind of sloppy if you ever want to try and re-use code so a better option might be to have only one instance of Main_B2 somewhere else such as the Canvas, instead of one on each button.
Then you could have in it public GameObject fields that you can drag the button objects into, and private Animation fields for the animations.:
public GameObject button1
public GameObject button2
private Animation anim1
private Animation anim2
Then in Start:
anim1 = button1.GetComponent<Animation>();
anim2 = button2.GetComponent<Animation>();
And then wherever you referred to anim you would refer to anim1 or anim2 instead:
void ReverseAnim_1()
{
anim1.["1"].speed = -1;
anim1.["1"].time = anim1["1"].length;
anim1.Play();
}
void Anim1()
{
anim1["1"].speed = 1;
anim1.Play();
}
void Anim2()
{
anim2["2"].speed = 1;
anim2.Play();
}
void ReverseAnim_2()
{
anim2["2"].speed = -1;
anim2["2"].time = anim2["2"].length;
anim2.Play();
}
Your scripts 'anim' variable is an Animation. Normally to adjust animation parameters you set them on an Animator, not Animation. But perhaps your solution can work.
For clarity. An animator organizes how animations play out, when, for how long and how they transition.
I would personally advise you to use an animator with behaviour patterns and transitionings between animations. Instead of the current approach.
Either that or use one of the many Tweening asset packs from the asset store. They are specifically made to create UI effects like what you describe.
At least consider these solutions if you keep being stuck :-)

How can I save the playerprefs of a boolean variable?

I am trying to code a mute button, and it works, however the setting of that button is not saved.
public void Mute (){
AudioListener.volume = 0;
sound.enabled = false;
sound.image.enabled = false;
noSound.enabled = true;
noSound.image.enabled = true;
}
public void UnMute (){
AudioListener.volume = 1;
sound.enabled = true;
sound.image.enabled = true;
noSound.enabled = false;
noSound.image.enabled = false;
}
I have 2 methods here, and I need it to save the state of which one was clicked using playerprefs. I was thinking something along the lines of a boolean, but I'm stumped, and and I can't wrap my head around how I would do that.
Yes you can do that with the help of a boolean variable as like the following:
public bool isMuted = false;
public void Do_muteOperation()
{
if (isMuted)
{
UnMute();
isMuted = false;
}
else
{
Mute();
isMuted = true;
}
}

How can I check if the level is loaded in Unity3D

I've started learning C# and Unity3D this year and I've come across a problem. I'm loading a new level and the player object gets initialized before the the level has finished loading.
I think I only need to check whether the level is loaded or not before initializing the object. I don't know if I could use LoadLevelAsync. I'm using Unity3D Personal Edition.
My current code:
MasterClient.cs
void Update(){
if(SceneUpdateRequired)
{
Application.LoadLevel(SceneUpdateID);
if (Application.isLoadingLevel == false)
{
SceneUpdateRequired = false;
SceneUpdateCompleted = true;
}
}
}
void CharacterLoginUpdate(){
if (SceneUpdateCompleted == true)
{
GameObject networkPlayerObj = (GameObject)Instantiate(NPlayerObj, PlayerLoginUpdatePosition, PlayerLoginUpdateRotation);
NPlayer networkPlayer = networkPlayerObj.GetComponent<NPlayer>();
networkPlayer.UpdatePlayerInstantiateCompleted(PlayerLoginUpdateNetworkID, PlayerLoginUpdateHP, PlayerLoginUpdateClass, PlayerLoginUpdateLevel, PlayerLoginUpdateName, PlayerLoginUpdatePosition);
PlayerLoginUpdateRequired = false;
}
}
The problem with your code is your are loading level in update where if you dont control the task with booleans you are going to end up with big problems.
your update code should be as follows
void Update(){
if(SceneUpdateRequired)
{
Application.LoadLevel(SceneUpdateID);
SceneUpdateRequired = false;
}
if (Application.isLoadingLevel == false)
{
SceneUpdateRequired = false;
SceneUpdateCompleted = true;
}
}
This way the scene code will try to load level only when you request it to and not every time in update loop as loading levels is heavy.
Another thing is you might encounter one more problem if you need to use
SceneUpdateRequired,SceneUpdateCompleted variables somewhere else the
if (Application.isLoadingLevel == false)
{
SceneUpdateRequired = false;
SceneUpdateCompleted = true;
}
the above part which is in update loop will reset the variables everytime whenever its not loading the level. To prevent this you will have to introduce another boolean flag to stop its update happening everytime. So your code will end up looking like this if you want to prevent everyframe update
void Update() {
if(SceneUpdateRequired){
Application.LoadLevel(SceneUpdateID);
SceneUpdateRequired = false;
}
if (Application.isLoadingLevel == false && StartCheckingLoadLevel){
SceneUpdateRequired = false;
SceneUpdateCompleted = true;
StartCheckingLoadLevel = false;
}
}
void StartLoad() {
SceneUpdateRequired = true;
SceneUpdateCompleted = false;
StartCheckingLoadLevel = true;
}
void CharacterLoginUpdate(){
if (SceneUpdateCompleted == true) {
Debug.Log("Do Something after load");
} else {
Debug.Log("Scene not yet loaded");
}
}
Hope this helps.

Delete duplicate gameobject on restart

I have the following code which creates a main menu :
public class EscapeGUI : MonoBehaviour {
public GUISkin MySkin;
public bool pauseToggle = false;
public bool showGUI = false;
public bool levelLoaded = false;
static string filePath;
private List<string> list = new List<string>();
private string line;
void Update() {
if (!levelLoaded) {
showGUI = true;
Time.timeScale = 0;
Debug.Log ("NO LEVEL LOADED");
} else {
if (Input.GetKeyDown (KeyCode.Escape)) {
pauseToggle = !pauseToggle;
if (pauseToggle) {
Time.timeScale = 0;
showGUI = true;
} else {
Time.timeScale = 1;
showGUI = false;
}
}
Debug.Log("FILEPATH IS " + filePath);
Debug.Log("LEVEL IS LOADED");
}
}
void OnGUI() {
if (showGUI) {
GUI.skin = MySkin;
GUILayout.BeginArea (new Rect (Screen.width / 4, Screen.height / 4, 400, Screen.width / 2));
GUILayout.BeginHorizontal ();
if (levelLoaded){
if (GUILayout.Button ("Resume")) {
Time.timeScale = 1;
showGUI = false;
pauseToggle = false;
}
}
GUILayout.EndHorizontal ();
GUILayout.BeginHorizontal ();
if (levelLoaded){
if (GUILayout.Button ("Restart")) {
Application.LoadLevel (0);
showGUI = false;
pauseToggle = false;
Time.timeScale = 1;
levelLoaded = true;
Debug.Log ("Game is restarted with this level: " + filePath);
}
}
GUILayout.EndHorizontal ();
GUILayout.BeginHorizontal ();
if (GUILayout.Button ("Load")) {
filePath = EditorUtility.OpenFilePanel("Select JSON file",Application.streamingAssetsPath,"txt");
Debug.Log ("Game is loaded with this level: " + filePath);
StreamReader reader = new StreamReader(filePath);
while ((line = reader.ReadLine()) != null)
{
list.Add(line);
//Debug.Log(line);
}
//Do this as soon as the JSON is checked and found to be OK.
GameObject.Find("Preserved Variables").SendMessage("setFilePath", filePath);
Time.timeScale = 1;
levelLoaded = true;
showGUI = false;
pauseToggle = false;
}
GUILayout.EndHorizontal ();
GUILayout.BeginHorizontal ();
if (GUILayout.Button ("Quit")) {
Application.Quit();
}
GUILayout.EndHorizontal ();
GUILayout.EndArea ();
}
}
}
A game is created by importing a JSON file (in the code its just txt for testing, i have not implemented the JSON part yet), in this JSON file the game flow will be described.
So basically when a player clicks load, I want the game to be playable and then when he clicks restart because of the 'Application.LoadLevel (0);' code everythings gets deleted, thus I don't know anymore what the current file (level) it was.
So I created an empty gameobject called 'Preserved Variables' and I put a C# script component in this, the script looks like this:
public class PreservedVariables : MonoBehaviour {
public string filePath;
public static PreservedVariables instance;
void Awake() {
if(instance){
Destroy(this);
} else {
DontDestroyOnLoad(this);
instance = this;
}
}
void setFilePath(string fp) {
filePath = fp;
}
string getFilePath() {
return filePath;
}
}
Now the problem is that when I run this and ingame i click 'load', i select my file and so far everything is good. But then when I click "restart" I get the following 2 problems:
1) the main menu shows me only the 'load' and 'quit' as it is only supposed to show when there is no game loaded (so this only happens at startup), however i think this will be fixed by fixing nr.2 (see below)
2) As soon as i click restart after loading a file, the gameobject 'Preserved Variables' is made again but this time it does not have a script component attached. (the original gameobject has its FilePath updated correctly though).
If I may I would like to ask an extra small question to this, how do I exactly retrieve the filepath variable again from the empty gameobject 'Preserved Variables' so that I can use it in my restart code?

Categories

Resources