Friday, 28 September 2012

Some more Unity editor scripting goodies

Last post I showed you how to make some boring additions to the editor, this post I'll step it up to slightly-less-than-boring.

As I mentioned in a previous post, our game has triggers, and when you hit a trigger sound happens.  Normally, you might make these triggers into a prefab, and, every time you wanted to make a new one you'd create a new instance of the prefab, attach your sound, place the trigger, and adjust the collider.  In order to simplify this process I created a drag & drop area so you can drop in a sound file and it sets everything up such that you need only adjust the horizontal position and radius of the trigger.

Here is a the example code for a drag and drop GUI in the inspector.  Luckily, it's not very complicated.  First, we create a new Rect, which will serve as our drag and drop area, in this example it's 50 units tall and expands to the width of the inspector.  Then we capture the current Event, with Event.current.  This will tell us if the user is performing a drag operation.  There are lot a lot of Event Types, but we're only concerned with DragPerform and DragUpdated.

At this point we check if the user's drag is inside our Rect, otherwise we can ignore it.  This is done by calling Contains() on our Rect and passing it the mouse position.  Next I set the DragAndDrop.visualMode to DragAndDropVisualMode.Copy.  This little touch gives the user visual feedback that he's within the drag area bounds by changing the mouse cursor.  Finally, if the event is a DragPerform, as opposed to DragUpdated, then we call DragAndDrop.AcceptDrag(), which is probably important for something.

So now let's do something with our newly dragged object.

In this snippet I added a block of code to our switch statement.  The idea is that for each object that the user dropped, check if it's an audio clip.  If it is, create a new Trigger, make it a child of our TriggerContainer, set it's position to that of our container, and set it's audio clip to the one dragged.  To do this, first I load the prefab using AssetDatabase.LoadAssetAtPath() and pass it the path to our trigger relative to the root of the project.  Then, we simply Instantiate() a new one, set it's position to that of our container, and set it's parent to our container.  As you may notice, setting the parent/child relationship is done through the transform object, which isn't necessarily obvious.  Finally, I finish it off by grabbing the AudioSource object and setting it's clip to the one that was dragged in.

When you're done, it should look something like this:

and dragging in new AudioClips will create new Triggers:

So there it is.  I covered making a drag and drop GUI, loading assets from an editor script, and instantiating new parent/child objects.