To play music from one cube, then the cube has to finish playing before you can click it to play again :
#pragma strict
var Trigger : AudioClip;
var isPlayingAudio : boolean = false;
function OnMouseDown()
{
if (!isPlayingAudio)
{
isPlayingAudio = true;
audio.clip = Trigger;
audio.Play();
Debug.Log("audio is Playing");
Invoke( "AudioIsFinished", Trigger.length );
}
}
function AudioIsFinished()
{
Debug.Log("audio is Stopped");
isPlayingAudio = false;
}
To Do what you are suggesting of only having one audio but multiple cubes, I would do it totally differently :
- On one script, raycast from the mouse position.
- If music is not playing :
- for the cube that has been hit, assign an audioclip based on its name, and play it.
- Set boolean to isPlaying true so that no other cubes can play anything.
- same as above to reset the boolean to allow cubes to become playable again.
Did all that make sense?
Alternative 2 :
Actually, I finished it sooner than I thought! Scenario :
Multiple cubes are in the scene. When a cube is clicked, audio is played. No other cube can be clicked until the audio is finished.
There are some rules to make this work.
- name your cubes in this format : trackNN e.g. track01 track07 track10 track11 track19 track75 track99 . You can use a capitol T, but the number must be between 00 and 99. You must start at Track01, or it will break. If you dont use 0 in front of single digits it will break . So Track07 is fine, track14 also fine, track1 or Track5 will make it break.
- Create an empty gameObject. Attach the below script. (An AudioSource will be added when the script is attached). Let’s call it AudioManager
- Make all your music cubes children of AudioManager (drag and drop them on the empty object).
- In the Inspector of AudioManager, drop your sounds into musicTracks ( it will appear as Music Tracks ).
-
Important : you must have the same amount of clips as there are cubes, or it will break . The audio must be in the correct order e.g. for music cube 1 (called track01) the first audio in musicTracks will be associated with it. cube track02 is the second audio in musicTracks , etc.
If I have made this not too confusing, you should have no problems inplementing this. The good news is as long as you start your naming with track01 to track10, you can keep adding up to 99 cubes! just make the new cube a child of the AudioManager and drop the sound in the inspector.
Ok finally here’s the new script :
#pragma strict
@script RequireComponent( AudioSource );
public var musicTracks : AudioClip[];
private var musicManager : Transform;
private var musicCubes : Transform[];
var isPlayingAudio : boolean = false;
function Start()
{
audio.Stop(); // incase PlayOnAwake is ticked
// check there is music in the Inspector
if ( musicTracks.Length == 0 )
{
Debug.Log( " musicTracks are missing ..." );
}
// load all Music Cubes into array
SetupArrays();
}
function Update()
{
if ( Input.GetMouseButtonDown(0) && !isPlayingAudio )
{
CheckForMusicCube();
}
}
function SetupArrays()
{
musicManager = this.transform;
musicCubes = new Transform[ musicManager.childCount ];
var i : int = 0;
for ( var theTrack in musicManager )
{
musicCubes[i++] = theTrack as Transform;
}
}
function CheckForMusicCube()
{
// raycast to find next clicked cube
var ray : Ray = Camera.main.ScreenPointToRay( Input.mousePosition );
var hit : RaycastHit;
if ( Physics.Raycast( ray, hit, 1000 ) )
{
//Debug.Log( "Ray Hit " + hit.collider.gameObject.name );
var theName : String = hit.collider.gameObject.name;
//var theSubName : String = theName.Substring( 0, 5 );
//Debug.Log( theName + " : " + theSubName );
if ( theName.Substring( 0, 5 ) == "track" || theName.Substring( 0, 5 ) == "Track" )
{
//Debug.Log( theName.Substring( 5, 2 ) + " : " + parseInt( theName.Substring( 5, 2 ) ) );
// get clip from array based on clicked cube
var nextClipIndex : int = parseInt( theName.Substring( 5, 2 ) ) - 1;
var nextClip : AudioClip = musicTracks[ nextClipIndex ];
audio.clip = nextClip;
isPlayingAudio = true;
audio.Play();
//Debug.Log("audio is Playing");
Invoke( "AudioIsFinished", nextClip.length );
}
}
}
function AudioIsFinished()
{
//Debug.Log("audio is Stopped");
isPlayingAudio = false;
}
I have left lots of Debugs in there ready to be uncommented, for troubleshooting if needed. Constructive feedback is welcome. Have Fun =]
Alternative 3 :
If you want to just stop the current audio and play the new audio, you can modify the second example like this :
#pragma strict
@script RequireComponent( AudioSource );
public var musicTracks : AudioClip[];
private var musicManager : Transform;
private var musicCubes : Transform[];
function Start()
{
audio.Stop(); // incase PlayOnAwake is ticked
audio.loop = false; // incase loop is ticked
// check there is music in the Inspector
if ( musicTracks.Length == 0 )
{
Debug.Log( " musicTracks are missing ..." );
}
// load all Music Cubes into array
SetupArrays();
}
function Update()
{
if ( Input.GetMouseButtonDown(0) )
{
CheckForMusicCube();
}
}
function SetupArrays()
{
musicManager = this.transform;
musicCubes = new Transform[ musicManager.childCount ];
var i : int = 0;
for ( var theTrack in musicManager )
{
musicCubes[ i ] = theTrack as Transform;
i ++;
}
}
function CheckForMusicCube()
{
// raycast to find next clicked cube
var ray : Ray = Camera.main.ScreenPointToRay( Input.mousePosition );
var hit : RaycastHit;
if ( Physics.Raycast( ray, hit, 1000 ) )
{
//Debug.Log( "Ray Hit " + hit.collider.gameObject.name );
var theName : String = hit.collider.gameObject.name;
//var theSubName : String = theName.Substring( 0, 5 );
//Debug.Log( theName + " : " + theSubName );
if ( theName.Substring( 0, 5 ) == "track" || theName.Substring( 0, 5 ) == "Track" )
{
audio.Stop(); // stop the current track
//Debug.Log( theName.Substring( 5, 2 ) + " : " + parseInt( theName.Substring( 5, 2 ) ) );
// get clip from array based on clicked cube
var nextClipIndex : int = parseInt( theName.Substring( 5, 2 ) ) - 1;
var nextClip : AudioClip = musicTracks[ nextClipIndex ];
audio.clip = nextClip;
audio.Play(); // play the new track
}
}
}
Alternative 4 :
Here is how to check if the selected cube is the same as the last selected cube, if so then do nothing.
#pragma strict
@script RequireComponent( AudioSource );
public var musicTracks : AudioClip[];
private var musicManager : Transform;
private var musicCubes : Transform[];
private var lastHitCube : GameObject;
function Start()
{
audio.Stop(); // incase PlayOnAwake is ticked
audio.loop = false; // incase loop is ticked
// check there is music in the Inspector
if ( musicTracks.Length == 0 )
{
Debug.Log( " musicTracks are missing ..." );
}
// load all Music Cubes into array
SetupArrays();
}
function Update()
{
if ( Input.GetMouseButtonDown(0) )
{
CheckForMusicCube();
}
}
function SetupArrays()
{
musicManager = this.transform;
musicCubes = new Transform[ musicManager.childCount ];
var i : int = 0;
for ( var theTrack in musicManager )
{
musicCubes[ i ] = theTrack as Transform;
i ++;
}
}
function CheckForMusicCube()
{
// raycast to find next clicked cube
var ray : Ray = Camera.main.ScreenPointToRay( Input.mousePosition );
var hit : RaycastHit;
if ( Physics.Raycast( ray, hit, 1000 ) )
{
// Check if this is not the current selected cube
if ( hit.collider.gameObject != lastHitCube )
{
//Debug.Log( "Ray Hit " + hit.collider.gameObject.name );
var theName : String = hit.collider.gameObject.name;
//var theSubName : String = theName.Substring( 0, 5 );
//Debug.Log( theName + " : " + theSubName );
if ( theName.Substring( 0, 5 ) == "track" || theName.Substring( 0, 5 ) == "Track" )
{
// this is now the lastHitCube
lastHitCube = hit.collider.gameObject;
audio.Stop(); // stop the current track
//Debug.Log( theName.Substring( 5, 2 ) + " : " + parseInt( theName.Substring( 5, 2 ) ) );
// get clip from array based on clicked cube
var nextClipIndex : int = parseInt( theName.Substring( 5, 2 ) ) - 1;
var nextClip : AudioClip = musicTracks[ nextClipIndex ];
audio.clip = nextClip;
audio.Play(); // play the new track
}
}
}
}