- Home /
How can I get a split-up sound to properly loop with an animation?
Hi, I'm working on a game, where the player picks up Trash cans, and empties the trash from them into a Trash Truck. One of the features of my game is that it has a lever on the back-side of the Trash Truck, that the user can interact with, that will play an trash-compacting animation on the Trash Truck, for it's Compactor. I have a sound that I want to play with this animation, it is the sound of a Trash Truck's Compactor, being used (all of the hydraulic sounds,),. This sound, I have split up into 3 different sections,;: The Start (Whirring Up Sound,), Sound, The Looping (Looping Hydraulic Whirring Sound,), Sound, and The End (Whirring Down Sound,), Sound. Essentially, what I want to happen is, the player left clicks the lever, the Start Sound plays. Then, the Looping Sound starts playing, and looping. Then, once the animation finishes, the Looping Sound stops looping, stops, and the End Sound plays.
The player can interact with the lever while this animation plays, so they could be right in the middle of the trash-compacting animation and click on the lever, and the animation reverses. I also want this change to reflect in the sound. Not in a sense that the sound will reverse, but that the sound's ends will be reversed, I guess, sort of. For example, the user is starting to compact the trash, they flick the lever, now the animation is reversing to the beginning. Once it gets to the beginning, it shouldn't play the start sound, it should play the end sound. Same with if the player decides to move back to the start while the animation is playing.
I am trying to write a script to achieve this, but I currently haven't been able to get it to work, completely. I can't seem to get the looping sound to play, and sometimes if the animation is playing forwards and I try to reverse the animation, going back to the beginning, both the end sound, and start sound, play, and loop, or both play, and then nothing plays after (Which is what should happen, minus the start sound playing,),. All in all, it is very confusing, and I'm tired of destroying my ears if it decides to play one of these sounds every frame, which is incredibly painful. I just want to get this to work. Here is my script, currently:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CompactorAudio : MonoBehaviour
{
[SerializeField] public AudioClip compactStart;
[SerializeField] public AudioClip compactLoop;
[SerializeField] public AudioClip compactEnd;
public AudioSource audioSource;
public AudioListener audioListener;
public bool startCompact;
public bool loopCompact;
public bool endCompact;
public bool doLoop;
public PlayerInteract playerInteract;
void Awake()
{
startCompact = false;
loopCompact = false;
endCompact = false;
doLoop = false;
audioSource.loop = false;
}
// Start is called before the first frame update
void Start()
{
audioListener = GetComponent<AudioListener>();
audioSource = gameObject.GetComponent<AudioSource>();
}
// Update is called once per frame
void Update()
{
if(playerInteract.animStatus == true)
{
//if(playerInteract.isInteract == true)
if (!startCompact && !loopCompact)
{
startCompact = true;
endCompact = true;
audioSource.clip = compactStart;
//audioSource.PlayOneShot(compactStart);
audioSource.Play();
}
//if (startCompact && !audioSource.isPlaying && !loopCompact /*&& playerInteract.animend.startMessage == "animmid"*/)
/*
{
audioSource.clip = compactLoop;
audioSource.loop = true;
audioSource.Play();
loopCompact = true;
endCompact = true;
}
*/
}
if(playerInteract.animend.endMessage == "animend" && endCompact == true)
{
audioSource.Stop();
audioSource.loop = false;
loopCompact = false;
startCompact = false;//New
audioSource.clip = compactEnd;
audioSource.PlayOneShot(compactEnd);
endCompact = false;
}
if (playerInteract.compactorAnim.GetFloat("speed") == -1.0f && !audioSource.isPlaying && !loopCompact || playerInteract.compactorAnim.GetFloat("speed") == 1.0f && !audioSource.isPlaying && !loopCompact)
{
audioSource.clip = compactLoop;
audioSource.loop = true;
audioSource.Play();
loopCompact = true;
endCompact = true;
startCompact = false;
}
if (playerInteract.compactorAnim.GetFloat("speed") == 0.0f && !audioSource.isPlaying && endCompact == true && playerInteract.animend.endMessage == "animend")
{
audioSource.Stop();
audioSource.loop = false;
startCompact = false;
loopCompact = false;
audioSource.clip = compactEnd;
audioSource.PlayOneShot(compactEnd);
endCompact = false;
}
if(playerInteract.compactorAnim.GetFloat("speed") == /*-1.0f*/ 0.0f && playerInteract.animend.startMessage == "animstart" && startCompact == false)
{
audioSource.clip = compactEnd;
audioSource.PlayOneShot(compactEnd);
startCompact = false;
loopCompact = false;
endCompact = false;
}
}
public void CompStart()
{
audioSource.Stop();
audioSource.loop = false;
audioSource.PlayOneShot(compactStart);
}
public void CompLoop()
{
if (!audioSource.isPlaying)
{
audioSource.Stop();
audioSource.loop = true;
audioSource.PlayOneShot(compactLoop);
}
}
public void CompEnd()
{
if (!audioSource.isPlaying)
{
audioSource.Stop();
audioSource.loop = false;
audioSource.PlayOneShot(compactEnd);
}
}
}
If anyone needs any more information, please, let me know! Thanks.
Answer by The-Aidency · Dec 05, 2020 at 06:20 AM
Woah! First of all, impressive work on that, I admire your ingenuity. :)
The best option for you would be to use events within the animation. Hope that helped. Good luck!
Thanks, this is the first compliment I've gotten. Glad to see someone interested!
I actually have animation events for the animation, that's what the animend.start$$anonymous$$essage and animend.end$$anonymous$$essage things are. Essentially, at the beginning of the animation, it's start$$anonymous$$essage == "animstart", then one frame after it, it's start$$anonymous$$essage == "animmid", then one frame before the end is end$$anonymous$$essage == "animmid", and the end frame is end$$anonymous$$essage == "animend". These are used to control when to stop the animation from playing so that it won't continue playing past the end, causing delay when the player wants to reverse the animation. The problem with trying to play these sounds with the animation, I think, is that the player might not want to play the entire animation, / interact / flick the lever before the animation finishes. In this case, won't it not properly finish? I don't know. I also don't want it to be that the start sound plays if it's being reversed to the beginning, it should play the end sound.
Or wait, maybe this would work... I don't know.
I'll try it, thanks!
Actually, I think that is the issue, the Start Sound is longer than a frame, so is all of them, so it wouldn't just play. I need it to be like, it'll play the start sound, and once the start sound finishes, if either the start$$anonymous$$essage or end$$anonymous$$essage == "animmid", then, play the loop sound. And then once it reaches the end going forwards, or reaches the start going backwards, have it stop looping, then stop the looping sound, and play the end sound.
Again, it seems like the way I'm doing it at least, it will never play the loop sound, and it plays the start and end sounds once reversed to the beginning, and loops them. And right now it won't play the end sound once the animation reaches the end going forwards, but it seems as if once you flick the lever, and reverse the animation, it will start playing the end sound.
Your answer
Follow this Question
Related Questions
Play audio.PlayOneShot() once in an Update() function 2 Answers
Multiple Cars not working 1 Answer
Trigger diferent sounds playing from the same object 1 Answer
Animation playing over and over 0 Answers
loop animation while audio is playing 0 Answers