Best method to listen when checkbox is enabled / disabled (in Unity Editor) ?
I want to enable and disable while running/playing scene
Maybe possible to toggle once and Editor could wait when i click again?
I don't need every update scan list..
My code:
void Update () {
checkboxStatus(visibleLocations, locationsList);
}
public void checkboxStatus(bool checkboxEnabled, List<GameObject> list)
{
if (list.Count > 0)
{
foreach (var item in list)
{
if (checkboxEnabled)
{
item.GetComponentInChildren<MeshRenderer>().enabled = true;
}
else
{
item.GetComponentInChildren<MeshRenderer>().enabled = false;
}
}
}
}
You could simply store and compare the previous value. You could optionally also add pre-processors in order to make the Update method only exist in the editor but later in a build only use the method call (see Platform dependent compilation) like
#if UNITY_EDITOR
private bool _lastVisibleLocations;
private void Update ()
{
if(visibleLocations != _lastVisibleLocations)
{
checkboxStatus(visibleLocations, locationsList);
_lastVisibleLocations = visibleLocations;
}
}
#endif
public void checkboxStatus(bool checkboxEnabled, List<GameObject> list)
{
// You can skip the check for Count here
// if there are no elements then foreach simply will do nothing anyway
foreach (var item in list)
{
// your if-else here was a bit redundant
// you can directly use the value of checkBoxEnabled
item.GetComponentInChildren<MeshRenderer>().enabled = checkBoxEnabled;
}
}
If it is only for the Editor you could even move it from Update into OnValidate so it is only checked if something actually was changed via the Inspector.
Related
I want a script to have radio buttons for booleans and it seems like OnValidate() would be the perfect way to do that. However, i would need to trace what value was changed in the inspector and put a check for the identifier but I couldn't find the solution for the tracing part. How do i know what value was changed for OnValidate() to be called?
As said in the comments might not be the most "beautiful" solution but I would do it e.g. like
// These are the fields in the Inspector
// changing any via the Inspector will Invoke OnValidade
[SerializeField] private bool bool1;
[SerializeField] private bool bool2;
// These are private and will be used to check what was changed
private bool _oldBool1;
private bool _oldBool2;
private void OnValidate()
{
if(bool1 != _oldBool1)
{
// bool1 was changed
if(bool1)
{
// Probably: set all other values to false
}
else
{
// Probably check if all other values are false, if so this may not be false
}
}
if(bool2 != _oldBool2)
{
// bool2 was changed
if(bool2)
{
// Probably: set all other values to false
}
else
{
// Probably check if all other values are false, if so this may not be false
}
}
// Etc
// And finally store the new values
_oldBool1 = bool1;
_oldBool2 = bool2;
// Etc
}
Afaik the changes via script of the serialized fields should not Invoke another OnValidate, only changes via the Inspector or the first time the asset is loaded.
This function is called when the script is loaded or a value is changed in the Inspector (Called in the editor only).
You could probably also work with a List/Array instead of individual fields of course
Typed on smartphone so can't test it right now but I hope the idea gets clear
private void CheckingSelection() {
Transform child = Selection.activeTransform;
Transform[] patchesTransform = builder.GetLevelEditorPatchesTransform();
foreach (var parent in patchesTransform) {
if (child.IsChildOf(parent) && child != parent) {
Debug.Log("Set active " + parent.gameObject);
Selection.activeGameObject = parent.gameObject;
}
}
}
That's what I do, but it does not select the parent. What am I do wrong ?
The deal is how I called method CheckingSelection();
I added this method to delegate Selection.selectionChanged. And I thought its kind of logical things to do my checking after selecting something. But it was not working. It might be of internal Unity things, that block recursy or some.
So, I addedCheckingSelection() method to EditorApplication.update delegate, and it works.
I'm trying to remove a gameObject from the world and a list using:
Destroy(obj);
itemsInInv.Remove(obj.gameObject);
But for some reason, it's reading my list.count as 0 every time I try to reference it threw a click event. If I use a key down and remove a specific item it works fine. But when I try to read my list threw a click event it returns 0 instead of the amount of items actually in the array
Like I can push 'Z' and get the Debug.Log(itemsInInv.Count) will say 15. Then I'll click the item to try and run the same Debug.Log(itemsInInv.Count) and it returns 0.
I've tried using the built in interface on the unity program. I tried using
items.GetComponent<Button>().onClick.AddListener(() => { useItem(); });
Which actually did work 100% fine for a little while then for some reason stopped working and won't work again no matter what I do lol.
I've tried using:
void OnDestroy()
{
manager.GetComponent<UIManager>().Remove(this.gameObject);
Debug.Log("remove" + manager.GetComponent<UIManager>().itemsInInv.Count);
}
public void OnPointerClick(PointerEventData eventData)
{
Destroy(gameObject);
}
Also tried doing the remove in the same function as the click. Same problem. Idk how else this is possible to do it? Even if I create a boolean and have it set to false, then use the button to set it too true, it won't read as true when debugged.
What I'm pretty much asking is, how do I add a list of buttons to the screen. Then delete the SAME button I clicked on from the screen and the list.
Soo this is what i did to get it too work....
i added this script onto my item thats being clicked
public void OnPointerClick(PointerEventData eventData)
{
EventSystem.current.SetSelectedGameObject(gameObject);
Debug.Log("hey"+ EventSystem.current.currentSelectedGameObject);
}
then in my other script im running
items.GetComponent<Button>().onClick.AddListener(() => { useItem(); });
which runs
public void useItem()
{
Invoke("itemUsed", 0.25f);
}
which runs after 0.25
void itemUsed()
{
Debug.Log(EventSystem.current.currentSelectedGameObject);
deleteItem(EventSystem.current.currentSelectedGameObject);
sortItems();
}
I had to do the invoke because it was calling useItem, before the currently selected was being selected
Also my event System was a child of my canvas which made my gameManager unable to access it the way i was
Dont use a list. Use a Dictionary.
public static Dictionary<string, GameObject> dict = new Dictionary<string, GameObject>();
then you can use the gameobjects name.
foreach(GameObject r in FindObjectsOfType(typeof(GameObject)))
{
dict.Add(r.name, r);
}
Then you can do
Destroy(gameObject.name);
dict.Remove(gameObject.name);
I have the following code:
void Setup(CityBuilding[] buildings) {
foreach (CityBuilding building in buildings)
{
GameObject buildingDisp = Instantiate(singleGoodsDisplay);
//... Other stuff not relevent happens here
buildingDisp.GetComponent<Button>().onClick.AddListener(() => { ProcessClick(building); });
Debug.Log(building);
}
}
private void ProcessClick(CityBuilding building)
{
Debug.Log(building);
}
The bottom line is, I have a few buttons that are saved as a prefab and instantiated. I'm adding an onClick Listener to it, in the form of a lambda function. I'm passing in a data object. Right now buildings is an array of two. I see that both items are debugged, however, when I actually click on the buttons, I always see the second item is used, never the first. I'm not quite sure what I'm doing wrong. Any thoughts? Thanks!
It seems that the object reference isn't saved, it only uses the latest. What does work is to save a copy and pass it, as follows:
void Setup(CityBuilding[] buildings) {
foreach (CityBuilding building in buildings)
{
CityBuilding temp=building;
GameObject buildingDisp = Instantiate(singleGoodsDisplay);
//... Other stuff not relevent happens here
buildingDisp.GetComponent<Button>().onClick.AddListener(() => { ProcessClick(temp); });
}
}
I have a checkBox in my Windows application called "Continuous". When user checks this and clicks "Process" button, application will process all the items in the listBox. However if user does not check this box it will only process the first one in the list.
In my Process method I want to write an if condition to check the checkBox checked and execute the foreach loop otherwise execute just the first item.
Here is my code
private void btnProcess_Clicl()
{
bool bDone = false;
while(!bDone)
{
LoadList(); //This will load the list from database into listBox
if(listBox.items.Count > 0)
{
ProcessList();
}
if(!chkBox.Checked)
bDone = true;
}
}
I've implement the foreach loop to process list in ProcessList() method. Is there anyway to avoid executing LoadList() method from executing if the user checks continuous checkBox? LoadList() will populate the listBox from database.
do something like this
if( chkBox.Checked )
ProcessList();
else
ProcessOne();
Write the functions to do what you want
update
to avoid duplicating the processing code you could do something like
public void ProcessList()
{
foreach( var item in list )
ProcessOne( item );
}
Factoring is your friend.
void ProcessList(int start, int count) {
for (int i=start; i < start + count; i++) {
ProcessItem(i);
}
}
void ProcessItem(int i) { // your code here
}
private void btnProcess_Click() {
if (IsContinuous) {
ProcessList(0, list.Count);
}
else {
ProcessItem(0);
}
}
private bool IsContinuous { get { return chkBox.Checked; } }
This will work for you but I don't especially like it since I think Process should be part of the list data structure itself and not my UI. Model (and View) and Control should be separate (if possible).
Boolean doAllItems = chkBox.Checked;
foreach(Object something in collection)
{
DoWork(something);
if(!doAllItems)
break;
}