#Sahil

1 messages · Page 1 of 1 (latest)

blissful jay
#

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

trim trellis
#

yeah i figured

#

ok lemme try your way then

#

might as well learn it now so i can use it in the future

blissful jay
#

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

trim trellis
#

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?

blissful jay
#

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

trim trellis
#

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

blissful jay
#

Hmm let me see the code

trim trellis
#
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;
    }
blissful jay
#

No dot between UnityEvent and OnTrigger

trim trellis
blissful jay
#

Oh sorry, typo

trim trellis
#

ok its good now

#

right so now i need to invoke it in the trigger?

blissful jay
#

Yup

#

Although we will have to reformat the code a bit for the whole "reset" stuff, but our event will still be useful

trim trellis
#
private void OnTriggerEnter(Collider other)
    {
        OnTrigger.Invoke();
        button.Play("ButtonPressDown");
        buttonPressed = true;
    }

this right

blissful jay
#

Better to put it at the end

trim trellis
#

ok

blissful jay
#

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

trim trellis
#
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?

blissful jay
#

Are you not getting any errors?

#

Well no nvm it shouldn't

trim trellis
#

basically once all buttons are pressed, it should either open the door or reset the buttons if it was the wrong order

blissful jay
#

Or you should

trim trellis
blissful jay
#

How is your class called?

trim trellis
#

which class

blissful jay
#

The one with the OnTrigger event

trim trellis
#

public Button[] buttons;
like this

blissful jay
#

Hmm, might want to rename it to avoid confusion with Unity's built-in button, but it's okay

blissful jay
#

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

trim trellis
#

I thought its based on the order we put the buttons in the inspector?

blissful jay
#

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

trim trellis
#

👍

#

did you figure it out @blissful jay ?

blissful jay
#

yea, but UnityEvents are being annoying

vestal rampart
#

dat happens . . .

blissful jay
#

You apparently can't use static UnityEvents out of the box, you need to instantiate them

trim trellis
#

so what now

blissful jay
#

Ok, should be good now

vestal rampart
blissful jay
#

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);
    }
}
trim trellis
#

then wouldnt the first way be better

#

at least for this scenario

blissful jay
#

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

vestal rampart
#

i just hoped in, but what is the initial question or what they're trying to achieve?

trim trellis
#

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

blissful jay
#

Yeah, static events are not the best

#

Well, they are, but not for now

trim trellis
#

oh i would need to incrememnt

#

yeah im not sure how to proceed

blissful jay
#

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

trim trellis
#

so what happened with the event system?

blissful jay
#

Well, I removed it since it was becoming a pain

#

I can put it back if you want

trim trellis
#

no i mean this is fine

#

makes more sense tbh, i was kinda getting lost with the events

#

thanks

blissful jay
#
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

trim trellis
#

i think for now i will stick with the first code

#

I want to understand events better before using this

blissful jay
#

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

trim trellis
#

thanks for all the help I appreciate it

blissful jay
#

np