I tried both setting enabled to true and SetActive(true) to diplay a Gameover Image. However, none of them works. I have a public Image gameOverImage declared and set the gameOverImage.enabled in the Start() to false.
private void Start()
{
gameOverImage.enabled = false;
}
Then in one of my function, I put:
public void killAt(Vector2 loc)
{
foreach (GameObject obj in setup.GetActive())
{
if (obj.GetComponent<PieceInfo>().GetLocation() == loc)
{
if (obj.GetComponent<PieceInfo>().GetPieceType() == 'G')
{
gameOver = true;
gameOverImage.enabled = true;
Debug.Log("?????");
}
setup.deactivate(obj);
break;
}
}
}
The console does have ????? logged but no gameOverImage displayed in the game view. The game is over because I couldn't click my game any more. Any ideas? I also tried UI text. It doesn't work as well.
In Unity in order to activate an object you need to have it in the scene. If the GameObject does not exist in the scene, or in your case the UI Element that contains the Image, is not in your scene SetActive(true) or Enabled = true will not have any effect. You will need to instantiate the object. To make it exist in your world.
Prefabs, are useful to store a common configuration that can be used multiple times in your game but they do not exist in the scene, that is why you have to instantiate them.
For your GameOver Image you have a few options the simplest is this:
using UnityEngine;
using UnityEngine.UI;
public class EnableUI : MonoBehaviour {
public Image GameOverImage;
// Use this for initialization
void Start () {
GameOverImage.gameObject.SetActive(false);
}
// Update is called once per frame
void Update () {
if(Input.GetKeyDown(KeyCode.Space))
{
GameOverImage.gameObject.SetActive(true);
}
}
}
If you want to instantiate it:
using UnityEngine;
public class EnableUI : MonoBehaviour {
// This is a prefab that is canvas with your game over image nested as a child image UI under it
public GameObject GameOverObject;
// Use this for initialization
void Start () { }
// Update is called once per frame
void Update () {
if(Input.GetKeyDown(KeyCode.Space))
{
Instantiate(GameOverObject);
}
}
}
Related
I am making Replay logic for my game, where when I click replay I got to the Main Page. The problem I am facing is that after clicking Play on the game after coming from Replay, the Zombie character in my game is not showing up. The game is running without the player. I am posting the script, check the Replay function which is attached to Replay button in the game.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Assertions;
public class GameManager : MonoBehaviour
{
public static GameManager instance = null;
private bool playerActive = false;
private bool gameOver = false;
private bool gameStarted = false;
private GameObject newZombie;
[SerializeField] private GameObject mainMenu; //contains main menu content
[SerializeField] private GameObject endGame; //contains game over content
[SerializeField] private GameObject zombie;
public bool PlayerActive{
get{
return playerActive;
}
}
public bool GameOver{
get{
return gameOver;
}
}
public bool GameStarted{
get{
return gameStarted;
}
}
void Awake()
{
if(instance == null){
instance = this;
}else if(instance != this){
Destroy(gameObject);
}
Assert.IsNotNull(mainMenu);
Assert.IsNotNull(endGame);
DontDestroyOnLoad(gameObject);
}
// Start is called before the first frame update
void Start()
{
endGame.SetActive(false);
mainMenu.SetActive(true);
}
// Update is called once per frame
void Update()
{
}
public void PlayerCollided()
{
gameOver = true;
endGame.SetActive(true);
mainMenu.SetActive(false);
DontDestroyOnLoad(gameObject);
}
public void PlayerStartedGame()
{
playerActive = true;
}
public void EnterGame()
{
endGame.SetActive(false);
mainMenu.SetActive(false);
gameStarted = true;
}
public void Replay()
{
endGame.SetActive(false);
mainMenu.SetActive(true);
gameOver = false;
newZombie = Instantiate(zombie) as GameObject;
}
There are a lot of assumptions we have to make based on the information you gave.
Try instantiating the zombie on a specific location. You're using Instantiate(gameObject), but there's a different variant to the Instantiate method which also takes a Vector3 position to spawn the object as a second argument.
If that doesn't work, please reply with answers to the following questions:
Does the zombie spawn at all (is it in the hierarchy)
Which methods exactly do the buttons invoke, for example:
[1]: https://i.stack.imgur.com/9xbgy.png
You're using a singleton pattern but you don't change scenes in this class. Are you changing scenes in any of your scripts? If yes, you will have to consider looking into them because every script that is persisting between scenes with the DontDestroyOnLoad() method could potentially interfere with your player.
Vlad
I don't know how to reload a scene so that the user can press a key and reset the game. Whenever I do it, the engine just crashes. The game is based on a cat chasing glasses around with a 120-second timer, and each of them has unique abilities. On collision, it should reload the scene. Is there any way that I can do this?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class gamemanager : MonoBehaviour
{
public GameObject catwin;
public GameObject glasseswin;
public timer timer;
public Transform catpos;
public Transform glassespos;
public Vector3 catspawn;
public Vector3 glassesspawn;
public bool gameover = false;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKey("r"))
{
GameReset();
}
}
public void CW()
{
catwin.SetActive(true);
gameover = true;
while (gameover)
{
if (Input.GetKey(KeyCode.R))
{
GameReset();
}
}
}
public void GW()
{
glasseswin.SetActive(true);
if (Input.GetKey("r"))
{
GameReset();
}
}
public void GameReset()
{
catwin.SetActive(false);
glasseswin.SetActive(false);
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
It crashes because the while loop inside the CW method is actually a while (true). When something calls this method it should wait until method is completed, but it'll never happen because of the loop. As a result, the program gets stuck while trying to execute infinitely many commands in one frame, so it has no other choice but to crash.
In order to fix it remove the loop from the method and check whether the key was pressed in Update. Something like this:
if (gameover && Input.GetKey("r"))
GameReset();
You can replace gameover with something else in order to include other conditions
I'm making a new game in Unity and I'm stuck in my script. I'm really noob in C# scripting. I'm already looking for all information but no luck. The game is very simple, it is 2D game where need just click on bubbles and they are rotating when are clicked. I will describe what I exactly need to create. I need a script when all objects are clicked then scene automatically changes to the next level + I need it to have a timeline, for example, for each level have 30 seconds to click all bubbles, when the time is over the game is over and a window pops up with a message "Game Over" and you can press the Reply and Exit buttons. I really hope that someone helps me. Thanks!
P.S. This is my script now for my gameObjects:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class pop : MonoBehaviour
{
public AudioClip sound;
AudioSource audio;
// Start is called before the first frame update
void Start()
{
audio = GetComponent<AudioSource>();
}
// Update is called once per frame
void Update()
{
}
bool wasClicked = false;
private void OnMouseDown()
{
if (!wasClicked)
{
wasClicked = true;
transform.Rotate(0, 0, 180);
audio.PlayOneShot(sound);
}
}
}
You should separate these.
I would have a central manager for the scene change like e.g.
public class Manager : MonoBehaviour
{
[SerializeField] private float timer = 30;
private void Awake ()
{
// Register to an event we will add which is fired everytime
// a pop was clicked
pop.onClicked += PopClicked;
}
private void OnDestroy ()
{
// Don't forget to remove the callback as soon as not needed anymore
pop.onClicked -= PopClicked;
}
private void PopClicked ()
{
// Check if there is no Unclicked pop remaining
if(pop.Unclicked.Count == 0)
{
// if so go to the next scene
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
}
}
private void Update ()
{
// Every Frame reduce the timer by the time passed since the last frame
timer -= Time.deltaTime;
// Maybe also update a timer display text here
if(timer <= 0)
{
// if it reaches 0 -> GameOver scene
SceneManager.LoadScene("GameOver");
}
}
}
And then modify your Pop class accordingly with some additional things:
public class pop : MonoBehaviour
{
// Stores all Unclicked instances
// As this is static it is "shared" between all instances or better said
// it is part of the type itself
private static HashSet<pop> _unclicked = new HashSet<pop>();
// Public readonly access
public static HashSet<pop> Unclicked => new HashSet<pop>(_unclicked);
// Event that is invoked everytime a pop is clicked
public static event Action onClicked;
public AudioClip sound;
[SerializeField] AudioSource audio;
void Awake()
{
if(!audio) audio = GetComponent<AudioSource>();
// Add yourself to the collection of Unclicked instances
_uncliked.Add(this);
}
private void OnDestroy ()
{
// Don't forget to also remove in case this is destroyed
// e.g. due to the scene change to GameOver
if(_unclicked.Contains(this)) _unclicked.Remove(this);
}
private void OnMouseDown()
{
// Is this still Unclicked?
if (!_unclicked.Contains(this)) return;
transform.Rotate(0, 0, 180);
audio.PlayOneShot(sound);
// Remove yourself from the Unclicked instances
_unclicked.Remove(this);
// Invoke the event
onClicked?.Invoke();
}
}
I wanted to add a flashlight to my game. When I press the button to make it disappear, it disappears, but when I press the button to try to make it appear again it doesn't. I've been trying to find the solution for the past hour and a half and looked into the docs too but I didn't find anything.
using System.Collections.Generic;
using UnityEngine;
public class flashlight : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Alpha1))
{
gameObject.SetActive(true);
}
if (Input.GetKeyUp(KeyCode.Alpha2))
{
gameObject.SetActive(false);
}
}
}
The script is being deactivated along with the gameObject so it isn't listening for Input.GetKeyUp(KeyCode.Alpha2).
To get round this create an empty GameObject to hold the script and make the light a child of said GameObject, then when you deactivate the light the script is still active and listening for the Input.
Update the script like this to assign the light child
public class flashlight : MonoBehaviour
{
public GameObject light;//Assign this is the inspector
void Update()
{
if (Input.GetKeyDown(KeyCode.Alpha1))
{
light.SetActive(true);
}
if (Input.GetKeyUp(KeyCode.Alpha2))
{
light.SetActive(false);
}
}
}
How do I set gameobject(myCanvas) to be false during the first play?
I've put this script into the cube, and when I click the cube it will show the Canvas.
I haven't been clicking on the cube but, the canvas has already come out.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class MouseDownText : MonoBehaviour {
public Canvas myCanvas;
void Start()
{
// first start game. gameobject will turn off
myCanvas.gameObject.SetActive(false);
}
void OnMouseDown()
{
// for switch on/off
myCanvas.gameObject.SetActive(!myCanvas.gameObject.activeSelf);
}
}
From what I understand you have a canvas component attached to a game object (a cube) and you want to use mouse clicks to toggle whether or not the canvas is active.
Have you tried:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class MouseDownText : MonoBehaviour {
public Canvas myCanvas;
// Use this for initialization
void Start () {
myCanvas = GetComponent<Canvas> ();
myCanvas.enabled = false;
}
// Update is called once per frame
void Update () {
}
void OnMouseDown()
{
// for switch on/off
if (myCanvas.enabled)
myCanvas.enabled = false;
else
myCanvas.enabled = true;
}
}
Also make sure you haven't accidentally enabled it in some other code somewhere.