Button Mapping: Assign value to a variable once to reference a value in another script? [SOLVED]

So I’m trying to get my in-game button mapping system working and the way I want to do it is like this:

Inputs Script: assigns bools and floats to equal Inputs (for example: LH = Input.GetAxis(“Horizontal”); and pressAction = Input.GetButtonDown(“ActionButton”)).

PlayerInputs Script: assigns bools and floats to variables from the Inputs(^) script (for example: jumpPress = InputsScript.pressAction).

The reason I’ve done this is so that in the PlayerInputs script I could assing (e.g.) ‘jumpPress’ to be any variable from the Inputs script so as to make a button mapping system. That way the Inputs script refers to the inputs themselves and PlayerInputs decides which action is controlled by which input.

The only issue is that I have to state in the playerInputs script that (e.g.) ‘jumpPress’ is equal to ‘pressActon’ from the Inputs script. Essentially, each Update() is:

jumpPress = InputsScript.pressAction;

But I don’t know how to just set that ‘InputsScript.pressAction’ to a reference variable so that I only need to write that once and not hardcode jumpPress to that specific variable in another script.

Essentially what I want is this:

bool activeJumpButton;
    bool jumpPress;

    void Start(){
        activeJumpButton = /*reference to*/ InputsScript.pressAction;
    }

    void Update() {
        jumpPress = activeJumpButton;
    }

    void ChangeButton(bool buttonToChange, bool newInput) {
        buttonToChange = newInput;  //e.g. activeJumpButton = InputsScript.otherButton;
    }

If there any way to do this?

I’m guessing that InputScript.pressAction is a boolean?
Why not just remove the Start method and change the Update method to:

Update()
{
 jumpress = InputScript.pressAction;
}

That’s what I’m trying to avoid. I don’t want it to be hardcoded like that because I want to be able to change which bool in InputScript a variable (e.g. jumpPress) points to.

I’m not completely sure I understand what you are trying to achieve.

In the InputScript you check for the button input each frame right? If thats the case I would use delegates instead, and in the InputScript I would change what delegates are assigned to what buttons. In that case there would be no need to do Update() in the player input, instead just handle the action directly.

But following your way of thinking (as far as I understand) I would have a bool for each possible command in the input script. And then in the Input script change around what command bools are assigned to what buttons. instead of having activeJumpButton in the playerscript I would just say jumpPress = InputScript.jump;
Like this:

Class InputScript
{
    bool pressAction = Input.ActionButton
    bool jump;
  
    public void ChangeButton(bool buttonToChange, bool newInput)
    {
        buttonToChange = newInput;
    }
}

class PlayerInput()
{
  bool jumpPress;

  void Update() {
      jumpPress = InputScript.jump;
  }
}

What I’m trying to achieve is to basically instead of writing out ‘InputScript.whatever’ for each assignment I’d like a variable that references/points to it so that it is passed through ChangeButton() and is basically a much smaller script.

Like in my first example, I want a variable like ‘activeJumpButton’ that is always referencing a variable in InputScript without explicitly writing out what that variable is.


Essentially I just want startPress to print out (in Debug.Log(startPress)) the value of the bool that activeStartPress references in InputsScript without writing it out explicitly in Update(). Just one change in ChangeButton() whenever that’s called and that will set what activeStrartPress references.

There’s a mistake in the way you think.

First of all, the type ‘bool’ is a value type, not a reference type.
So you won’t have a reference to it, you only assign its value and that’s it. Based on that, you wouldn’t be able to tell which bool is currently set, the only thing you’ll see in your example is whether the one that provided the value was true or false.

That’s the first thing. Now if you change it so that you always pull the value of Input.pressAction, it wouldn’t work either, at least not the way you’d like to. That’s because the only information you’ll receive is either true or false, not the combination ‘that specific one of my N booleans’ was true/false.

In order to distinguish between the variables and its assigned values you need to access each of them directly (that’s what you’re trying to avoid, i know) or use a type that can represent all the different values.
First option allows to use the most simple types such as boolean, because you know have the additional information about which boolean you are about to check.
Latter option allows you to access a single variable (that’s closer to your needs) and get the state, but you now need to check all states. An enumeration is the best example for this one.
The principle is quite different, but the result will be all over the same. In both cases you have to check numerous states.

Now, @Kvart has also mentioned delegates which are a powerful tool and can probably used to achieve something that is much closer to your original idea, but you probably wanna have a look at some basics again (unless you were just simply confused in this case and generally know them).

Delegates are one answer.

The other possibility is to build in a misdirection layer between the two classes. This layer can then be set to point at which ever variable you want. It’s how I normally manage runtime configurable input. Delegates can also be used in this fashion.

There is also ways to achieve the same result with reflection.

Here is a basic delegate example

public static class Input {
    public static bool a;
    public static bool b;
}

public class InputUser {

    Func<bool> inputFunction;

    void Start (){
        inputFunction = () => return Input.a;
    }

    // You get the idea

}

I can’t get this line to work, unfortunately. If I remove ‘return’, I cannot assign the startPress (for example) in my PlayerInputs script to be this inputFunciton.

Why would you want to remove the return? You might need to wrap it in a code block. I’m a little rusty with the exact lambda syntax.

void Start (){
        inputFunction = () => {return Input.a;};
    }

^ This is the way to do it! :smile:

And the method to change the ‘inputFunction’ delegate is this:

void ChangeButton(ref Func<bool> boolToChange, Func<bool> newValue) {
        boolToChange = () => { return newValue(); };
    }

I’ve had to change all the bools in the InputsScript to be Funcs rather than just bools, but it works perfectly! :smile:
Essentially just pass through ‘inputFunction’ as:

ChangeButton(ref inputFunciton,  Inputs.button);
1 Like