Please note that this post only concerns itself with missing scripts as a cause of deleting scripts. If they’ve gone missing because you moved them, you have to revert your changes in source control. Never move scripts outside of Unity (eg. in Visual Studio), as it will also break references.

Uh oh… Something’s Not Right.

If you’ve ever come across a missing script on a GameObject, you might have thought to yourself “Oh no… something is broken!“. And you’re right, something is not as it should be. I’ve come across this issue when I’ve deleted a script from the project view that was attached to some object in the hierarchy. Luckily, that means that the script is no longer needed (provided it was not deleted by accident, in which case you have to resort to source control), and as such, we can safely just remove the missing component. Clicking on the warning thrown in the console pings the object, and it is then simple to select it, right click and remove the missing script.

However, you might be unlucky that the deleted script used to reside on hundreds of GameObjects! That’s a lot of tedious clicking to be done, and it sure does tingle my editor scripting senses.

Editor Scripting to the Rescue!

Whenever I come across a task that bores me even before I start it, it’s a good sign that it’s because it needs automation! Automating boring and time consuming tasks is definitely something that tickles my fancy – not only because it is fun to kill off tedious, monotonous tasks for good, but also because it makes for a much better workflow in the long run!

Anyway, to get back on track, let’s assume that the script that is now missing was previously residing on a thousand different GameObjects (exaggeration get’s the point across – I hope you will never end in this scenario). In order to remove the missing script from one GameObject, we need to do the following actions:

  1.  Click on the warning thrown in in the console.
  2. Notice what object is pinged in the hierarchy, then click on it.
  3. Right click the missing script (or click the little cog icon in the top right corner).
  4. Click ‘Remove Component’.

In the nightmarish scenario where the script was on a thousand different GameObjects, that amounts to a staggering four thousand clicks to remove the annoying warnings (assuming you are not absolutely savage and just ignore them by filtering them out in the console). Wow.

Now you’re just making me angry. show me the money!

Okay, enough chatting about. Today I was in this very scenario (although less extreme), so I deviced a simple editor utility script to automatically select all GameObjects in the scene with a missing script, all by the click of a button!

This way, we can simply skip straight ahead to step 3. of the previous list, and this time, we won’t have to repeat the process! So let’s get our hands dirty. We’ll start by creating a new C# class to handle the functionality. I called mine ‘SelectGameObjectsWithMissingScripts’. “Short” and concise.

The entire thing is wrapped in a function called SelectGameObjects() , which we can call by heading to the top menu bar in Unity under tools > Select GameObjects With Missing Scripts, thanks to the [MenuItem("Tools/Select GameObjects With Missing Scripts")] attribute.
Note that we need to import UnityEngine.SceneManagement, since we want to search all objects in the current scene! We do this by first getting a reference to the current scene, after which we can find all the root GameObjects in that scene (those that are on the top level of the hierarchy). We’ll also initialize a list that will eventually hold all the GameObjects that we found had missing scripts on them.

Note that it’s a List<Object> and not a List<GameObject>. This is because we later want to edit what objects are selected in Unity, and we will do that through the Selection class. More on that later. For now, we’ll simply loop through all the root GameObjects and get all the Components attached to them. We can then loop through the Components, and check to see if any of them are null! If they happen to be, then we’ll add them to our objectsWithDeadLinks list! While we’re at it, let’s also print it to the console so we can see the name of all the accomplice GameObjects.

In order to select them in the editor, all we’ll have to do is simply modify the Selection.objects property! Since this property is of type Object[], we do this by converting our list to an array before assigning it.

Lastly, in the case that there are actually no GameObjects with missing scripts in the current scene, we’ll also account for that by printing a success message to the console. And that’s it! The final script can be seen below!

Conclusion

I hope you found this useful. It sure did end up saving me a lot of time in the end. There are a few things to be noted about this script, however. As you might know, multi-object editing is not allowed for objects that don’t share components. This means that if you have one GameObject with a MyScript Component, and another GameObject with a MyOtherScript component, and you then delete both scripts in the project view, both of these GameObjects would be selected using this tool, however, you would not be able to delete any of the missing scripts, since they are two different missing scripts. This is really annoying, and perhaps there is some sort of workaround for this. Unfortunately DestroyImmediate(currentComponent); doesn’t work, since the component is null. Until a clever solution rises to the surface, just make sure to do a quick check of missing components for each script that you decide to remove!

Thanks to /u/trojanfoe on reddit for tips on improving the script!