Jump to content

Trying to control WHERE a sound plays...


Recommended Posts

So while I sleep tonight a pray for some sort of a moment of clarity I thought I'd drop this here in the hope that in my quite likely failure, some good a knowledgeable soul might offer me some insight...

I made a mod for docking sounds, it looks like this:

using System;using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;


namespace DockingSounds
{
class DPSoundFX : PartModule
{
[KSPField]
public string sound_docking = "DPSoundFX/Sounds/dock";
[KSPField]
public string sound_undocking = "DPSoundFX/Sounds/undock";
static bool eventAddedDocking = false;
static bool eventAddedUndocking = false;
static bool groupCreatedDocking = false;
static bool groupCreatedUndocking = false;
public FXGroup dockSound = null;
public FXGroup undockSound = null;

public bool createGroup (FXGroup group, string name, bool loop)
{
if (name != string.Empty) {
if (!GameDatabase.Instance.ExistsAudioClip (name)) {
Debug.LogError ("[DPSoundFX]ERROR - file " + name + ".* not found!");
return false;
}
group.audio = gameObject.AddComponent<AudioSource> ();
group.audio.volume = GameSettings.SHIP_VOLUME;
group.audio.rolloffMode = AudioRolloffMode.Logarithmic;
group.audio.dopplerLevel = 0f;
group.audio.panLevel = 1f;
group.audio.clip = GameDatabase.Instance.GetAudioClip (name);
group.audio.loop = loop;
group.audio.playOnAwake = false;
return true;
}
return false;
}


public void DPFXdock (GameEvents.FromToAction<Part, Part> partAction)
{
//Debug.LogError ("[DPSoundFX] Docking");
//Debug.LogError (" Docked FROM : " + partAction.from.vessel.vesselName);
//Debug.LogError (" Docked TO : " + partAction.to.vessel.vesselName);
//Debug.LogError (" Docked FROM ID: " + partAction.from.vessel.id.ToString ());
//Debug.LogError (" Docked TO ID : " + partAction.to.vessel.id.ToString ());

Debug.LogError ("[DPSoundFX] Docking " + partAction.from + " -> " + partAction.to);
Debug.LogError ("[DPSoundFX] Playing: " + sound_docking);

if (!partAction.from.Modules.Contains ("DPSoundFX"))
return;

if (!this.dockSound.audio.isPlaying) {
this.dockSound.audio.Play ();
}
}

public void DPFXundock (Part part)
{
Debug.LogError ("[DPSoundFX] Undocking " + part);
Debug.LogError ("[DPSoundFX] Playing: " + sound_undocking);

if (!part.Modules.Contains ("DPSoundFX"))
return;

if (!this.dockSound.audio.isPlaying) {
this.undockSound.audio.Play ();
}
}

public override void OnStart (PartModule.StartState state)
{
Debug.LogError ("[DPSoundFX] OnStart Called: State is " + state);

if (HighLogic.LoadedScene != GameScenes.FLIGHT)
return;

base.OnStart (state);

groupCreatedDocking = createGroup (dockSound, sound_docking, false);
groupCreatedUndocking = createGroup (undockSound, sound_undocking, false);


if (groupCreatedDocking && !eventAddedDocking) {
GameEvents.onPartCouple.Add (DPFXdock);
eventAddedDocking = true;
}


if (groupCreatedUndocking && !eventAddedUndocking) {
GameEvents.onPartUndock.Add (DPFXundock);
eventAddedUndocking = true;
}

Debug.LogError ("[DPSoundFX] OnStart Executed: State was " + state);
}

void OnDestroy ()
{
GameEvents.onPartUndock.Remove (DPFXundock);
eventAddedUndocking = false;
groupCreatedUndocking = false;

GameEvents.onPartCouple.Remove (DPFXdock);
eventAddedDocking = false;
groupCreatedDocking = false;
}
}
}

Trouble is this, I took out 4 rovers and placed them so that 2 were near one another in one location, and 2 were near one another but 500m away from the first 2.

I then couple the first two. "Cha-CHUNK!!" the docking sound plays, as expected.

I hit the "[" key and jump to one of the other pair of rovers and couple them. "Cha-CHUNK!!" the docking port sound plays, softly, 500m away at the location of the first pair of docked rovers. :(

I tried a number of ideas. No joy.

One thing I tried was printing the UID of "gameObject" and "partAction.to" and "partAction.from" in the DPFXdock routine. On the first docking the gameObject UID and partAction.from UID matched (which I expected), on the second docking, the gameObject UID was the same as the first docking, while the partAction.to and partAction.from were unique UIDs as one would expect.

This leads me to think that it has to do with the "gameObject" as it exists when DPFXdock is called, but that value (which I readonly) seems to get set and then stuck after the first time DPFXdock is called.

I'm rather stuck. I *think* my only option is going to be to create an empty gameObject, position it at the docking port, make the docking port it's parent, set an audio source to that object, set all the audio.property values, play() the clip, and then destroy the empty game object every time a port docks or undocks - but that seems wasteful...

Link to comment
Share on other sites

This is probably my fault for getting myself tied in a knot last time you asked for help. Your issue is that the part that responds is always the one which added the event, when there should be an event callback for each and every docking port in the scene.

tl;dr

Remove the bits that make only a single subscription to the docking GameEvent. That will give you a callback for each docking part. Inside that callback, only do something if this part is the initiator. That will probably fix it (your initial issue was the combination of not checking if it was the target part and not removing the callback in OnDestroy)

Link to comment
Share on other sites

Sonuva.... I pulled the conditional statements "if (groupCreatedDocking && !eventAddedDocking) {" and now I get sounds from all locations - only trouble is that now I get sound from all locations all the time LOL... now I have to sort out a conditional that inhibits all but the docked part from firing...

Still, it's progress!

Link to comment
Share on other sites

Final solution soon to be released:

//*******************************// Title: DPSoundFX
// Author: Ted Thompson
// License: CC BY-SA 4.0
// Created: June 19, 2015
//*******************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;


namespace DockingSounds
{
class DPSoundFX : PartModule
{
[KSPField]
public string sound_docking = "DPSoundFX/Sounds/dock";
[KSPField]
public string sound_undocking = "DPSoundFX/Sounds/undock";
public FXGroup dockSound = null;
public FXGroup undockSound = null;

//Create FX group for sounds
public bool createGroup (FXGroup group, string name, bool loop)
{
if (name != string.Empty) {
if (!GameDatabase.Instance.ExistsAudioClip (name)) {
Debug.LogError ("[DPSoundFX]ERROR - file " + name + ".* not found!");
return false;
}
group.audio = gameObject.AddComponent<AudioSource> ();
group.audio.volume = GameSettings.SHIP_VOLUME;
group.audio.rolloffMode = AudioRolloffMode.Logarithmic;
group.audio.dopplerLevel = 0f;
group.audio.panLevel = 1f;
group.audio.clip = GameDatabase.Instance.GetAudioClip (name);
group.audio.loop = loop;
group.audio.playOnAwake = false;
return true;
}
return false;
}

// Play docking sound
public void DPFXdock (GameEvents.FromToAction<Part, Part> partAction)
{
//Debug.Log ("[DPSoundFX] Docking");
//Debug.Log (" Docked FROM : " + partAction.from.vessel.vesselName);
//Debug.Log (" Docked TO : " + partAction.to.vessel.vesselName);
//Debug.Log (" Docked FROM ID: " + partAction.from.vessel.id.ToString ());
//Debug.Log (" Docked TO ID : " + partAction.to.vessel.id.ToString ());

// Does the "caller" even have a DPSoundFX entry in it's config? (KIS trigger workaround)
if (!partAction.from.Modules.Contains ("DPSoundFX"))
return;

// Is the "caller" the one that just docked? If not go away, you're not welcome here!!
if (Part.FromGO (gameObject).flightID != partAction.from.flightID)
return;

if (!this.dockSound.audio.isPlaying) {
this.dockSound.audio.Play ();
}
}

public void DPFXundock (Part part)
{
// Does the "caller" even have a DPSoundFX entry in it's config? (KIS didn't seem to trigger this, but it might avoid a false trigger from elsewhere)
if (!part.Modules.Contains ("DPSoundFX"))
return;

// Did the caller just undock? If not go home caller, your drunk.
if (Part.FromGO (gameObject).flightID != part.flightID)
return;

if (!this.dockSound.audio.isPlaying) {
this.undockSound.audio.Play ();
}
}

public override void OnStart (PartModule.StartState state)
{
Debug.Log ("[DPSoundFX] OnStart Called: State is " + state);

if (HighLogic.LoadedScene != GameScenes.FLIGHT)
return;

base.OnStart (state);

createGroup (dockSound, sound_docking, false);
createGroup (undockSound, sound_undocking, false);


GameEvents.onPartCouple.Add (DPFXdock);
GameEvents.onPartUndock.Add (DPFXundock);

Debug.Log ("[DPSoundFX] OnStart Executed: State was " + state);
}

void OnDestroy ()
{
GameEvents.onPartUndock.Remove (DPFXundock);
GameEvents.onPartCouple.Remove (DPFXdock);
}
}
}

Now gameobject behaves as I expected it to, it's the object that caused the call to start with. So checking it's UID (flightID in the code) against the part UID lets me eliminate all but the part that actually triggered the call. Problem solved.

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...