Hi to everyone guys !!!
I’ve just a thing to do but I’m not sure I did it in the best way: I’ve to play a single sound effect for different time lengths by looping the central part of the sound. This operation must be done in parallel with others operations or animations of various GameObjects in the scene.
There are 2 ways to do this:
- having 3 different files to combine
- having a single files to loop seeking the position of audio at need
My solution to way 1 (C# code) is:
using UnityEngine;
using System.Collections;
public class Loop3SoundsPlayer : MonoBehaviour {
// the array with the 3 files to play
public AudioClip[] sounds = new AudioClip [3];
// final length of audio
public float finalSoundLength;
// the length the loop must have to achieve the final sound length
private float loopLength;
// starting time of sound playing
private float startTime;
// flag to know if we need to continue to calculate the sound playing time
private bool soundPlaying = false;
void Start () {
loopLength = finalSoundLength - (sounds[0].length + sounds[2].length);
startTime = Time.time;
} // Start
void Update () {
if (soundPlaying) {
Debug.Log (Time.time - startTime);
} // if
} // Update
// called from another controller to start playing the sound
public void playSound () {
startTime = Time.time;
if (audio) {
playSoundCoroutineStart ();
} // if
} // playSound
private void playSoundCoroutineStart () {
audio.clip = sounds[0];
audio.loop = false;
soundPlaying = true;
audio.Play ();
Invoke ("playSoundCoroutineLoop", sounds[0].length);
} // playSoundCoroutineStart
private void playSoundCoroutineLoop () {
audio.clip = sounds[1];
audio.loop = true;
audio.Play ();
Invoke ("playSoundCoroutineEnd", loopLength);
} // playSoundCoroutineLoop
private void playSoundCoroutineEnd () {
audio.clip = sounds[2];
audio.loop = false;
audio.Play ();
Invoke ("stopTimer", sounds[2].length);
} // playSoundCoroutineEnd
private void stopTimer () {
soundPlaying = false;
} // stopTimer
} // Loop3SoundsPlayer
the previous controller must be used in couple with this one:
using UnityEngine;
using System.Collections;
public class MoveMe3 : MonoBehaviour {
public Loop3SoundsPlayer lsp;
private bool start = false;
void Update () {
if (Input.GetKey (KeyCode.Space)) {
start = true;
lsp.playSound ();
} // if
if (start) {
transform.localPosition += new Vector3 (0.1f, 0f, 0f);
Invoke ("stopMe", lsp.finalSoundLength);
} // if
} // Update
private void stopMe () {
start = false;
} // stopMe
} // MoveMe3
The effect is that, after pressing space, the GameObject will start to move and the sound will be played. The duration of GameObject movement is linked to the duration of the sound effect. as you can see the sound effect duration is precise by the order of 0.1 secs but I need it with a precision of 0.001 secs !!! My first try was to use a while(true) loop but all won’t work 'cause it wasn’t used as a thread. I know that the “Invoke” are not reliable because they are closely linked to the framerate but the code I’ve shown you was the best solution I was able to think.
For the second way I’ve tried a similar approach by using “AudioSource.time” variable but it doesn’t seems to work.
I tried this piece of code but the audio will always start form its zero position:
using UnityEngine;
using System.Collections;
public class SeekSoundPlaybackPosition : MonoBehaviour {
void Update () {
if (Input.GetKey (KeyCode.Space)) {
playSound ();
} // if
// Debug.Log ("audio time = " + audio.time);
} // Update
private void playSound () {
if (audio) {
audio.time = 1.74f;
Debug.Log ("audio time = " + audio.time);
// audio.Play ();
} // if
} // playSound
} // SeekSoundPlaybackPosition
It’s really probable that I’m missing or mistaking something, so… could you be so gentle to help me?
About the first way I’ve lots of doubts about it also if it seems to work correctly.
Please, feel free to comment and post your ideas or alternative solutions.
THANKS A LOT GUYS !!!