I am writing some code to be fairly generic and can be used in different games. One of the things I am doing is providing a “rumbling sound” where you can specify an audio clip and motor frequency vales and I will do the vibration while the sound is playing. I will do this using the new InputSystem’s Gamepad object.
But I am trying to do a dynamic check for it that fails:
Type typeGamepad = Type.GetType(“UnityEngine.InputSystem.Gamepad”);
is returning null, even though I can check for it in the immediate window:
? UnityEngine.InputSystem.Gamepad
UnityEngine.InputSystem.Gamepad
base: UnityEngine.InputSystem.InputDevice
all: {UnityEngine.InputSystem.Utilities.ReadOnlyArray<UnityEngine.InputSystem.Gamepad>}
current: null
s_GamepadCount: 0
s_Gamepads: null
This is in a project that has the new input sytem installed and active input set to both. On another project with the same settings, I was able to vibrate the controller just going directly to Gamepad.current in code.
The call is on line 42 below. If you know the answer to this question, you might know whether what I am trying to do will work in Unity. If there is a reason it won’t, please let me know.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace MusicAndSFX
{
// class Rumble is for vibrating gamepads
// note that it only has static calls
public class Rumble
{
// object for gamepad, if there is one
private static object oController = null;
// method to invoke on object
private static MethodInfo methodSetMotorSpeeds = null;
// make sure we have called Init;
private static bool bInit = false;
// boolean to note we found InputSystem, defaults to true as we only want to set false once and check for that
private static bool bInputSystem = true;
// time we last checked for a gamepad. Start with -2 seconds so we will check right away
private static float timeLastCheckedForGamePad = -2.0f;
// InitRumble function instead of static constructor we only bother with it if SetMotorSpeeds is ever called
private static void InitRumble()
{
// if we already checked for InputSystem and didn't find it, that won't change
if (!bInputSystem)
return;
// check to see if we have initialized
if (bInit && oController != null)
return;
// note that InitRumble has been called
bInit = true;
// I nearly always use try/catch around Reflection
// in this case, the processing is optional anyway
try
{
// Basically a test to see if InputSystem is being used in this game
Type typeGamepad = Type.GetType("UnityEngine.InputSystem.Gamepad");
// if it is used, we will attempt to get the controller and the method for setting mtor speeds
bInputSystem = (typeGamepad != null);
if (bInputSystem)
{
// note that we found InputSystem - if we don't find a current controller, we still want to check at intervals
bInputSystem = true;
// note time we are testing
timeLastCheckedForGamePad = Time.time;
// try to get current gamepad
oController = typeGamepad.GetProperty("current", BindingFlags.Static | BindingFlags.Public).GetValue(null, null);
if (oController != null && methodSetMotorSpeeds == null)
{
// not really dependent on havingfound a controller, but pointless to do it if not
Type[] parameterTypes = new Type[] { typeof(float), typeof(float) };
// let's get ready to rumble! get the method call for setting motor speeds
methodSetMotorSpeeds = typeGamepad.GetMethod("SetMotorSpeeds", parameterTypes);
}
}
}
catch(Exception ex)
{
Debug.LogError("Exception in Rumble.Init " + ex.Message);
}
}
public static void SetMotorSpeeds(float lowFrequency, float highFrequency)
{
// make sure we have initialized; will short circuit if no gamepad
InitRumble();
try
{
// see if we have a controller and the method to call
if (oController != null && methodSetMotorSpeeds != null)
{
// call the gamepad's motor speed function
object[] parameters = new object[] { lowFrequency, highFrequency };
methodSetMotorSpeeds.Invoke(oController, parameters);
}
}
catch (Exception ex)
{
Debug.LogError("Exception in Rumble.SetMotorSpeeds " + ex.Message);
}
}
}
}