in the my code if repeats repeatedly but but it shouldn't be - c#

I press escape, in the debug it says that Pause(), Resum(), Pause() completed. And during the pause, Resum(), Pause(), Resum(), Pause() increase. During the dialogue, I press escape more to turn off the dialogue and still pause. How can I make sure that only one action is performed, and not several different ones? RETURN NOT WORKING
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class PauseMenu : MonoBehaviour
{
public static bool GameIsPaused;
public DialogWindow dialogWindow;
public GameObject pauseMenuUI;
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
if (GameIsPaused)
{
Debug.Log("resume");
Resume();
}
if (DialogWindow.IsDialog)
{
Debug.Log("dialog");
dialogWindow.Close();
}
else
{
Debug.Log("pause");
Pause();
}
}
}
public void Resume()
{
Cursor.lockState = CursorLockMode.Locked;
pauseMenuUI.SetActive(false);
Time.timeScale = 1f;
GameIsPaused = false;
}
public void Pause()
{
Cursor.lockState = CursorLockMode.None;
pauseMenuUI.SetActive(true);
Time.timeScale = 0f;
GameIsPaused = true;
}
public void ToMainMenu(int sceneNumber)
{
SceneManager.LoadScene(sceneNumber);
}
}

Perhaps you could use else if instead of just else, that would eliminate any chance of the different if statements to trigger simultaneously.
if (Input.GetKeyDown(KeyCode.Escape))
{
if (GameIsPaused)
{
Debug.Log("resume");
Resume();
}
else if (DialogWindow.IsDialog)
{
Debug.Log("dialog");
dialogWindow.Close();
}
else
{
Debug.Log("pause");
Pause();
}
}

Related

Unity 2D RPG Healing from Potions

I'm currently developing developing a 2d top-down RPG game in Unity.
I am trying to implement a healing system where you heal some points when you buy a coffee. This is my healthManager:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HealthManager : MonoBehaviour
{
public int maxHealth = 10;
public int currentHealth;
public HealthBarScript healthBar;
void Start()
{
currentHealth = maxHealth;
healthBar.SetMaxHealth(maxHealth);
}
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
TakeDamage(1);
}
}
public void TakeDamage(int damage)
{
currentHealth -= damage;
healthBar.SetHealth(currentHealth);
if(currentHealth <= 0)
{
currentHealth = 0;
}
}
public void heal(int heal)
{
currentHealth += heal;
healthBar.SetHealth(currentHealth);
if(currentHealth >= maxHealth)
{
currentHealth = maxHealth;
}
}
}
And this is the script to buy coffee from a game object (sth. like a healing fountain):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class KaffeeautomatDialog : MonoBehaviour
{
public GameObject dialogBox;
public Text dialogText;
public string dialog;
public bool playerInRange;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if(Input.GetKeyDown(KeyCode.E) && playerInRange)
{
if(dialogBox.activeInHierarchy)
{
dialogBox.SetActive(false);
}
else
{
dialogBox.SetActive(true);
dialogText.text = dialog;
}
}
}
public void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
Debug.Log("Player entered");
playerInRange = true;
var healthManager = other.GetComponent<HealthManager>();
if(Input.GetKeyDown(KeyCode.J) && playerInRange)
{
if(healthManager != null)
{
healthManager.heal(5);
Debug.Log("You healed 5 Points!");
}
}
}
}
public void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
Debug.Log("Player left");
playerInRange = false;
dialogBox.SetActive(false);
}
}
}
The Dialog Box shows up just fine and the Text is displayed. When i am staning in front of the healing fountain, i can activate and deactivate the dialog box by pressing "e".
But when i press "j", i don't heal and the console.log won't appear in Unity.
Did i mess up the Component import?
Checking for an Input it should always happen inside the Update() method and not inside the OnTriggerEnter2D() because the OnTriggerEnter2D() method it will only executed everytime something gets inside the trigger which might happen only onces. On the other hand Update() it will be executed every single frame and check for an Input.
What you can do is the following, inside your OnTriggerEnter2D() method you need to have a global boolean variable that indicates that the player has entered the trigger and inside your Update() method when you check for the Input key "J" you need to check if the above boolean flag is true, if it is true then continue with the heal process. Also you need to make the flag false when the player exit the trigger.
From what I see you already have such flag playerInRange, you can write the following code:
public HealthManager healthManager;
void Update()
{
if(playerInRange)
{
if(Input.GetKeyDown(KeyCode.E))
{
if(dialogBox.activeInHierarchy)
{
dialogBox.SetActive(false);
}
else
{
dialogBox.SetActive(true);
dialogText.text = dialog;
}
}
if(Input.GetKeyDown(KeyCode.E))
{
if(healthManager != null)
{
healthManager.heal(5);
Debug.Log("You healed 5 Points!");
}
}
}
}
public void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
Debug.Log("Player entered");
playerInRange = true;
healthManager = other.GetComponent<HealthManager>();
}
}
Remove the Input check from your OnTriggerEnter2D() method.

I want to enable my collider again after disabling it

When my character hits the gameobject collider, an enemy will be spawned and the collider is disabled, cuz I do not want to spawn multiple enemies. When my character dies and I have to start from the beginning, the collider should be enabled again to spawn the enemy again.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TriggerSpawner : MonoBehaviour
{
public EnemySpawn enemyspawn;
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag("Player"))
{
enemyspawn.SpawnEnemy();
gameObject.GetComponent<BoxCollider2D>().enabled = false;
}
}
}
//in other class
private void SetHealth(float health)
{
var actualNextHealth = Mathf.Min(m_maxHealth, health);
m_currentHealth = actualNextHealth;
if (m_healthBar != null && m_maxHealth > 0f)
m_healthBar.SetHealth(actualNextHealth / m_maxHealth);
if (m_currentHealth <= 0f)
{
UpdateHighscore();
Die();
}
}
private void Die()
{
m_character.NotifyDied();
if (m_canRespawn)
{
SetVulnerable();
RemovePoison();
m_hazards.Clear();
gameObject.transform.position = m_spawnPosition;
SetHealth(m_maxHealth);
}
else {
Destroy(gameObject);
}
}
You can create a static variable in the trigger script that you assign the Collider value to it.
When an enemy is spawned it deactivates, as in your code.
public class TriggerSpawner : MonoBehaviour
{
public static Collider2D spawnCollider;
public EnemySpawn enemyspawn;
void Start() => spawnCollider.GetComponent<Collider2D>();
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.CompareTag("Player"))
{
enemyspawn.SpawnEnemy();
spawnCollider.enabled = false;
}
}
}
When you die, it will reactivate.
private void Die()
{
m_character.NotifyDied();
if (m_canRespawn)
{
TriggerSpawner.spawnCollider.enabled = true;
SetVulnerable();
RemovePoison();
m_hazards.Clear();
gameObject.transform.position = m_spawnPosition;
SetHealth(m_maxHealth);
}
else {
Destroy(gameObject);
}
}
With minimal changes on your code, I'd suggest this:
private void Die()
{
m_character.NotifyDied();
if (m_canRespawn)
{
SetVulnerable();
RemovePoison();
m_hazards.Clear();
gameObject.transform.position = m_spawnPosition;
SetHealth(m_maxHealth);
gameObject.GetComponent<BoxCollider2D>().enabled = true; // add this line
}
else {
Destroy(gameObject);
}
}

The scene change script for my unity project is not working, I cant understand why

Here is the code for the same.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class changescene : MonoBehaviour
{
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
if(Input.GetKeyDown(KeyCode.Space))
{
SceneManager.LoadScene(1);
}
}
}
}
Running this with a 3D cube tagged player is not changing scenes and neither showing any errors.
Input.GetKeyDown is only true once per key press and only during a single frame where the key went down.
It is extremely unlikely that you press the key down exactly in the FixedUpdate physics all when the trigger enters your collider!
You want to split your physics / collision detection from user input and rather do e.g.
public class changescene : MonoBehaviour
{
private bool isEntered;
private void OnTriggerExit(Collider other)
{
if (!other.CompareTag("Player")) return;
isEntered = false;
}
private void OnTriggerEnter(Collider other)
{
if (!other.CompareTag("Player")) return;
isEntered = true;
}
private void Update()
{
if(isEntered && Input.GetKeyDown(KeyCode.Space))
{
SceneManager.LoadScene(1);
}
}
}
Or if you want to make it a bit more efficient without an Update method that runs most of time unnecessary you can use a Coroutine like e.g.
public class changescene : MonoBehaviour
{
private void OnTriggerExit(Collider other)
{
if (!other.CompareTag("Player")) return;
StartCoroutine(CheckSpaceRoutine());
}
private void OnTriggerEnter(Collider other)
{
if (!other.CompareTag("Player")) return;
StopAllCoroutines();
}
private IEnumerator CheckSpaceRoutine()
{
while(true)
{
if(Input.GetKeyDown(KeyCode.Space))
{
SceneManager.LoadScene(1);
yield break;
}
yield return null;
}
}
}

Trying to add select button on my controller to open pause menu

So i tryied to add the select button on controller to my script so i can access it with a controller but I don't under stand how because I'm new to coding and if you can explain that would be great.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PauseMenu : MonoBehaviour{
public static bool GameIsPaused = false;
public GameObject pauseMenuUI;
private bool pauseEnabled;
void Update() {
if (Input.GetKeyDown(KeyCode.Escape))
{
if (GameIsPaused)
{
Resume();
}else
{
Pause();
}
}
}
void Resume()
{
pauseMenuUI.SetActive(false);
Time.timeScale = 1f;
GameIsPaused = false;
}
void Pause()
{
pauseMenuUI.SetActive(true);
Time.timeScale = 0f;
GameIsPaused = true;
}
}
First you have to know which button ID's of gamepad/ joystick. I prefer using this package for getting the button ID's of any new gamepad/ joystick. And then by getting the ID's you have to modify the Input Manager if required and call the function, like for example
if(Input.GetKey(KeyCode.Joystick1Button10)){
// do something
}

Pause sounds and background music in Unity

I am making a Pause menu in Unity that appears when you press escape. But whenever I press escape, the background music still plays. I am getting an error in lines 32 and 46.
The error log is Assets\PauseMenu.cs(32,32): error CS0029: Cannot implicitly convert type 'UnityEngine.AudioSource' to 'UnityEngine.AudioSource[]'
Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PauseMenu : MonoBehaviour
{
public static bool GameIsPaused = false;
public GameObject pauseMenuUI;
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
if (GameIsPaused)
{
Resume();
}
else
{
Pause();
}
}
}
void Resume()
{
pauseMenuUI.SetActive(false);
Time.timeScale = 1f;
GameIsPaused = false;
AudioSource[] audios = FindObjectOfType<AudioSource>();
foreach (AudioSource a in audios)
{
a.Play();
}
}
void Pause()
{
pauseMenuUI.SetActive(true);
Time.timeScale = 0f;
GameIsPaused = true;
AudioSource[] audios = FindObjectOfType<AudioSource>();
foreach (AudioSource a in audios)
{
a.Pause();
}
}
}
FindObjectOfType<AudioSource>() return only one object to return an array of object use FindObjectsOfType<AudioSource>()

Categories