Unity PauseMenu doesn't work in second level - c#

I am making a pause menu for my game. In level1 my pause menu works, but in level2 if you press esc it appears but the buttons aren't interactive for some reason. I copied the canvas from level.
public class PauseMenu : MonoBehaviour {
public string levelSelect;
public string mainMenu;
public bool isPaused;
public GameObject pauseMenuCanvas;
void Start (){
}
void Update () {
if(isPaused)
{
pauseMenuCanvas.SetActive(true);
Time.timeScale = 0f;
} else {
pauseMenuCanvas.SetActive(false);
Time.timeScale = 1f;
}
if(Input.GetKeyDown(KeyCode.Escape))
{
isPaused = !isPaused;
}
}
public void Resume()
{
isPaused = false;
}
public void LevelSelect()
{
Application.LoadLevel(levelSelect);
}
public void Quit()
{
Application.LoadLevel(mainMenu);
}
}

You need to add EventSystem
The EventSystem allows you to interact with buttons

Related

Why is my code constantly setting a variable to "true"?

I have opened the unity(2021.3.7f1) first person module, and tried to add an attack animation to it. I have discovered that my code as soon as it takes 1 input(click), it keeps taking that input. The "isAttacking" variable, keeps being set to "true", even when the player is not clicking. The debug there is how I have figured out this problem.
I cannot for the life of me figure out why this is happening, please help.
Under StarterAssets
public class StarterAssetsInputs : MonoBehaviour
{
[Header("Character Input Values")]
public Vector2 move;
public Vector2 look;
public bool jump;
public bool sprint;
[Header("Movement Settings")]
public bool analogMovement;
[Header("Mouse Cursor Settings")]
public bool cursorLocked = true;
public bool cursorInputForLook = true;
// I added this in vv
public bool attack = false;
#if ENABLE_INPUT_SYSTEM && STARTER_ASSETS_PACKAGES_CHECKED
public void OnMove(InputValue value)
{
MoveInput(value.Get<Vector2>());
}
public void OnLook(InputValue value)
{
if(cursorInputForLook)
{
LookInput(value.Get<Vector2>());
}
}
public void OnJump(InputValue value)
{
JumpInput(value.isPressed);
}
public void OnSprint(InputValue value)
{
SprintInput(value.isPressed);
}
// I added this in vv
public void OnAttack(InputValue value)
{
AttackInput(value.isPressed);
}
#endif
public void MoveInput(Vector2 newMoveDirection)
{
move = newMoveDirection;
}
public void LookInput(Vector2 newLookDirection)
{
look = newLookDirection;
}
public void JumpInput(bool newJumpState)
{
jump = newJumpState;
}
public void SprintInput(bool newSprintState)
{
sprint = newSprintState;
}
private void OnApplicationFocus(bool hasFocus)
{
SetCursorState(cursorLocked);
}
private void SetCursorState(bool newState)
{
Cursor.lockState = newState ? CursorLockMode.Locked : CursorLockMode.None;
}
// I added this in vv
private void AttackInput(bool newAttack)
{
attack = newAttack;
}
}
}
Under first-person controller
private void Attack()
{
if (_input.attack)
{
Debug.Log("Debug " + debugNR);
debugNR++;
WeaponController attackState = weapon.GetComponent<WeaponController>();
attackState.isAttacking = true;
}
}
Under weapon controller
public class WeaponController : MonoBehaviour
{
public Animator animator;
public bool isAttacking = false;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
animator.SetBool("Attack", isAttacking);
}
public void Attack()
{
isAttacking = false;
animator.SetBool("Attack", isAttacking);
}
}
Thanks in advance for the help
_input.attack must be set to false, as part of the attack function in the first person controller
The function was changed from:
private void Attack()
{
if (_input.attack)
{
Debug.Log("Debug " + debugNR);
debugNR++;
WeaponController attackState = weapon.GetComponent<WeaponController>();
attackState.isAttacking = true;
}
}
To:
private void Attack()
{
if (_input.attack)
{
Debug.Log("Debug " + debugNR);
debugNR++;
WeaponController attackState = weapon.GetComponent<WeaponController>();
attackState.isAttacking = true;
_input.attack = false;
}
}

Music player in c# unity doesn't work with other scenes

Okay, so I have a toggle button, which controlls the music volume. And it works fine, but when i go to an other scene, and go back - the toggle doesn't work(doesn't change music volume). Here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Music : MonoBehaviour
{
AudioSource audioSource;
private float volume = 1f;
Toggle toggle;
private void Awake()
{
SetMusicSingletone();
}
private void Start()
{
audioSource = GetComponent<AudioSource>();
toggle = FindObjectOfType<Toggle>();
}
private void Update()
{
audioSource.volume = this.volume;
}
public void ToggleMusic()
{
if (!toggle.isOn)
{
this.volume = 0f;
}
else if (toggle.isOn)
{
this.volume = 1f;
}
}
private void SetMusicSingletone()
{
var music = FindObjectsOfType<Music>();
if (music.Length > 1)
{
Destroy(gameObject);
}
else
{
DontDestroyOnLoad(gameObject);
}
}
}
The toggle uses method ToggleMusic()
Alright so the problem is: You have referenced the ToggleMusic method from this instance of Music in your toggle .. then you change scenes and come back .. but due to the singleton thing you destroy the Music instance linked to this new Toggle -> Toggle does nothing now.
You already have a singleton pattern so why not directly make use of it:
public class Music : MonoBehaviour
{
private static Music _singleton;
public static Music Singleton => _singleton;
[SerializeField] private AudioSource audioSource;
private bool volumeOn;
public bool MusicIsOn => volumeOn;
private void Awake()
{
if (_singleton)
{
Destroy(gameObject);
return;
}
DontDestroyOnLoad(gameObject);
_singleton = this;
if(!audioSource) audioSource = GetComponent<AudioSource>();
ToggleMusic(true);
}
public void ToggleMusic(bool on)
{
audioSource.volume = on ? 1f : 0f;
volumeOn = on;
}
public void ToggleMusic()
{
ToggleMusic(!volumeOn);
}
}
And then on your toggle instead of assigning a callback via the Inspector rather do
public class MusicToggle : MonoBehaviour
{
[SerializeField] private Toggle toggle;
private void Awake ()
{
if(!toggle) toggle = GetComponent<Toggle>();
toggle.onValueChanged.AddListener(OnValueChanged);
toggle.isOn = Music.Singleton.MusicIsOn;
}
private void OnValueChanged (bool on)
{
Music.Singleton.ToggleMusic(on);
}
}

Music is not getting stop when scene reload in unity

I am using a toggle button to play and stop music and I am using playerPrefs to save the state. Toggle button is playing or stopping the music but when I reload the scene It gets messed up. Music keeps playing even if the toggle button is on(Means set the music off).
For the player Prefs. I am using Player prefs Manager script:
public static void SetMusicOnOFF(int value)
{
PlayerPrefs.SetInt(Music, value);
}
public static int GetMusicOnOff()
{
return PlayerPrefs.GetInt(Music, 5);
}
For the toggle button I am using:
class MusicToggleButton : MonoBehaviour
{
Toggle t;
// Use this for initialization
void Start ()
{
t = GetComponent<Toggle>();
if (PlayerPrefsManager.GetMusicOnOff() == 1)
{ //ERROR CALLING THE METHOD TO CHANGE MUSIC TO ON
t.isOn = true;
}
}
When the toggle button is pressed I am calling StartStopMusicPlayer method:
class MusicPlayer : MonoBehaviour
{
public static bool stopPlayer;
// Use this for initialization
void Awake ()
{
if (PlayerPrefsManager.GetMusicOnOff() == 2)
{
audioSource.Play();
audioSource.playOnAwake = true;
audioSource.loop = true;
}
else
{
audioSource.Stop();
}
}
public void StartStopMusicPlayer()
{
stopPlayer = !stopPlayer;
if (stopPlayer)
{
PlayerPrefsManager.SetMusicOnOFF(1);
audioSource.Stop();
}
else
{
PlayerPrefsManager.SetMusicOnOFF(2);
audioSource.Play();
}
}
}
Music Player Class is not destroying on reload. But the MusicToggleButton class is destroyed on reload.
Thank you for your help.
Calling PlayerPrefs.SetInt(Music, value) is not enough. You should call PlayerPrefs.Save() after that. Or your changes will not take effect after restart.
public static void SetMusicOnOFF(int value)
{
PlayerPrefs.SetInt(Music, value);
PlayerPrefs.Save();
}
Solution was so simple. If anyone want to know. Just change the toggle button with normal button. and Inside the MusicToggleButton class.
public class MusicToggleButton : MonoBehaviour
{
public Image offOnImage;
public bool changeValue;
public Color TargetColor;
public Color originalColor;
// Use this for initialization
void Start ()
{
changeValue = !(PlayerPrefsManager.GetMusicOnOff() == 1);
if (PlayerPrefsManager.GetMusicOnOff() == 1)
{
Debug.Log("stop Music");
offOnImage.color = TargetColor;
}
else
{
Debug.Log("Playing Music");
offOnImage.color = originalColor;
}
}
public void musicButtonClick()
{
changeValue = !changeValue;
if (changeValue)
{
//Debug.Log("changing to target color");
//offOnImage.CrossFadeColor(TargetColor, 0.5f, false, false);
offOnImage.color = originalColor;
Debug.Log("Playing");
}
else
{
//Debug.Log("changing to original color");
//offOnImage.CrossFadeColor(Color.white, 0.5f, false, false);
Debug.Log("pause");
offOnImage.color = TargetColor;
}
}
}
This will do Play and pause music. Act like a toggle button.

Disable instantiate and button click

There is issue that i facing with two objects and one button. One is cube second is ground when we click on button cube is collide with ground destroy and instantiate again. On Cube collision score is decrement.Also in hierarchy there is Empty game object which name is controller which has method of text score.Score is working fine but i want that when score is 0 then button click does not work and cube is not instantiate.
Cube :
Ground :
Controller :
CubeScript:
public class Cube : MonoBehaviour {
Rigidbody2D body;
void Start () {
body = GetComponent<Rigidbody2D>();
body.isKinematic = true;
}
}
Ground Script:
public class Ground : MonoBehaviour {
private Button button;
private BoxCollider2D collide;
public GameObject object1Clone;
void Start () {
collide = GetComponent<BoxCollider2D>();
collide.isTrigger = true;
button = GameObject.FindGameObjectWithTag ("Button").GetComponent<Button> ();
button.onClick.AddListener (() => Magnetic ());
}
void OnTriggerEnter2D(Collider2D target) {
Destroy (target.gameObject);
Instantiate (object1Clone, new Vector3 (0f, 4.12f, 0f), Quaternion.identity);
}
public void Magnetic(){
GameObject.FindGameObjectWithTag ("Player").GetComponent<Rigidbody2D> ().isKinematic = false;
}
}
ScoreScript:
public class ScoreScript : MonoBehaviour {
public static int Score=1;
void OnTriggerEnter2D(Collider2D target) {
if (Score <=0) {
} else {
Score--;
Controller.instance.SetScore(Score);
}
}
}
Controller:
public class Controller : MonoBehaviour {
public static Controller instance;
public Text scoreText;
void Start () {
scoreText.text = ""+1;
if(instance==null){
instance=this;
}
}
public void SetScore(int score){
scoreText.text =""+score;
}
}
First change the listener registration to this:
button.onClick.AddListener (Magnetic);
this will make it easier to remove the listener.
I will show you two ways of doing it, an easy one and a proper one a bit harder to grasp. So if you don't quite get it, use the first and learn about the second.
Every time you decrease the score, check for it and call for the appropriate action:
public class ScoreScript : MonoBehaviour {
public static int Score=1;
void OnTriggerEnter2D(Collider2D target)
{
Score--;
Controller.instance.SetScore(Score);
if(Score <= 0){
GameObject.Find("ground").GetComponent<Ground>().ClearButtonListener();
}
}
}
And in the Ground component:
public void ClearButtonListener()
{
button.onClick.RemoveListener (Magnetic);
}
Now the second more appropriate way would be to use event and listener
public class ScoreScript : MonoBehaviour, IScoreHandler {
public static int Score=1;
public event Action OnScoreZero = () => {};
void OnTriggerEnter2D(Collider2D target)
{
Score--;
Controller.instance.SetScore(Score);
if(Score <= 0){
OnScoreZero();
}
}
}
public interface IScoreHandler{ event Action OnScoreZero; }
And your listeners listens.
public class Ground : MonoBehaviour {
private Button button;
private BoxCollider2D collide;
public GameObject object1Clone;
private IScoreHandler scoreHandler = null;
void Start () {
scoreHandler = GameObject.Find("Score").GetComponent<IScoreHandler>();
if(scoreHandler != null){
scoreHandler.OnScoreZero += ClearButtonListener;
}
collide = GetComponent<BoxCollider2D>();
collide.isTrigger = true;
button = GameObject.FindGameObjectWithTag ("Button").GetComponent<Button> ();
button.onClick.AddListener (Magnetic);
}
void OnDestroy(){
if(scoreHandler != null){
scoreHandler.OnScoreZero -= ClearButtonListener;
}
}
}
Thanks to interface and event, your class is no more relying on another class but on an interface which makes it more flexible and scalable.
You need to set the field interactable of the UnityEngine.UI.Button object to false, see http://docs.unity3d.com/ScriptReference/UI.Button.html, i.e. use
void OnTriggerEnter2D(Collider2D target) {
if (Score <=0) {
/* disable the button */
GameObject.FindGameObjectWithTag ("Button").GetComponent<Button>().interactable = false;
}
in your ScoreScript.cs.

How to get animation to play multiple times in Unity?

I want to get a sprite to play an animation of a drop of liquid falling every time that it is clicked, however the animation only plays the first time I click it and I have no idea why.
Here is the code used on the sprite:
public class PipetteScript : MonoBehaviour {
public Animator pipetteAnim;
public BoxCollider2D pipetteMove;
public IndicatorScript indicator;
// Use this for initialization
void Start () {
pipetteAnim.enabled = true;
pipetteMove.enabled = true;
indicator.enabled = true;
}
void OnMouseDown () {
pipetteAnim.Play ("Pipette_dropping");
Debug.Log ("Anim playing");
}
}
The debug log even prints out "Anim playing" every time I click on the sprite.
Use animation in Update function and Let me update
public class PipetteScript : MonoBehaviour {
public Animator pipetteAnim;
public BoxCollider2D pipetteMove;
public IndicatorScript indicator;
public bool boolval = false;
// Use this for initialization
void Start () {
pipetteAnim.enabled = true;
pipetteMove.enabled = true;
indicator.enabled = true;
}
void update()
{
if(boolval == true)
pipetteAnim.Play ("Pipette_dropping");
if(boolval == false)
pipetteAnim.Stop ("Pipette_dropping");
}
void OnMouseDown () {
boolval = True;
}
void OnMouseUp () {
boolval = False;
}

Categories