Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question MissingMethodException: Method not found.

Discussion in 'Input System' started by JMCCK83, Sep 19, 2022.

  1. JMCCK83


    Oct 26, 2019
    I've written a basic script that allows the player to slow time while they are aiming a weapon. Everything works fine until I perform the aiming action. The character performs it but time doesn't change, and an error then appears in the console.

    It uses the Opsive UFPS asset for the character controller. I've posted this same issue on their forums but they say it's an Input System issue and not they're asset.

    Here's the code for it for the script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.InputSystem;
    6. public class PlayerUpgrades : MonoBehaviour
    7. {
    8.     // Bullet Time
    9.     [Header("Bullet Time")]
    10.     public bool bulletTimeActive;
    11.     public float bulletTimeSpeed;
    13.     public void OnFire2(InputAction.CallbackContext context)
    14.     {
    15.         if (bulletTimeActive)
    16.         {
    17.             if (context.started)
    18.             {
    19.                 Time.timeScale = bulletTimeSpeed;
    20.             }
    21.             else if (context.canceled)
    22.             {
    23.                 Time.timeScale = 1f;
    24.             }
    25.         }
    26.     }
    27. }
    And this is the error I get in the console:

    Code (CSharp):
    1. MissingMethodException: Method 'PlayerUpgrades.OnFire2' not found.
    2. System.RuntimeType.InvokeMember (System.String name, System.Reflection.BindingFlags bindingFlags, System.Reflection.Binder binder, System.Object target, System.Object[] providedArgs, System.Reflection.ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, System.String[] namedParams) (at <e40e5a8f982c4b618a930d29f9bd091c>:0)
    3. UnityEngine.SetupCoroutine.InvokeMember (System.Object behaviour, System.String name, System.Object variable) (at <4a31731933e0419ca5a995305014ad37>:0)
    4. UnityEngine.InputSystem.LowLevel.<>c__DisplayClass7_0:<set_onUpdate>b__0(NativeInputUpdateType, NativeInputEventBuffer*)
    5. UnityEngineInternal.Input.NativeInputSystem:NotifyUpdate(NativeInputUpdateType, IntPtr)
    The player object has the Player Input component on it, and the Fire2 action exists in the Action Map.

    Through testing the OnFire2 method it does work but only if I don't use a callback.

    Am I missing something else or have I made a mistake somewhere?
  2. JMCCK83


    Oct 26, 2019
    Managed to fix it myself.

    I changed the Behavior on the Player Input component to Invoke Unity Events. From there I just added the OnFire2 method to Fire2's callback. No more errors and the method works correctly.

    Sebasapk likes this.
  3. demented_hedgehog


    Nov 14, 2014
    I know this is the solution in this case but I can't understand why the designers at Unity would route the code around like this.. it's just more things that can break.
    Vaupell likes this.
  4. QuitsDoubloon


    Dec 23, 2018
    Yeah, I had a project last year that didn't have this problem. And now I will seemingly have to use this workaround as well. Quite weird and annoying.
    Btw a workaround is to also do InputAction.ActionMap.Action.started += function
    works with callback context aswell.
  5. zetarov


    Nov 27, 2019
    For anyone still searching for a solution close to what the send event should perform, I use this method in my project. I share it there.

    I created a base class for behaviours that needs to use PlayerInput events. So your script needs to inherit this class in order to work and the Player Input components needs to have its behavior sets to "Invoke C Sharp Events".

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.InputSystem;
    4. // Base class for dispatching event of the PlayerInput component.
    5. [RequireComponent(typeof(PlayerInput))]
    6. public abstract class PlayerInputDispatcher : MonoBehaviour {
    7.     protected PlayerInput _playerInput;
    8.     public PlayerInput playerInput { get => _playerInput; }
    10.     private void OnEnable() {
    11.         _playerInput = GetComponent<PlayerInput>();
    12.         _playerInput.onActionTriggered += BroadcastAction;
    13.     }
    15.     private void BroadcastAction(InputAction.CallbackContext context) {
    16.         if (!_playerInput.isActiveAndEnabled) return;
    17.         SendMessage($"On{}", context, SendMessageOptions.RequireReceiver);
    18.     }
    19. }
    As an example, here is how I use it on a player component (very bare but still).

    Code (CSharp):
    2. // Base *example* class for a Character
    3. public class Character : PlayerInputDispatcher, GameInput.ICharacterActions {
    4.     public void OnCancelLaunch(InputAction.CallbackContext context) {
    5.         Debug.Log("OnCancelLaunch");
    6.     }
    8.     public void OnInvertCharacterBonuses(InputAction.CallbackContext context) {
    9.         Debug.Log("OnInvertCharacterBonuses");
    10.     }
    12.     public void OnMove(InputAction.CallbackContext context) {
    13.         Debug.Log("OnMove");
    14.     }
    16.     public void OnPrepareLaunch(InputAction.CallbackContext context) {
    17.         Debug.Log("OnPrepareLaunch");
    18.     }
    20.     public void OnUseCharacterBonus1(InputAction.CallbackContext context) {
    21.         Debug.Log("OnUseCharacterBonus1");
    22.     }
    24.     public void OnUseCharacterBonus2(InputAction.CallbackContext context) {
    25.         Debug.Log("OnUseCharacterBonus2");
    26.     }
    27. }
    Another thing you can note is that with the new input system you can take advantage of the class/interfaces generation, for my project it generates this particular interface
    . By adding it, I am sure I handle all the methods corresponding to each input properly.

    This interface is name that way because of those :
    • GameInput is the name of my generated class for the input actions.
    • Character is the name of the Action Maps I use for the input of my characters.
    Note that those parameters depends on your input actions configuration.

    PS : Unity may have a better way to do this, but this is a working solution so far.