haven't posted on here before but I have been trying for a while to create a game and would like a death/game over sort of scene to appear when the player loses all 3 of their lives. I have a functioning game manager and my player can lose lives (they have 3). This is all being done in unity games and is 2d (idk if that helps). I currently have other stuff in my scene loader script that works fine so I will post the whole thing but I am having issues with the bottom most code!
Thank you!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneLoader : MonoBehaviour
{
public string scenename;
public GameManager GM;
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.tag == "Player")
{
SceneManager.LoadScene(scenename);
}
}
private void Deathscene()
{
if(GM.LifeTotal == 0)
{
SceneManager.LoadScene(Bob);
}
}
}
Gamemanager script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GameManager : MonoBehaviour
{
public int PotionsCollected = 0;
public int LifeTotal = 3;
public Text PotionsOutput;
public Text LifeOutput;
void Update()
{
PotionsOutput.text = "Potions: " + PotionsCollected;
LifeOutput.text = "Life: " + LifeTotal;
}
public void CollectPotion()
{
PotionsCollected++;
}
public void UsePotion()
{
PotionsCollected--;
}
public void LoseLife()
{
LifeTotal--;
}
}
What you can do is from your Unity Editor go to File->Build Settings and then drag and drop inside the active scenes window your death scene.
Then an index will be generated on the right side of the window and you can use that index to load the scene. like this:
SceneManager.LoadScene("Use your generated index");
NOTE: Use your index as a number and not as a string.
UPDATED Solution:
public void LoseLife()
{
LifeTotal--;
if(LifeTotal <= 0)
{
SceneManager.LoadScene("Use your generated index");
}
}
I supposse LoseLife() it's called when the enemy attacks your player.
Related
Hello I'm game developer one day when I want to test my game on android I join to my game but when I press on buttons public void function doesn't work I fixed it by add to scripts what using buttons onClick.AddListener() but one problem IAP don't work with onClick.AddListener() you can help me fix problem with public void function what works on Editor but don't work in Android when I press on buttons. Thanks.
Script with AddListener [This script where I add onClick.AddListener() to fix this problem but it's be uncomfortable thats why I want to fix this]:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class GameButtonManager : MonoBehaviour
{
public GameObject DonationShop;
public GameObject ShopBtn;
public GameObject QuitShopBtn;
public GameObject QuitBtn;
public bool CanPress = true;
void Update()
{
ShopBtn.GetComponent<Button>().onClick.AddListener(EnableShop);
QuitShopBtn.GetComponent<Button>().onClick.AddListener(DisableShop);
QuitBtn.GetComponent<Button>().onClick.AddListener(BackToMenu);
}
public void EnableShop()
{
if(CanPress == true)
{
DonationShop.SetActive(true);
CanPress = false;
StartCoroutine(CanPressEnable());
}
}
public void BackToMenu()
{
SceneManager.LoadScene(1);
}
public IEnumerator CanPressEnable()
{
yield return new WaitForSeconds(5.5f);
CanPress = true;
}
public void DisableShop()
{
if(CanPress == true)
{
DonationShop.SetActive(false);
CanPress = false;
StartCoroutine(CanPressEnable());
}
}
}
I have a game that is similar to "Flappy Bird" and I have main menu where I can start game and change skin of a pigeon. My skin collection is implemented with scroll rect and in the center there is a trigger which starts an animation of scaling a pigeon, it works fine until I click "start" and the scene changes to game and when I return to my main menu and click "skins" this trigger doesn't work anymore.
Script what is attached to all scroll rect elements to detect collisions with trigger:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ResizeFieldScript : MonoBehaviour
{
private Animator _anim;
private void Start()
{
_anim = GetComponent<Animator>();
}
public void OnTriggerEnter2D(Collider2D collider)
{
Debug.Log("Trigger is working");
if(collider.tag == "ResizeField")
{
Debug.Log("Condition is working");
_anim.SetBool("isInTrigger", true);
}
}
public void OnTriggerExit2D(Collider2D collider)
{
_anim.SetBool("isInTrigger", false);
}
}
Script what is attached to an empty object to change scenes:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement;
public class UIController : MonoBehaviour
{
[SerializeField] private List<string> sceneNameList;
private string sceneToFind;
private int index = 0;
public void SceneChanger()
{
sceneToFind = EventSystem.current.currentSelectedGameObject.name;
foreach(string str in sceneNameList)
{
if(str == sceneToFind)
{
SceneManager.LoadScene(index);
index = 0;
break;
}
index++;
}
}
public void Exit()
{
Application.Quit();
}
public void BackMenu()
{
SceneManager.LoadScene(4);
}
}
OnTriggerEnter2D doesn't work after switching scenes. We could use OnTriggerEnter2D to jump scenes.
code show as below:
private void Update() {
// If E is pressed
if (Input. GetKeyDown(KeyCode. E)) {
// scene switching
SceneManager.LoadScene(4);
}
}
private void OnTriggerEnter2D(Collider collision) {
if (collision. tag == "ResizeField") {
// The UI prompts the user to press E to jump
EnterDialog.SetActive(true);
Debug.Log("Condition is working");
// _anim.SetBool("isInTrigger", true);
}
}
Hope it helps you.
Trying to combine these two:
https://answers.unity.com/questions/1171111/hideunhide-game-object.html
Show/ hide Unity 3D elements
I got this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Modify_Menu_Button_Handler : MonoBehaviour
{
void Start()
{
GameObject[] buttons_in_create_menu;
buttons_in_create_menu = GameObject.FindGameObjectsWithTag("CreateMenu");
}
public void ChangeMenu()
{
foreach (GameObject button in buttons_in_create_menu)
{
button.SetActive(false);
}
}
}
But, the foreach line is red-underlined, saying the buttons_in_create_menu doesn't exist in the current context.
Coming from Javascript, I'm not sure how scope works in C# and especially within Unity's game loop. Thought the Start() function would be called upon the scene loading, based on the Unity docs: link
You must define the variable globally in the class.
Like this:
public class Modify_Menu_Button_Handler : MonoBehaviour
{
public GameObject[] buttons_in_create_menu;
void Start()
{
buttons_in_create_menu = GameObject.FindGameObjectsWithTag("CreateMenu");
}
public void ChangeMenu()
{
foreach (GameObject button in buttons_in_create_menu)
{
button.SetActive(false);
}
}
}
So I am creating a game, which is a Novel game. I want to add a functionality where my friend can add a new dialogue on a character game object. To do that, I already created a main script that enqueue and dequeue all of what is written on the inspector. Two more scripts, one script is a class for creating a new properties on the inspector where my friend can write, the other script functionality is to patch it on the inspector itself. I decided to add a patcher to customize unity editor to add a button. All what is left is a function to add another class where in my friend can write another character name and sentences.
This is what it looks like on Unity Inspector:
Please Help.
DialogueManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DialogueManager : MonoBehaviour
{
private Queue<string> sentences;
public Text WrapperName;
public Text WrapperContent;
void Start()
{
sentences = new Queue<string>();
}
public void StartDialogue (Dialogue dialogue)
{
WrapperName.text = dialogue.name;
sentences.Clear();
foreach (string sentence in dialogue.sentences)
{
sentences.Enqueue(sentence);
}
DisplayNextSentence();
}
public void DisplayNextSentence()
{
if(sentences.Count == 0)
{
EndDialogue();
return;
}
string sentence = sentences.Dequeue();
WrapperContent.text = sentence;
}
public void EndDialogue()
{
Debug.Log("dialogue Ended..");
}
}
Dialogue.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Dialogue
{
public string name;
[TextArea(3, 10)]
public string[] sentences;
}
StoryElement.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class StoryElement : MonoBehaviour
{
public Dialogue dialogue;
public void TriggerDialogue()
{
FindObjectOfType<DialogueManager>().StartDialogue(dialogue);
}
}
elementscriptpatcher.cs
using System.Collections;
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(StoryElement))]
public class elementscriptpatcher : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
if(GUILayout.Button("Add another script"))
{
// I need to write a function for appending a class Dialogue on Dialogue.cs which was initialized on the StoryElement.
}
}
}
you can use GameObject.AddComponent.
if(GUILayout.Button("Add another script"))
{
gameObject.AddComponent<Dialogue>();
}
EDIT : As #derHugo said in comments, we can't add a class that's base is not Monobehaviour. So you will require an Access Class to access Dialogue.cs.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AccessClass : MonoBehaviour {
public Dialogue mClassObject;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
Use Ink for Unity, and author the dialogue as text files.
I have created a game where when the user breaks all the blocks he is taken to the next scene but this is not happening despite adding all of the scenes I have in the build settings. I have no errors whatsoever and the scene is written correctly. Can someone help me resolve this, please?
This is the build settings
Bricks script : (where the scene is called)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bricks : MonoBehaviour {
public LevelManager myLevelManager;
public static int brickCount = 0;
public int maxNumberOfHits = 0;
int timesHit;
public AudioClip BlockBreaking;
// Use this for initialization
void Start () {
timesHit = 0;
if(this.gameObject.tag == "BrickHit")
{
brickCount++;
}
if(this.gameObject.tag == "BrickHitTwice")
{
brickCount++;
}
}
void OnCollisionEnter2D()
{
timesHit++;
if (timesHit == maxNumberOfHits)
{
brickCount--;
Destroy(this.gameObject);
}
if(brickCount == 0)
{
myLevelManager.LoadLevel("Level1.2"); //THIS SCENE IS NOT LOADING
}
if(this.gameObject.tag == "BrickHit") //If the gameObject (Block One Point) with the tag "BrickHit" is hit
{
Scores.scoreValue += 1;//The user will be rewarded 1 point
AudioSource.PlayClipAtPoint(BlockBreaking, transform.position);
}
if(this.gameObject.tag == "BrickHitTwice") //If the gameObject (Block Two Points) with the tag "BrickHitTwice" is hit
{
Scores.scoreValue += 2; //The user will be rewarded 2 points
AudioSource.PlayClipAtPoint(BlockBreaking, transform.position);
}
}
LevelManager Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class LevelManager : MonoBehaviour {
public void LoadLevel(string name)
{
print("Level loading requested for" + name);
SceneManager.LoadScene(name);
}
I suspect that your bug may lie in the fact that you're Destroy()ing the gameObject before it can load the next scene; you get a race condition on what will finish first; LoadScene or Destroy() - which would explain why it sometimes work. You should never assume it is a bug in the framework before understanding your problem.
Try putting the Destroy() after the LoadScene() or with a delay to understand if this is your issue.
Also, your LevelManager can be made static and doesn't need to inherit from MonoBehaviour since it doesn't use gameObject functionality.
public static class LevelManager {
public static void LoadLevel(string name)
{
print("Level loading requested for" + name);
SceneManager.LoadScene(name);
}
}
Used by doing LevelManager.LoadLevel("MyLevel");, but then you may question what is more effective, doing LevelManager.LoadLevel or SceneManager.LoadLevel, as they will do the exact same thing.
The main issue that you're having is not having a single source to check brickCount instead each individual brick is maintaining its own count. I would recommend moving the brick counting logic into a separate class. It would seem like LevelManager would a good place for it. So in LevelManager add:
private int brickCount = 0;
public void AddBrick()
{
brickCount++;
}
public void RemoveBrick()
{
brickCount--;
// Check if all bricks are destroyed
if (brickCount == 0)
{
LoadLevel("Level1.2");
}
}
And then in your brick script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bricks : MonoBehaviour {
public LevelManager myLevelManager;
public int maxNumberOfHits = 0;
int timesHit;
public AudioClip BlockBreaking;
// Use this for initialization
void Start () {
timesHit = 0;
myLevelManager.AddBrick();
// I'm not sure why you were checking the tag here, since the result was the same
}
void OnCollisionEnter2D()
{
timesHit++;
if (timesHit == maxNumberOfHits)
{
myLevelManager.RemoveBrick();
Destroy(this.gameObject);
}
/* This looks like the player is getting score whether the brick is destroyed or not. Also, it would appear the player won't get scored on the final brick */
if(this.gameObject.tag == "BrickHit") //If the gameObject (Block One Point) with the tag "BrickHit" is hit
{
Scores.scoreValue += 1;//The user will be rewarded 1 point
AudioSource.PlayClipAtPoint(BlockBreaking, transform.position);
}
if(this.gameObject.tag == "BrickHitTwice") //If the gameObject (Block Two Points) with the tag "BrickHitTwice" is hit
{
Scores.scoreValue += 2; //The user will be rewarded 2 points
AudioSource.PlayClipAtPoint(BlockBreaking, transform.position);
}
}
}