Inactive GameObject in CallbackContext

I’m currently using the new Input System, and I’ve bound the “esc” key to a callbackcontext method, which i declared in the player Input component. The GameManager script exists on a different gameobject than the one I’m showing here that has the player input component, if that’s important to note.

Here’s the code for the method, the code seems to throw an error when it checks _antiDoubleCallCoroutine, because it says that the GameObject “GameManager” is “inactive”, and when I do Debug.Log for property “isActiveAndEnabled” on GameManager, it returns false. This confuses me because the object is active in the inspector, and there’s never any code that disables the GameManager.

image

The GameManager is a prefab, and also utilizing a semi-singleton pattern, where there’s one static variable of type GameManager, named gm. when I instead replace the code with gm followed by the method or variable, then it seems to work, for example gm.antiDoubleCallCoroutine, and gm.StartCoroutine() both don’t throw an error. Does anyone know why that is? If there is a workaround to this, please let me know as I have not found an answer yet.

image
image

(Somehow, this is fine and makes the code run)

Thank you so much in advance!

The GameManager script exists on a different gameobject

Then, the GameManager is not really a Singleton. gm has the GameManager assigned that was assigned last. EDIT: sorry, I cannot read :wink: I read “[it] exists on different game objects”.

I would recommend to enable “Error Pause” in the console. When you hit the error, look at your Pause callback in the inspector. Check if the GameManager reference still exists, and if so, if the assigned Game Manager is really active / enabled.

That really sounds like your code is running on a different instance of the GameManager than gm.

Try:

public void PauseGame(InputAction.CallbackContext context) {
    if (context.performed) {
        Debug.Log(this == gm);
        Debug.Log(this.GetInstanceID());
        Debug.Log(gm.GetInstanceID());
    }
}

Could it be that you have several instances of the PlayerInput component in your scene? One giving the error and another one that doesn’t?

1 Like

Yeah absolutely, which is super confusing to me since I specifically tried to prevent that by assigning “this” to the singleton instance

Here are the results of my debugging, this is not equal to the instance, and the instance IDs are different. Furthermore, yes you are right I have several instances of PlayerInput in my scene. The reason being for local multiplayer and the same Callback context is also on the other PlayerInput component, which is controlled via the arrow keys on a keyboard, I wanted to make it so that either player could pause the game with “esc”, however because one key press registered as two, since the esc key is put into both control schemes. I understand this is a convoluted way of handling two inputs as one preferably, however I wasn’t sure of any other way to do this, could that be causing the problem? I realized I over engineered, there’s one escape key on a keyboard, not two, so I’d just have to assign the escape key to an input in just one of the control schemes and that would be it. Do you think this would be one of the contributing factors to the issue I’m having? or is it mostly dismissable due to it just performing an action twice?

Ok, so i made a new non-static variable of type GameManager named test, serialized it so i can see it in the inspector, assigned the GameManager to this, just like with gm, tried to log the context and if test was enabled this time, and I was able to get a new error, which is the second error in the image below. This was after I put on error pause to more clearly see the issue. The GameManager from what I can see in the inspector is still active, however the debugging says otherwise so that has me super stumped.

image


image
image
image

That sounds like you actually linked your action to your prefab and not to the instance in the scene. Prefabs are also objects, but they are not active in the scene and can not run coroutines. However you can call methods on those prefab objects.

Try adding a Debug.Log with a “context” argument inside your PauseGame method like this:

Debug.Log("PauseGame", gameObject);

When you do that you can now click on the log message in the console and Unity will highlight the context object in Unity. If this will ping the prefab in the project view, you have linked the wrong object. You have to link to an object in the scene.

Technically it would be fine to call methods on scriptableobject instances or prefabs, however you can not start coroutines in them since they are assets and not active in the scene. It all depends on your exact setup, but when the only issue is to start a coroutine, all you need is ANY active MonoBehaviour in the scene to “host” your coroutine. That can be any MonoBehaviour singleton in the scene (as long as it does not get deactivated as this will kill any running coroutines). The coroutine themselfs can be defined anywhere. It matters on what object you call StartCoroutine on. As I said, prefabs can not run coroutines, only prefab instances in the scene can.

1 Like

That makes a lot of sense, thanks for the help! Both of my players were prefabs and I believe back then I didn’t realize me not being able to assign an object in the scene to a prefab parameter was for a reason, so I assigned it to the GameManager prefab instead, not the instance in the scene. I now switched the parameters over to the GameManager in the scene and while it can’t be applied to the prefab, it now works.

1 Like