#Sahil
1 messages · Page 1 of 1 (latest)
Let's discuss it here
Your code won't work because when your button is pressed, it is set to true
You wrote them as nested if, but they aren't really nested, you could write if (button[0].buttonPressed && button[2].buttonPressed,...)
yeah i figured
ok lemme try your way then
might as well learn it now so i can use it in the future
You're not forced to use Events but what you're missing is some way to keep track of which button has last been pressed
yeah and thats kind of important in this i think
ok this isnt working
currentButton.OnTrigger?.AddListener(OnButtonPressed);
gives me an error that button doesnt contain a definition for that
do i need to define it somehow?
Yes, you need to need to define need in whatever currentButton is
public UnityEvent.OnTrigger;
By the way, do you want it to reset if the player presses the wrong button?
An Event isn't automatic, you have to decided when it is triggered by using yourEventName.Invoke();
I want it to reset if after all buttons are pressed and its the wrong order
its telling me UnityEvent.OnTrigger doesnt exist in current context
I put it in the Button script
Hmm let me see the code
public MultiButtonDoor multiButtonDoor;
public UnityEvent.OnTrigger;
private Animator button;
public bool buttonPressed = false;
private void Start()
{
button = GetComponent<Animator>();
}
private void Update()
{
if (multiButtonDoor.incorrectOrder)
{
multiButtonDoor.incorrectOrder = false;
button.Play("ButtonPressUp");
}
}
private void OnTriggerEnter(Collider other)
{
button.Play("ButtonPressDown");
buttonPressed = true;
}
No dot between UnityEvent and OnTrigger
that how you wrote it?
Oh sorry, typo
Yup
Although we will have to reformat the code a bit for the whole "reset" stuff, but our event will still be useful
private void OnTriggerEnter(Collider other)
{
OnTrigger.Invoke();
button.Play("ButtonPressDown");
buttonPressed = true;
}
this right
Better to put it at the end
ok
It wouldn't make a difference in this case but it might in others
you first want to do the stuff your method is for (let's say, update the health of a character), THEN send the information that the health has been updated
public Button[] buttons;
public GameObject[] doors;
private Button currentButton;
public float doorMoveTime = 1f;
public bool incorrectOrder = false;
int index = 0;
void Start()
{
GetNextButton();
}
private void OnButtonPressed()
{
currentButton.OnTrigger?.RemoveListener(OnButtonPressed);
GetNextButton();
}
private void GetNextButton()
{
currentButton = buttons[++index];
currentButton.OnTrigger?.AddListener(OnButtonPressed);
}
this is what i have in the main script
so where would i open the door in the end?
basically once all buttons are pressed, it should either open the door or reset the buttons if it was the wrong order
Or you should
no errors
How is your class called?
which class
The one with the OnTrigger event
public Button[] buttons;
like this
Hmm, might want to rename it to avoid confusion with Unity's built-in button, but it's okay
so how do i do this?
So right now, the issue is that the way this is coded, we can't actually know when an incorrect button is pressed, but we can fix that
As things are right now, we are only "listening" to the button which interests us while completely ignoring the others
I thought its based on the order we put the buttons in the inspector?
Yes, it will listen to the clicks in the correct order, but it won't know if someone has clicked an incorrect button between clicking on two correct ones
I will tweak a few things, gimme 5mins
yea, but UnityEvents are being annoying
dat happens . . .
You apparently can't use static UnityEvents out of the box, you need to instantiate them
so what now
Ok, should be good now
yeah, that makes sense. they're made for the inspector . . .
There are basically two way to go about it : Either you loop through every Button in your list and use the line buttons[i].onTrigger.AddListener(OnClick);
Or you use a static Event, which is to say, an event that will be called any time any button of that class is pressed
I prefer the second myself, but static events do not tell you WHICH button is pressed by default, so you need to pass that info as well
They basically just tell you "a button has been pressed"
using UnityEngine;
using UnityEngine.Events;
public class YourButton : MonoBehaviour
{
public static UnityEvent<YourButton> onTrigger;
private void Awake()
{
if (onTrigger == null)
onTrigger = new UnityEvent<YourButton>();
}
public void OnTriggerEnter(Collider other)
{
onTrigger?.Invoke(this);
}
}
As you can see, I added <YourButton> after UnityEvent in this case, which means two things :
1- A variable of type YourButton will be passed as an argument
2- Any method in AddListener will now need to have a "Your button" argument
private void OnButtonPressed(YourButton button)
So the OnButtonPressed now has that argument as well
i just hoped in, but what is the initial question or what they're trying to achieve?
ok this is getting super confusing ngl
can we just do it the other way i cant learn all this so quickly
public Button[] buttons;
public GameObject[] doors;
public float doorMoveTime = 1f;
public bool incorrectOrder = false;
int i = 0;
void Start()
{
GetNextButton();
}
private void OnButtonPressed()
{
buttons[i].OnTrigger?.RemoveListener(OnButtonPressed);
GetNextButton();
}
private void GetNextButton()
{
i ++;
buttons[i].OnTrigger?.AddListener(OnButtonPressed);
}
would it be like this for the other way
Working on it
@trim trellis New "Event-free" approach
using UnityEngine;
public class Buttons : MonoBehaviour
{
public YourButton[] buttons; // My array of buttons, put in the order they have to be pressed in
private int index;
private bool[] buttonStates;
private bool wrongButtonPressed;
void Awake()
{
ResetAll();
}
void Update()
{
UpdateButtonsState();
}
private void UpdateButtonsState()
{
for (int i = 0; i < buttons.Length; i++)
if (buttons[i].isPressed && !buttonStates[i])
{
if (i != index)
wrongButtonPressed = true;
buttonStates[i] = true;
index++;
break;
}
if (index == buttons.Length)
{
if (wrongButtonPressed)
{
Debug.Log("Wrong combination, try again...");
ResetAll();
}
else
Debug.Log("Congrats you won!");
}
}
private void ResetAll()
{
index = 0;
buttonStates = new bool[buttons.Length];
for(int i = 0; i < buttons.Length; i++)
buttons[i].isPressed = false;
wrongButtonPressed = false;
}
}
It's a bit barbaric but it does the job
Just need to set isPressed = true; in OnTriggerEnter(); in your button class
Basically, you have an array of bool which keeps track of the current state of each button (whether it has been pressed or not), index keeps track of the last (correct) button that was pressed.
Every frame, we check the state of every button and see if it matches with the ones stored in buttonStates, if not, this means a button has just been pressed, in which case there are two cases : index = i (the correct button was pressed) or the opposite
so what happened with the event system?
no i mean this is fine
makes more sense tbh, i was kinda getting lost with the events
thanks
using UnityEngine;
public class Buttons : MonoBehaviour
{
public YourButton[] buttons; // My array of buttons, put in the order they have to be pressed in
private int index;
private bool wrongButtonPressed;
void Awake()
{
for (int i = 0; i < buttons.Length; i++)
buttons[i].onTrigger.AddListener(OnButtonPressed);
ResetAll();
}
private void ResetAll()
{
index = 0;
wrongButtonPressed = false;
}
private void OnButtonPressed(YourButton button)
{
int buttonIndex = -1;
for (int i = 0; i < buttons.Length; i++)
if (buttons[i] == button)
{
buttonIndex = i;
break;
}
if (buttonIndex == index)
{
index++;
if (index >= buttons.Length)
OnAllButtonsPressed();
}
else
wrongButtonPressed = true;
}
private void Reset()
{
wrongButtonPressed = false;
index = 0;
}
private void OnAllButtonsPressed()
{
if (wrongButtonPressed)
{
Debug.Log("Wrong combination, try again...");
Reset();
}
else
Debug.Log("Congrats you won!");
}
}
Version with events
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
public class YourButton : MonoBehaviour
{
public Button button;
public UnityEvent<YourButton> onTrigger;
private void Awake()
{
button.onClick.AddListener(TestMethod);
}
public void TestMethod()
{
onTrigger?.Invoke(this);
}
}
You need to add <YourButton> after UnityEvent and (this) after Invoke for it work
Use whichever you prefer, they should work the same
i think for now i will stick with the first code
I want to understand events better before using this
The reason why you'd avoid the first one is that using Update shouldn't be necessary
It's a negligeable performance hit in this case, but it's usually good practice not to use Update when not necessary
thanks for all the help I appreciate it
np