References to the panels missing - c#

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...

Related

decrease variable by button click C#

I want to decrease a value by clicking a button, but it does not stay at and turns back to the value at the beginning,
here is my code, what should I add or change can somebody help me?
Thanks a lot
public class LifeShow : MonoBehaviour
{
public GameObject Life; //where the variable will be decreased from
public int Lifevalue;
public string text;
public Button returns;
// Start is called before the first frame update
void Start()
{
Lifevalue = 1;
Life.GetComponent<Text>().text = "Life : " + Lifevalue;
}
// Update is called once per frame
// clicking the button and the lifevalue variable decreases
void Update()
{
Button btn = returns.GetComponent<Button>();
btn.onClick.AddListener(TaskOnClick);
void TaskOnClick()
{
Lifevalue-- ;
Life.GetComponent<Text>().text = "Life : " + Lifevalue;
}
}
}
What you can do is change the local method void TaskOnClick() to a public method by putting it outside update and using public keyword and you can add OnClick in unity
now hit the '+' button and drag and drop your object that script attached to. You can then find as this
choose your function and you are ready. You don't need to do this by script.
If you want to restrict it to not go below 0 you can add a If condition in script
if(LifeValue > 0)
{
LifeValue--;
// showing text
}
It will prevent to go below 0.
OnClick + to add listener
Drag listener object to slot (Life)
Choice function from Life script (Modify)
Set argument value 1 / -1 / -99
[DisallowMultipleComponent]
public class Life : MonoBehaviour {
public event System.Action<int> Changed; // event with INT attribute
private int _amouth;
public int Amouth { // this in property
get => _amouth;
// when you set Amouth, then change _amouth and invoke "Changed" event
set {
if (_amouth != value) {
_amouth = value;
Changed?.Invoke(_amouth);
}
}
}
private void Start () {
Amouth = 1;
}
public void Modify (int number) {
Amouth += number;
}
}
[DisallowMultipleComponent]
[RequireComponent(typeof(Text))]
public class LifeView : MonoBehaviour { // Add Component to text object
[SerializeField] private Life _life; // set on inspector window
private Text _text;
public int LineAmouth { get; private set; }
private void OnEnable () {
_text = GetComponent<Text>();
UpdateText(_life.Amouth);
_life.Changed += UpdateText; // subscribes to Life event
}
private void OnDisable () {
_life.Changed -= UpdateText;
}
private void UpdateText (int amouth) {
_text.text = "Life : "+amouth;
}
}
Not really an expert of Mono but, first of all it seems that you are attaching an event handler on every frame, which is not good. The code should be:
public class LifeShow : MonoBehaviour
{
public GameObject Life; //where the variable will be decreased from
public int Lifevalue;
public string text;
public Button returns;
// Start is called before the first frame update
void Start()
{
Lifevalue = 1;
Life.GetComponent<Text>().text = "Life : " + Lifevalue;
Button btn = returns.GetComponent<Button>();
btn.onClick.AddListener(TaskOnClick);
}
// Update is called once per frame
void Update()
{
}
void TaskOnClick()
{
Lifevalue-- ;
Life.GetComponent<Text>().text = "Life : " + Lifevalue;
}
}
Second, it is pretty unclear what's the difference between Lifevalue and the Life GameObject, can you tell?
EDIT: As someone stated in the comments this code is not really enough to give good hints, could you show the Life object's code? That would be pretty helpful.

How to open same animation with two same box colliders?

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);
}
}

gaze always execute even after PointExit

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();

How to change conditions in Update() unity c#

I have created navMeshand agent. For target I used two empty object.
For each empty object I created two buttons.
If I click on white button agent moves to empty target first again I click on red button agent moves to 2nd empty target.
I am facing problem when I want move agent from target-2 to target-1.
How I can move that agent to taeget-1?
See video for better understanding
video link https://youtu.be/zRKHdMeQsi0
Code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class SampleAgentScript : MonoBehaviour {
public Transform target , target2;
NavMeshAgent agent;
private static bool start1=false , start2=false;
void Start()
{
agent = GetComponent<NavMeshAgent>();
}
public static void buttonClick()
{
//if white button click
start1 = true;
}
public static void buttonClick2()
{
//if red button click
start2 = true;
}
void Update()
{
if (start1) //if white button click moves to targer-1
{
agent.SetDestination(target.position);
}
if (start2) //if red button click moves to targer-2
{
agent.SetDestination(target2.position);
}
}
}
May be this will help.
public static void buttonClick()
{
//if white button click
start1 = true;
start2 = false;
}
public static void buttonClick2()
{
//if red button click
start2 = true;
start1 = false;
}
You have forgotten to alternate the state by resetting the boolean values to false. As you have set boolean values in the button click handler, so you can alternate states in the update function as well.
void Update()
{
if (start1) //if white button click moves to targer-1
{
agent.SetDestination(target.position);
start1=false;
}
if (start2) //if re button click moves to targer-2
{
agent.SetDestination(target2.position);
start2=false;
}
}
When you click the second button both of the conditions become true and in each frame you are setting two different destinations.
public Transform dest, target , target2;
public void buttonClick()
{
dest = target;
}
public void buttonClick2()
{
dest = target2;
}
void Update()
{
agent.SetDestination(dest .position);
}

OnMouseDown() null reference exception

public class TowerNode : MonoBehaviour {
public bool IsShopOpen=false;
//Z position
public Vector3 positionOffSet;
//colors
public Color hoverColor;
private Color startColor;
//GameObjects
public GameObject turret;
//shop
public Shop shop;
//Build Manager
BuildManager buildManager;
void Start()
{
rend=GetComponent<Renderer>();
startColor = rend.material.color;
buildManager = BuildManager.instance;
shop = GetComponent<Shop>();
}
//When mouse is on the turret node
public void OnMouseDown()
{
Debug.Log("Mouse is Down");
bool IsShopOpen = true;
if (IsShopOpen == true)
{
Debug.Log("shop is open");
shop.onEnable();
}
if (EventSystem.current.IsPointerOverGameObject())
{
return;
}
if (!buildManager.CanBuild)
{
return;
}
if (turret != null)
{
Debug.Log("Cant Build Here!!!");
return;
}
buildManager.BuildTurretOn(this);
}
the other script of the shop is this:
public class Shop : MonoBehaviour
{
public TurretBlueprint Archery;
public TurretBlueprint Treb;
public TurretBlueprint Workamp;
public TurretBlueprint Barracks;
public Button Archeryy;
public Button Trebb;
public Button WorkCampp;
public Button Barrackss;
BuildManager buildManager;
void Start()
{
buildManager = BuildManager.instance;
disableAllButtons();
//OnEnable();
}
public void SelectArchery()
{
buildManager.SelectTurretToBuild(Archery);
Debug.Log("archery!!!!");
}
public void SelectTreb()
{
buildManager.SelectTurretToBuild(Treb);
Debug.Log("Treb!!!!");
}
public void SelectWorkamp()
{
buildManager.SelectTurretToBuild(Workamp);
Debug.Log("Work Camp!!!!");
}
public void SelectBarracks()
{
buildManager.SelectTurretToBuild(Barracks);
Debug.Log("Barracks!!!!");
}
public void onEnable()
{
Archeryy.gameObject.SetActive(true);
Trebb.gameObject.SetActive(true);
WorkCampp.gameObject.SetActive(true);
Barrackss.gameObject.SetActive(true);
}
public void disableAllButtons()
{
Archeryy.gameObject.SetActive(false);
Trebb.gameObject.SetActive(false);
WorkCampp.gameObject.SetActive(false);
Barrackss.gameObject.SetActive(false);
}
}
I need when i click on the game object that the shop will open the sop got few buttons under it, but it gives me:
"NullReferenceException: Object reference not set to an instance of an object
TowerNode.OnMouseDown () (at Assets/Scripts/TowerNode.cs:51)
UnityEngine.SendMouseEvents:DoSendMouseEvents(Int32)"
and I don't understand why.
The error you are getting implies that an object in the OnMouseDown function is null when executed:
NullReferenceException: Object reference not set to an instance of an object TowerNode.OnMouseDown () (at Assets/Scripts/TowerNode.cs:51)
You should look at ine 51 of TowerNode.cs and ascertain what can be null on that line. Could shop or buildManager be null? Perhaps this event is firing before you have initialised your TowerNode object.
It seems you are trying to access a component (Shop) from a completely unrelated GameObject. If you want all of your TowerNode objects to reference the Shop then you could use GameObject.Find. This isn't really recommended though; it seems like there is a better way to link these two objects but I am unsure of your use case.

Categories