In other words, can we define an asset, such as a sound file to play or a texture map to use–without dragging and dropping it in the interface?
For an example, if all 75 of our buttons use a single .ogg file, and they’re all controlled by the same script, can we just assign that .ogg file in the script rather than drag the same file to each button 75 times?
This functionality would be very useful to us quite often if it’s possible. Thanks!
You could probably make a prefab of a button with the sound attached, and then just change the text or texture on the button on a case-by-case basis. Sucks if you’ve already got the 75 buttons made and you have to retool them, but certainly will make it easier if you add more or want to make changes later.
I’d assign default properties for the script in this case. Select a script in your project view and check out the inspector.
-Jon
edit: Unity doesn’t allow you to find assets by code only because it needs to know what assets you are using in a scene so that it can only include required assets in a build.
Brilliant! It looks like I still have to go in and drag an AudioSource onto each button though. I feel bad asking for a way around that, because the whole drag-and-drop interface is the beauty of Unity. But for little ticky stuff like this, it’s easier to manage it all with code.
Yeah, indeed you would need* to do that IF you do use an AudioSource. Since your GUI sounds are most likely not positional 3D sounds… (heh!) what you could use is AudioSource.PlayClipAtPoint() in your GUI code.
*A thought is: you could use RequireComponent attribute on the GUI code class to require an AudioSource, and override the Reset function in your GUI code class, then assign the properties of the AudioSource component in there. Then maybe when you add your GUI script to an object it will automatically add the AudioSource component, and your Reset function will get called and automatically set up the clip in the AudioSource etc. I haven’t tried that, but I really want to automate GUI building stuff more in future games!
Ah, perhaps that PlayClipAtPoint is what I’m looking for. I basically just want a set-volume audio playback, regardless of where the camera is. In my last engine there was a separate kind of audio file for general audio playback like this and a second type for 3D spatial playback. I’m sure I’ll soon figure out how Unity does non-3D, GUI-type audio.
And I like the RequireComponent idea. I’ll have to mess with that as well. Sweet!
Well, stereo sounds are not positioned, and mono sounds are.
I don’t know of a way to properly tell AudioSource.PlayClipAtPoint not to attenuate a mono AudioClip, though. You can give it the position Camera.main.transform.position, but then if the camera moves quickly before the clip is done playing you’ll get some attenuation, I’d assume.
For me, personally, I think it’s easiest just to make short little gui bleeps stereo and be done with it.
You could also have a seperate gameObject and have the buttons call a method on a script attached to that object.
The script attached to the manager object could export a static variable, so the buttons would just have to call it like this:
function OnMouseUp() {
...
GUISoundManager.instance.PlayGUISound(GUISounds.MouseClick);
...
}
(Then ou just have to create a singleton class for the sound manager object called GUISoundManager, that has a method called PlayGUISound and an enum called GUISounds that is used to thell the sound manager what kind of sound it should play.)
So these solutions are going to help us workaround our button issues, but we’d still like to be able to reference objects in code for other reasons. For instance, we’d like to just specify which songs to play at various points in code.
Currently we do it like this:
var song1: AudioClip;
var song2: AudioClip;
. . .
audio.clip =song2;
audio.play();
(then we have to drag all the songs onto the game object).
What we’d like to be able to do is something like
audio.play(“mysong.ogg”);
I’m guessing that’s not really possible becaus assigning it to a game object at some point is how it gets registered as a game asset, but it would be helpful is there’s a way we can register it in code without actually attaching it to an object. (Although perhaps that’s just what we’re used to, and there’s a good reason to not let us do it this way).
The trick is to have a manager object with an array of AudioSources and an editor script that automatically assigns the array. Check the code in the above thread. It should be easy to adapt it to audio clips instead of textures.
When you have the array, and if you want to play one of the clips by name you could simply loop through them at Start and save them in a Hashtable:
var songs : AudioSource[]; // Automatically assigned by an editor script
private var m_songsHash : Hashtable;
function Start() {
m_songsHash=new Hashtable();
for(var song in songs) {
m_songsHash[song.name]=song;
}
}
funtion PlaySong(name) {
var song=m_songsHash[name];
if(song) {
AudioSource.PlayClipAtPoint(song, Vector3 (0, 0, 0));
}
}