RSS Feed

When to Use a ScriptableObject

May 6, 2018

When do we use a CustomAsset/ScriptableObject and when a Monobehaviour? Simply put, Monobehaviours in scenes are independent of each other. Scriptable objects are singletons. Each asset, referenced by name and class, is unique in the project. Any code that has access to a scriptable object can access the same data as every other across the project.

 

There is a caveat. At any time, if no game objects are live and referencing a scriptable object, then Unity is allowed to remove it from memory. It only matters if the object contains data that changes during runtime. In this case, use CustomAsset and mark it read/write. Read/write custom assets are never cleaned up unless they are persistent. In the latter case, they get restored the next time the asset is required.

 

The Askowl Custom Assets package has a CustomAsset called AudioClip. By adding a list of clips and setting a range of volume and pitch, you have an asset that can give a variation of sound that brings a game alive. Make Squeaky wheel sounds more realistic by not precisely repeating the sound. The same goes for gunshots, bird calls, axe strokes and practically any repetitive audio clip.

The problem happens when we want to play the sound. We need an audio source. If AudioClip were a Monobehaviour, we could find or create one on the same GameObject. If we pass it into the Play() function, the calling code has to know about an audio source which otherwise they do not need to know. It is wrong in so many ways. We have a tighter coupling, break the single responsibility principle and require users of the asset to write more supporting code.

 

We could create a matching MonoBehaviour that keeps a reference to AudioClip and finds an audio source using GetComponent<AudioSource>(). But then why use a ScriptableObject - except that each instance of the Monobehaviour requires an audio list and volume/pitch ranges. There is a more severe limitation in keeping the custom asset - there can only be one AudioSource. No good if it is to be attached to multiple boxes, birds or enemies.

Fortunately, Unity3d is mature. The answer is UnityEvent. Anywhere you want to play an audio clips custom asset, add:

 

[RequireComponent(typeof(AudioSource))]
public sealed class MyWorld: MonoBehaviour {

  [SerializeField] private AudioClips   audioClips;

  [SerializeField] private UnityEvent  audioClipsEvent;

  public void PlayAudioEvent() { audioClipsEvent.Invoke(); }

}

 

Using `RequireComponent` is optional, but it will load an AudioSource automatically when you add your MonoBehaviour to a GameObject.

 

In the example inspector the audio clips asset is reference twice - once to allow content editing and once for the event trigger. Again, this is only for convenience since you can edit the information directly on the asset.

 

 


 

Share on Facebook
Share on Twitter
Please reload

Featured Posts

My limited tests show that Dictionary is faster than `SortedList`. The latter uses `Array.BinarySearch` to find entries. I have read other performance...

How are C# Dictionaries so Fast?

August 27, 2018

1/5
Please reload

Recent Posts

April 12, 2018

Please reload

Archive
Please reload

Search By Tags
Please reload

Follow Us
  • Facebook Basic Square
  • Twitter Basic Square
  • Google+ Basic Square