I have a problem about my gaze on VR . What I am trying to do is that gaze upon the button I want to select then hide the first gameobject parent then show the second gameobject parent . Now the second gameobject parent will be shown and when I try to gaze upon the back button it will show the first gameobject parent and hide the second gameobject parent . The problem occurs here, when I am trying to nothing and don't gaze on the buttons it automatically show my second gameobject parent and go back to first parent gameobject and hide and show and hide and show always.
public float gazeTime = 2f;
private float timer;
private bool gazedAt;
public Setting setting;
private void Start()
{
}
public void Update()
{
if (gazedAt)
{
timer += Time.deltaTime;
if (timer >= gazeTime)
{
// execute pointerdown handler
ExecuteEvents.Execute(gameObject, new PointerEventData(EventSystem.current), ExecuteEvents.pointerDownHandler);
timer = 0f;
}
else
{
return;
}
}
else
{
return;
}
}
public void PointerEnter()
{
gazedAt = true;
Debug.Log("PointerEnter");
}
public void PointerExit()
{
gazedAt = false;
Debug.Log("PointerExit");
}
//Method for going to setting
public void Setting()
{
setting.ActivateSetting();
}
//Method for going back to main menu
public void GoBack()
{
setting.GoBackToMainMenu();
}
Here's how my Setting code is setup
public GameObject setting;
public GameObject back;
public void ActivateSetting()
{
setting.SetActive(false);
back.SetActive(true);
}
public void GoBackToMainMenu()
{
back.SetActive(false);
setting.SetActive(true);
}
What I want is that it will only show the gameobject parent if I gaze upon it.
After calling the click once you reset the timer but you didn't reset gazedAt
=> the Update method did still run the timer and call the click again.
It seems that your PointerExit is not called at all and therefore the button never reset.
Instead of the EventTrigger I would strongly recommend to use the interfaces IPointerEnterHandler and IPointerExitHandler like
public class YourClass : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
//...
public void OnPointerEnter()
{
}
public void OnPointerExit()
{
}
I would actually not use Update at all but prefer a Coroutine. Also don't use the complex call of ExecuteEvents.Execute(gameObject, new PointerEventData(EventSystem.current), ExecuteEvents.pointerDownHandler); instead use either Getcomponent<Button>().onClick.Invoke(); or call the method directly
private Button _button;
private void Awake()
{
// Get the reference only once to avoid
// having to get it over and over again
_button = GetComponent<Button>();
}
private IEnumerator Gaze()
{
// wait for given time
yield return new WaitForSeconds(gazeTime);
// call the buttons onClick event
_button.onClick.Invoke();
// or as said alternatively directly use the methods e.g.
setting.ActivateSetting();
}
public void OnPointerEnter()
{
Debug.Log("PointerEnter");
// start the coroutine
StartCoroutine(Gaze());
}
public void OnPointerExit()
{
Debug.Log("PointerExit");
// stop/interrupt the coroutine
StopCoroutine(Gaze());
}
As you can see there is no need at all for the timer and gazedAt values so you can't forget to reset them somewhere. It also avoids that the method is called repeatedly.
If you don't want to use a Button at all you could also add your own UnityEvent like
// add callbacks e.g. in the Inspector or via script
public UnityEvent onGazedClick;
// ...
onGazedClick.Invoke();
Related
I am making a cookie clicker game for a school project and for my achievement system I want to have a simple animation pop up, and text in a separate menu script that already works perfectly fine.
The issue I am having is that the first two achievements work fine, but after the second one pops up, it just repeats with "Test B" and "Test C" repeating infinitely in the console.
I've tried to have values try to make an 'if' statement void but nothing seems to work.
I feel like I am just eating my own tail with all of the Boolean values I created to get this far.
This is my code below, from only a single script in my Unity file.
Hopefully this has enough information needed for guidance.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Achievements : MonoBehaviour
{
[SerializeField] GameObject achievementBanner;
[SerializeField] GameObject achievementText;
[SerializeField] GameObject achievementBannerAnimation;
[SerializeField] GameObject achievementTextAnimation;
[SerializeField] GameObject achiOne;
[SerializeField] GameObject achiTwo;
[SerializeField] GameObject achiThree;
[SerializeField] GameObject achiFour;
[SerializeField] GameObject achiFive;
[SerializeField] GameObject achiSix;
[SerializeField] public static int achiementcount;
bool achievementrec = false;
bool achievementani = false;
bool achidone = false;
// Start is called before the first frame update
void Start()
{
achiOne.SetActive(false);
achiTwo.SetActive(false);
achiThree.SetActive(false);
achiFour.SetActive(false);
achiFive.SetActive(false);
achiSix.SetActive(false);
achievementBanner.SetActive(false);
achievementText.SetActive(false);
achievementText.GetComponent<Text>().text = "Achievement: First cookie!";
}
// Update is called once per frame
void Update()
{
print(achiementcount);
print(achidone);
if (achiementcount == 1)
{
if (!achievementani)
{
if (!achievementrec)
{
print("Test D");
achiOne.SetActive(true);
achievementBanner.SetActive(true);
achievementText.SetActive(true);
StartCoroutine(AchievementGot());
///achidone = true;
}
}
}
if (achidone == true)
{
///print("Test");
///achidone = false;
if (achiementcount == 2)
{
achievementText.GetComponent<Text>().text = "Achievement: First Clicker!";
achievementani = false;
achievementrec = false;
if (!achievementani)
{
if (!achievementrec)
{
print("Test C");
achiTwo.SetActive(true);
achievementBanner.SetActive(true);
achievementText.SetActive(true);
///achidone = true;
StartCoroutine(AchievementGot());
}
}
}
}
///print(achidone);
if (achidone == true)
{
///achidone = false;
if (achiementcount == 3)
{
achievementText.GetComponent<Text>().text = "Achievement: First Upgrade!";
achievementani = false;
achievementrec = false;
if (!achievementani)
{
if (!achievementrec)
{
print("Test A");
achiThree.SetActive(true);
achievementBanner.SetActive(true);
achievementText.SetActive(true);
StartCoroutine(AchievementGot());
}
}
}
}
}
IEnumerator AchievementGot()
{
///achievementrec = true;
achievementBannerAnimation.GetComponent<Animation>().Play("Achievement");
achievementTextAnimation.GetComponent<Animation>().Play("AchiText");
yield return new WaitForSeconds(6);
achidone = true;
print("Test B");
///print(achidone);
achievementBanner.SetActive(false);
achievementText.SetActive(false);
achievementani = true;
achievementrec = true;
///achidone = false;
}
}
First of all you should use a List/Array.
Then you probably also want to show the banner only ONCE when the achievement is unlocked the first time so you should also keep track of which one you already showed.
E.g. something like
[Serializable]
public class Achievement
{
// text to display in the banner
public string Label;
// the object to enable
public GameObject GameObject;
// has this been achieved
public bool Unlocked;
// has this achievement been displayed
public bool Displayed;
}
public class Achievements : MonoBehaviour
{
// in general instead of many GetComponent calls use the correct type right away in the Inspector
[SerializeField] private GameObject achievementBanner;
[SerializeField] private Text achievementText;
[SerializeField] private Animation achievementBannerAnimation;
[SerializeField] private Animation achievementTextAnimation;
[SerializeField] private Achievement[] achievements;
// is currently a display routine running already?
private bool currentlyDisplaying;
private void Start()
{
// initially hide all objects
foreach (var achievement in achievements)
{
achievement.GameObject.SetActive(false);
}
achievementBanner.SetActive(false);
achievementText.gameObject.SetActive(false);
}
private void Update()
{
// if currently a display routine is running do nothing
if (currentlyDisplaying) return;
// otherwise go through all achievements
foreach (var achievement in achievements)
{
// check if one is unlocked but hasn't been displayed yet
if (achievement.Unlocked && !achievement.Displayed)
{
// set to displayed and display it
StartCoroutine(DisplayAchievement(achievement));
// break to only handle one at a time
break;
}
}
}
private IEnumerator DisplayAchievement(Achievement achievement)
{
// just in case if other routine is already running do nothing
if (currentlyDisplaying) yield break;
// block other routines from being started
currentlyDisplaying = true;
// set displayed so it is not displayed again
achievement.Displayed = true;
// Enable your objects and set the text accordingly
achievementText.text = achievement.Label;
achievementText.gameObject.SetActive(true);
achievementBanner.SetActive(true);
achievement.GameObject.SetActive(true);
achievementBannerAnimation.Play("Achievement");
achievementTextAnimation.Play("AchiText");
yield return new WaitForSeconds(6);
achievementBanner.SetActive(false);
achievementText.gameObject.SetActive(false);
// allow the next routine to start
currentlyDisplaying = false;
}
}
even better than poll checking within Update would be to rather go for events like e.g.
[Serializable]
public class Achievement
{
// text to display in the banner
public string Label;
// the object to enable
public GameObject GameObject;
// has this been achieved
// private but (de)serializable e.g. for saving via Json etc later on
// and editable via Inspector
[SerializeField] private bool unlocked = false;
// public read-only access
public bool Unlocked => unlocked;
public void Unlock()
{
// is this already unlocked anyway?
if(!unlocked)
{
// if not unlock and invoke event
unlocked = true;
OnUnlocked?.Invoke(this);
}
}
// global event to subscribe to for all achievement unlocks
public static event Action<Achievement> OnUnlocked;
}
and then listen to this
public class Achievements : MonoBehaviour
{
// in general instead of many GetComponent calls use the correct type right away in the Inspector
[SerializeField] private GameObject achievementBanner;
[SerializeField] private Text achievementText;
[SerializeField] private Animation achievementBannerAnimation;
[SerializeField] private Animation achievementTextAnimation;
[SerializeField] private Achievement[] achievements;
// is currently a display routine running already?
private bool currentlyDisplaying;
// First-In first-out collection to work off the unlocked achievements in the UI
private readonly Queue<Achievement> achievementsToDisplay = new ();
private void Start()
{
// initially hide all objects
foreach (var achievement in achievements)
{
achievement.GameObject.SetActive(false);
}
achievementBanner.SetActive(false);
achievementText.gameObject.SetActive(false);
// listen to the event
Achievement.OnUnlocked += OnAchievementUnlocked;
}
private void OnDestroy()
{
// to avoid exceptions unregister the listener from the event
Achievement.OnUnlocked -= OnAchievementUnlocked;
}
// called everytime an achievement is unlocked
private void OnAchievementUnlocked(Achievement achievement)
{
// add achievement to the queue to work
achievementsToDisplay.Enqueue(achievement);
// if there isn't a worker routine running already anyway
if (!currentlyDisplaying)
{
// start one now
StartCoroutine(DisplayAchievements());
}
}
private IEnumerator DisplayAchievement()
{
// just in case if other routine is already running do nothing
if (currentlyDisplaying) yield break;
// block other routines from being started
currentlyDisplaying = true;
// as long as there are new achievements in the queue simply continue directly with the next one
while(achievementsToDisplay.Count > 0)
{
var achievement = achievementsToDisplay.Dequeue();
// Enable your objects and set the text accordingly
achievementText.text = achievement.Label;
achievementText.gameObject.SetActive(true);
achievementBanner.SetActive(true);
achievement.GameObject.SetActive(true);
achievementBannerAnimation.Play("Achievement");
achievementTextAnimation.Play("AchiText");
yield return new WaitForSeconds(6);
achievementBanner.SetActive(false);
achievementText.gameObject.SetActive(false);
}
// when queue is worked off terminate for now
// and allow the next routine to be started later
currentlyDisplaying = false;
}
}
Is there a listener event to detect if an object is set to inactive from active state or to active from inactive state? I do not want to add it in Update as there will be multiple calls and it would affect my game's performance. So is there an alternative for this?
public GameObject Go_1;
public GameObject Go_2;
void Update () {
if (Go_1.activeSelf) {
} else if (Go_2.activeSelf) {
}
}
You could implement something using the Update method like e.g.
public class ActiveSelfWatcher : MonoBehaviour
{
private Dictionary<ActiveSelfProvider, bool> _lastActiveSelfState = new Dictionary<ActiveSelfProvider, bool>();
private void OnObjectBecameActive(GameObject obj)
{
Debug.Log($"{obj.name} became active!", this);
}
private void OnObjectBecameInactive(GameObject obj)
{
Debug.Log($"{obj.name} became inactive!", this);
}
private void Update()
{
// Iterate through all registered instances of ActiveSelfProvider
foreach(var provider in ActiveSelfProvider.Instances)
{
// pre-cache the GameObject reference
var obj = provider.gameObject;
// pre-cache the current activeSelf state
var currentActive = obj.activeSelf;
if(!_lastActiveSelfState.TryGetValue(provider))
{
// we don't know this provider until now
// TODO here you have to decide whether you want to call the events now once for this provider or not
// TODO otherwise it is only called for providers you already know and changed their state
}
if(currentActive != _lastActiveSelfState[provider])
{
// the state is not the one we stored for this instance
// => it changed its states since the last frame
// Call the according "event"
if(currentActive)
{
OnObjectBecameActive(obj);
}
else
{
OnObjectBecameInactive(obj);
}
}
// store the current value
_lastActiveSelfState[provider] = currentActive;
}
}
}
This is your watcher class you currently already have anyway.
Then on all the objects you want to be able to watch you use
public class ActiveSelfProvider : MonoBehaviour
{
private static readonly HashSet<ActiveSelfProvider> instances = new HashSet<ActiveSelfProvider>();
public static HashSet<ActiveSelfProvider> Instances => new HashSet<ActiveSelfProvider>(instances);
private void Awake()
{
// register your self to the existing instances
instances.Add(this);
}
private void OnDestroy()
{
// remove yourself from the existing instances
instances.Remove(this);
}
}
If this is "efficient enough" for you use case you would have to test ;)
If you want to go super fancy, someone once made a Transform Interceptor .. a quite nasty hack which on compile time overrules parts of the Unity built-in Transform property setters to hook in callbacks.
One probably could create something like this also for SetActive ;)
Note: Typed on smartphone but I hope the idea gets clear
Yes, try with OnEnable and OnDisable.
// Implement OnDisable and OnEnable script functions.
// These functions will be called when the attached GameObject
// is toggled.
// This example also supports the Editor. The Update function
// will be called, for example, when the position of the
// GameObject is changed.
using UnityEngine;
[ExecuteInEditMode]
public class PrintOnOff : MonoBehaviour
{
void OnDisable()
{
Debug.Log("PrintOnDisable: script was disabled");
}
void OnEnable()
{
Debug.Log("PrintOnEnable: script was enabled");
}
void Update()
{
#if UNITY_EDITOR
Debug.Log("Editor causes this Update");
#endif
}
}
how i can pass a simple boolean variable between two different object?
I can try this but didn't work...
First script:
public class CollisionController : MonoBehaviour
{
public PlayerMovement movement;
public bool active = false;
private void OnCollisionEnter(Collision collision)
{
if(collision.collider.tag == "Obstacle")
{
active = true;
}
}
}
Second script (that read the boolean variable "active")
public class EmptyControllerColl : MonoBehaviour
{
public CollisionController controller;
public PlayerMovement movement;
public bool activeLocal = false;
private void Start()
{
GetComponentInChildren<CollisionController>();
}
void Update()
{
activeLocal = controller.active;
if(activeLocal == false)
{
Debug.Log("Nothing...");
}
if(activeLocal == true)
{
Debug.Log("Game over");
}
}
}
When the variable bool "Active" change its status, the variable "activeLocal" don't change status.. How can I resolve this problem?
Collision Controller is "connect" to Cube Object.
EmptyControllerColl is "connect" to emptyGameObject (parent of Cube).
This line
_ = GameObject.Find("cubo Variant").GetComponent<CollisionController>().active;
makes no sense. First of all there is no field or variable declared with the name _ so this shouldn't even compile at all. And secondly what do you need this for? Rather store the according reference once in the controller field and reuse it later.
Then for your usecase there is no need at all to store the value in a local variable ... this makes things only more complicated. Simply where you need it get the value from controller.active.
Also do not use == for tags. Rather check via CompareTag. The problem is that == silently fails if you have any typo or the tag doesn't exist at all. CompareTag rather throws an error that the given tag is not valid.
public class EmptyControllerColl : MonoBehaviour
{
// Best already drag this in via the Inspector in Unity
[SerializeField] private CollisionController controller;
public PlayerMovement movement;
// As fallback get it ONCE on runtime
private void Awake()
{
// since you say the cube is a child of this empty object you do not use
// Find at all but can simply use GetComponentInChildren
if(!controller) controller = GetComponentInChildren<CollisionController>(true);
}
void Update()
{
// No need to store this in a local field at all
if(!controller.active)
{
Debug.Log("Nothing...");
}
// use if else since both cases are exclusive and you don't even need to check the value twice
else
{
Debug.Log("Game over");
}
}
}
Event Driven - part A
In general you should avoid poll checks for a bool value in Update and rather come up with a more event driven solution! An example could look like:
public class CollisionController : MonoBehaviour
{
public PlayerMovement movement;
// Here everyone who wants can add listeners that get called as soon as
// we invoke this event. We will do it everytime the 'active' value is changed
public event Action<bool> OnActiveStateChanged;
// Backing field for 'active'
private bool _active;
// Property that reads and writes '_active'
// Everytime it is assigned it also invokes 'OnActiveStateChanged'
private bool active
{
get { return _active; }
set
{
_active = value;
OnActiveStateChanged?.Invoke(_active);
}
}
private void OnCollisionEnter(Collision collision)
{
if(collision.collider.CompareTag("Obstacle"))
{
active = true;
}
}
}
Now you would register a listener for this event like
public class EmptyControllerColl : MonoBehaviour
{
// Best already drag this in via the Inspector in Unity
[SerializeField] private CollisionController controller;
public PlayerMovement movement;
// As fallback get it ONCE on runtime
private void Awake()
{
// since you say the cube is a child of this empty object you do not use
// Find at all but can simply use GetComponentInChildren
if(!controller) controller = GetComponentInChildren<CollisionController>(true);
// register a callback. It is allowed an save to unregister first
// which makes sure this is only registered exactly once
controller.OnActiveStateChanged -= HandleControlerActiveStateChanged;
controller.OnActiveStateChanged += HandleControlerActiveStateChanged;
}
private void HandleGameOver()
{
Debug.Log("Game over");
}
private void HandleControlerActiveStateChanged(bool value)
{
if(!value)
{
Debug.Log("Nothing...");
}
else
{
Debug.Log("Game over");
}
}
private void OnDestroy()
{
// always clean up listeners
controller.OnActiveStateChanged -= HandleControlerActiveStateChanged;
}
}
This now is way more efficient since you don't all time run an Update method. Instead the HandleControlerActiveStateChanged is only called when the value of active is actually changed.
Event Driven - part B
And then actually in your case there is need to use a bool at all you could use a simple event Action instead and remove all the bools entirely:
public class CollisionController : MonoBehaviour
{
public PlayerMovement movement;
public event Action OnGameOver;
private void OnCollisionEnter(Collision collision)
{
if(collision.collider.CompareTag("Obstacle"))
{
OnGameOver?.Invoke();
}
}
}
Now you would register a listener for this event like
public class EmptyControllerColl : MonoBehaviour
{
[SerializeField] private CollisionController controller;
public PlayerMovement movement;
private void Awake()
{
if(!controller) controller = GetComponentInChildren<CollisionController>(true);
controller.OnGameOver -= HandleGameOver;
controller.OnGameOver += HandleGameOver;
}
private void HandleGameOver()
{
Debug.Log("Game over");
}
private void OnDestroy()
{
controller.OnGameOver -= HandleGameOver;
}
}
using UnityEngine;
public class CollisionController : MonoBehaviour
{
void Start()
{
// Calls the function ApplyDamage with a value of 5
// Every script attached to the game object
// that has an ApplyDamage function will be called.
gameObject.SendMessage("ApplyDamage", 5.0);
}
}
public class EmptyControllerColl : MonoBehaviour
{
public void ApplyDamage(float damage)
{
print(damage);
}
}
https://docs.unity3d.com/ScriptReference/GameObject.SendMessage.html
I have a level in a game where when you get in a box collider, a portal opens, and when you leave it, it closes. Both portals need to open when I enter in box collider 1, and both need to close when i leave it. This also needs to happen when I enter in a box collider 2 of the second portal. I have a script for box collider 1 and I apply it to box collider 2. It checks if the player is in a collider. I have an animator bool which directly takes variable from box collider script to check in range. I use that bool for animation. However, that animator bool doesen't work for box collider 2. Variable for box collider works, but not animator bool. Is there a way to connect that second one, or do i need to make a new script for that box collider?
Box Collider Code:
public bool inRange;
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
inRange = true;
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
inRange = false;
}
}
}
Portal Script Code:
public class Portal : MonoBehaviour {
private Animator anim;
private bool inPortalRange;
public GameObject portalBorder;
void Start ()
{
anim = GetComponent<Animator>();
}
void Update ()
{
OpenPortal();
UpdateAnimation();
}
private void UpdateAnimation()
{
anim.SetBool("inPortalRange", inPortalRange);
}
private void OpenPortal()
{
PortalBorder poborder = portalBorder.GetComponent<PortalBorder>();
inPortalRange = poborder.inRange;
}
}
A picture of a situation:
First of all you should not use GetComponent every frame. Either like the anim you should rather store it right away. Or you could simply make portalBorder of type PortalBorder then the according reference is set automatically when referencing it via the Inspector.
Then yes currently you are only updating one of the animators. In order to control them both you have to connect them somehow.
I would do something like this
public class Portal : MonoBehaviour
{
private Animator anim;
private bool inPortalRange;
// Public read-only access
public bool InPortalRange => inPortalRange;
// Reference each other via the Inspector in both portals
public Portal OtherPortal;
// Give this directly the according type so you don't need GetComponent at all
public PortalBorder portalBorder;
// I would recommend to do things always as early as possible
// Awake is executed before Start
private void Awake()
{
anim = GetComponent<Animator>();
}
private void Update ()
{
OpenPortal();
UpdateAnimation();
}
private void UpdateAnimation()
{
// Here now use the range of either this or the other portal
anim.SetBool("inPortalRange", InPortalRange || OtherPortal.inPortalRange );
}
private void OpenPortal()
{
inPortalRange = portalBorder.inRange;
}
}
However instead of making it a polling call in Update I would actually rather use an event driven approach:
public class PortalBorder : MonoBehaviour
{
public UnityEvent OnEnteredPortalRange;
public UnityEvent OnLeftPortalRange;
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
OnEnteredPortalRange.Invoke();
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
OnEnteredPortalRange.Invoke();
}
}
}
Now your script has to UnityEvent (just like the onClick of buttons) where you can add callbacks either via the inspector or using code
public class Portal : MonoBehaviour
{
public Animator anim;
private bool inPortalRange;
// Public read-only access
public bool InPortalRange => inPortalRange;
// Reference each other via the Inspector in both portals
public Portal OtherPortal;
// Give this directly the according type so you don't need GetComponent at all
public PortalBorder portalBorder;
// I would recommend to do things always as early as possible
// Awake is executed before Start
private void Awake()
{
anim = GetComponent<Animator>();
// Instead of checking a bool in Update simply
// wait until the according events get invoked
portalBorder.OnEnteredPortalRange.AddListener(EnablePortal);
portalBorder.OnLeftPortalRange.AddListener(DisablePortal);
}
private void OnDestroy()
{
// always make sure to remove callbacks when not needed anymore
// in roder to avoid NullReferenceExceptions
portalBorder.OnEnteredPortalRange.RemoveListener(EnablePortal);
portalBorder.OnLeftPortalRange.RemoveListener(DisablePortal);
}
public void EnablePortal()
{
anim.SetBool("inPortalRange", true);
OtherPortal.anim.SetBool("inPortalRange", true);
}
public void DisablePortal()
{
anim.SetBool("inPortalRange", false);
OtherPortal.anim.SetBool("inPortalRange", false);
}
}
When I click the OK button of the win or lose panel on the GameScene it takes me back to the MenuScene and shows the title screen instead of the level select screen.
The references to the paneles are missing before changing scene, how can I keep them through them?
StartManager
public GameObject startPanel, levelPanel;
// Start is called before the first frame update
void Start()
{
startPanel.SetActive(true);
levelPanel.SetActive(false);
}
public void PlayGame()
{
startPanel.SetActive(false);
levelPanel.SetActive(true);
}
public void Home()
{
startPanel.SetActive(true);
levelPanel.SetActive(false);
}
I expected the levelPanel to be active
public GameObject startPanel, levelPanel;
public static bool OpenLevelPanel;
// Start is called before the first frame update
void Start()
{
// Check OpenLevelPanel Bool Setting That;
startPanel.SetActive(!OpenLevelPanel);
levelPanel.SetActive(OpenLevelPanel);
}
public void PlayGame()
{
startPanel.SetActive(false);
levelPanel.SetActive(true);
}
public void Home()
{
startPanel.SetActive(true);
levelPanel.SetActive(false);
}
On Button Ok Click
StartManager.OpenLevelPanel = true;
//Switch Scene...