Created
September 11, 2018 16:49
-
-
Save AaronV/3fd7cc22039cf34f536ab98db47d044a to your computer and use it in GitHub Desktop.
Detect missing methods in scene UnityEvents.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Based on code found here: https://stackoverflow.com/questions/42784338/unity-missing-warning-when-button-has-missing-onclick/42788400?noredirect=1#comment91506017_42788400 | |
*/ | |
#if UNITY_EDITOR | |
using System; | |
using System.Reflection; | |
using UnityEngine; | |
using UnityEngine.UI; | |
public class MissingOnClickDetector : MonoBehaviour | |
{ | |
void Awake() | |
{ | |
//Debug.Log("Class exist? " + classExist("ok.ButtonCallBackTest")); | |
SearchForMissingOnClickFunctions(); | |
} | |
void SearchForMissingOnClickFunctions() | |
{ | |
//Find all Buttons in the scene including hiding ones | |
Button[] allButtonScriptsInScene = Resources.FindObjectsOfTypeAll<Button>() as Button[]; | |
for (int i = 0; i < allButtonScriptsInScene.Length; i++) | |
{ | |
DetectButtonError(allButtonScriptsInScene[i]); | |
} | |
} | |
//Searches each registered onClick function in each class | |
void DetectButtonError(Button button) | |
{ | |
for (int i = 0; i < button.onClick.GetPersistentEventCount(); i++) | |
{ | |
//Get the target class name | |
UnityEngine.Object objectName = button.onClick.GetPersistentTarget(i); | |
//Get the function name | |
string methodName = button.onClick.GetPersistentMethodName(i); ; | |
//////////////////////////////////////////////////////CHECK CLASS/SCRIPT EXISTANCE///////////////////////////////////////// | |
//Check if the class that holds the function is null then exit if it is | |
if (objectName == null) | |
{ | |
Debug.Log("<color=blue>Button \"" + button.gameObject.name + | |
"\" is missing the script that has the supposed button callback function. " + | |
"Please check if this script still exist or has been renamed</color>", button.gameObject); | |
continue; //Don't run code below | |
} | |
//Get full target class name(including namespace) | |
string objectFullNameWithNamespace = objectName.GetType().FullName; | |
//Check if the class that holds the function exist then exit if it does not | |
if (!ClassExist(objectFullNameWithNamespace)) | |
{ | |
Debug.Log("<color=blue>Button \"" + button.gameObject.name + | |
"\" is missing the script that has the supposed button callback function. " + | |
"Please check if this script still exist or has been renamed</color>", button.gameObject); | |
continue; //Don't run code below | |
} | |
//////////////////////////////////////////////////////CHECK FUNCTION EXISTANCE///////////////////////////////////////// | |
//Check if function Exist as public (the registered onClick function is ok if this returns true) | |
if (FunctionExistAsPublicInTarget(objectName, methodName)) | |
{ | |
//No Need to Log if function exist | |
//Debug.Log("<color=green>Function Exist</color>"); | |
} | |
//Check if function Exist as private | |
else if (FunctionExistAsPrivateInTarget(objectName, methodName)) | |
{ | |
Debug.Log("<color=yellow>The registered Function \"" + methodName + "\" Exist as a private function. Please change \"" + methodName + | |
"\" function from the \"" + objectFullNameWithNamespace + "\" script to a public Access Modifier</color>", button.gameObject); | |
} | |
//Function does not even exist at-all | |
else | |
{ | |
Debug.Log("<color=red>The \"" + methodName + "\" function Does NOT Exist in the \"" + objectFullNameWithNamespace + "\" script</color>", button.gameObject); | |
} | |
} | |
} | |
//Checks if class exit or has been renamed | |
bool ClassExist(string className) | |
{ | |
Type myType = Type.GetType(className); | |
return myType != null; | |
} | |
//Checks if functions exist as public function | |
bool FunctionExistAsPublicInTarget(UnityEngine.Object target, string functionName) | |
{ | |
try | |
{ | |
Type type = target.GetType(); | |
MethodInfo targetinfo = type.GetMethod(functionName); | |
return targetinfo != null; | |
} | |
catch (AmbiguousMatchException) | |
{ | |
return true; | |
} | |
} | |
//Checks if functions exist as private function | |
bool FunctionExistAsPrivateInTarget(UnityEngine.Object target, string functionName) | |
{ | |
Type type = target.GetType(); | |
MethodInfo targetinfo = type.GetMethod(functionName, BindingFlags.Instance | BindingFlags.NonPublic); | |
return targetinfo != null; | |
} | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See this Stack Overflow page for more context about this code.