Skip to content
DEV505 / Sound ManagerDOCUMENTATION

DEV505 / CODE RECIPE

Wait for clearance and launch on sound completion.

Keep a sequence alive while conditions are unmet, then use its matching Finished notification to start a following flight sound.

Start with Your first sound if you have not set up a sound scene before. Use a separate test scene with one enabled Sound Manager, generated Sound Keys, and one Audio Listener near the sound object. Add LaunchSequence and LaunchFlight from 10-Launch to the manager's Direct events list; these are the supplied .soundgraph assets under Assets/DEV505/SoundManager/Samples.

Save the complete code below as LaunchAfterSound.cs in Assets/Scripts. Wait for Unity to compile it, create an empty GameObject, and drag the script onto it. The filename must match the class name. Test one recipe component at a time so another demo controller does not compete for the same events.

Create an empty GameObject named Rocket and assign its Transform to Rocket. Start with Power 0, Pressure 0, and Clamps Open unchecked. Keep both objects near the listener.

In Play Mode, wait until the Sound Manager is ready. To run a listed test action, open the component's three-dot menu in the Inspector and choose that action. These are the script's ContextMenu methods. Your own code or a Unity UI Button can call its public methods too. Inspector edits made during Play Mode are temporary.

Choose Begin waiting for clearance. It should remain silent. Set Power to 0.8, Pressure to 0.1, and enable Clamps Open. You should hear the countdown and ignition, followed by the flight sound. Moving the Rocket Transform now moves the sound with it. This example does not animate the rocket itself.

Choose Cancel and stop to reset. Begin again with the clamps closed, then cancel before completion. Flight must not begin. Disabling the component also cancels the sequence, stops flight, and disposes the notification subscription.

The initial context supplies Power and Pressure as Floats and ClampsOpen as a Bool. Update sends later changes to the retained sequence. The authored condition requires Power at least 0.72, Pressure below 0.85, and open clamps.

The graph waits until those conditions pass, orders the counter setup, repeats countdown ticks, delays, and plays ignition. The whole play’s natural ending is reported as SoundNotificationKind.Finished.

The callback first matches the retained sequence handle. A Finished notification sets a pending flag; a different terminal outcome clears it. Update consumes the pending flag only when the active service is not paused and the Rocket still exists, then starts LaunchFlight following that Transform.

Clearing the sequence field before cancelling it prevents a later cancellation notification from being mistaken for an active launch request. Never treat every terminal notification as success: Cancelled and Failed do not mean that the sequence completed as intended.

Wait For Condition is an initial gate. Once it has released the countdown, lowering power or closing clamps does not rewind that gate. This small recipe demonstrates gating and completion only. The full Launch controller keeps checking safety afterward and aborts below Power 0.65, above Pressure 0.96, or with clamps closed.

Add those checks if your game needs them. The small component also omits pad machinery, venting, visual countdown, flame effects, and rocket motion. Its HasLaunched property becomes true after the flight sound is accepted; use the marked code location to start your own movement.

LaunchAfterSound.cs
using System;
using DEV505.SoundManager;
using UnityEngine;
public sealed class LaunchAfterSound : MonoBehaviour
{
[SerializeField] private Transform rocket = null;
[SerializeField, Range(0, 1)] private float power = 0f;
[SerializeField, Range(0, 1)] private float pressure = 0f;
[SerializeField] private bool clampsOpen = false;
private SoundHandle sequence;
private SoundHandle flight;
private IDisposable subscription;
private bool launchPending;
public bool HasLaunched { get; private set; }
private void OnEnable() => subscription = SoundBus.Notifications.Subscribe(OnSoundChanged);
[ContextMenu("Begin waiting for clearance")]
public void Begin()
{
if (!Application.isPlaying || !isActiveAndEnabled || sequence.IsAlive() || flight.IsAlive()) return;
var service = SoundServices.Current;
if (service == null || !service.Ready || !rocket) return;
launchPending = false;
HasLaunched = false;
var context = SoundPlayContext.At(transform.position, service.OwnerOf(this))
.With(SoundParameters.LaunchSequence.Power, power)
.With(SoundParameters.LaunchSequence.Pressure, pressure)
.With(SoundParameters.LaunchSequence.ClampsOpen, clampsOpen);
var result = SoundBus.Play(Sounds.LaunchSequence, context);
if (result.Accepted) sequence = result.Handle;
else Debug.LogWarning($"Countdown could not start: {result.Status}", this);
}
private void Update()
{
if (sequence.IsAlive())
{
SoundBus.SetFloat(sequence, SoundParameters.LaunchSequence.Power, power);
SoundBus.SetFloat(sequence, SoundParameters.LaunchSequence.Pressure, pressure);
SoundBus.SetParameter(sequence, SoundParameters.LaunchSequence.ClampsOpen, SoundValue.Bool(clampsOpen));
}
var service = SoundServices.Current;
if (!launchPending || service == null || service.Paused || !rocket) return;
launchPending = false;
sequence = default;
var context = SoundPlayContext.Following(rocket, service.OwnerOf(rocket.gameObject))
.With(SoundParameters.LaunchFlight.Thrust, 1f);
var result = SoundBus.Play(Sounds.LaunchFlight, context);
if (result.Accepted)
{
flight = result.Handle;
HasLaunched = true;
// Start your rocket movement here. Following updates audio position as you move it.
}
else Debug.LogWarning($"Flight could not start: {result.Status}", this);
}
private void OnSoundChanged(SoundNotification message)
{
if (!message.Handle.Equals(sequence)) return;
if (message.Kind == SoundNotificationKind.Finished) launchPending = true;
else if (message.IsTerminal)
{
sequence = default;
launchPending = false;
}
}
[ContextMenu("Cancel and stop")]
public void Cancel()
{
launchPending = false;
var oldSequence = sequence;
sequence = default; // Its later Cancelled notification cannot start a launch.
SoundBus.Stop(oldSequence, 0);
SoundBus.Stop(flight, 0);
flight = default;
HasLaunched = false;
}
private void OnDisable()
{
subscription?.Dispose();
subscription = null;
Cancel();
}
}

Read the demo walkthrough for the graph, parameters, controls, and Unity screenshots. The related API reference explains the calls used here. Return to all twelve recipes to choose another interaction.

This page imports the checked C# file directly. It was compiled against the documented Unity revision; its runtime checks and source hash are recorded in the documentation repository’s validation files.