Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

WHOOSH sound when passing nearby objects

Discussion in 'Scripting' started by Cactus_on_Fire, Jan 5, 2015.

  1. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    Hey all.

    How can I play a whooshing sound when passing nearby objects ? I'm not good with coding at all, so the only way I can think of is making a huge sphere on the player that will act as a hitbox that will play an audio when it collides with objects and will reset after like a few milliseconds. Not an accurate solution, but close enough.

    Any other ideas on how to create such an effect ? If not, can you help me with how to make the sphere that will play an audio on collision ?
     
  2. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    8,935
  3. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    It's like a 3D city jumper where you pass through buildings and jump through the rooftops. So I'll just parent a sphere collider to the player with this JS. But how can I induce the audio ?
     
    Last edited: Jan 5, 2015
  4. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
  5. Barachiel

    Barachiel

    Joined:
    Nov 25, 2012
    Posts:
    147
    You can assign your audio clip by dragging it and dropping it in the inspector of your player object (or whatever your script is attached to) and it'll create the component it needs to use it. In your script you can just use audio.Play();

    To get a quick understanding of what you can do, check out the docs here:
    http://docs.unity3d.com/ScriptReference/AudioSource.html

    The entries for clip, isPlaying, Play, Pause, Stop and PlayOneShot are likely to be of most interest to you right now.
     
  6. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    It works kinda buggy. Sometimes it plays right, sometimes it delays, sometimes it doesn't play at all. But I think it can work if I specify which mesh the box should collide to play the audio. Can I do that ?
     
  7. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    You could raycast outward from the sides of the players head (ears) and check the current velocity of the player when you get a hit on the building layer. You can update a bool with that code and elsewhere play seamlessly looping audio as long as that bool is true.

    This will give you a good amount of control for passing by objects that have variable sizes, and only playing the sound when moving fast enough for it to occur.
     
  8. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    That's a great idea. It may even effect the doppler slightly for a sexier sound. The thing is, the mesh that it should whoosh when hit is a one single mesh, but it has gaps between so it can catch a break when going through. Although I have zero knowledge of coding and I can't really write such a script.
     
  9. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    raycasting and linecasting are pretty simple. If there is a gap / hole in the collider, the ray can go through and not detect anything.

    Code (CSharp):
    1. //assuming the layer for your structures is 10
    2.  
    3. Vector3 head = Camera.main.transform.position;
    4. Vector3 rightEarCheck = head + Camera.main.transform.right * min_distance_for_sound;
    5. RaycastHit hit;
    6. int layerMask = 1 << 10;
    7.  
    8. if(Physics.Linecast(head, rightEarCheck, out hit, layerMask))
    9. {
    10.     //set a bool true
    11.     //check hit variable for the distance of the hit to control volume / other details of the whoosh
    12. }
    13. else
    14. {
    15.     //set a bool false
    16. }
    17.  
    18. ...
    19.  
    20. if(boolName)
    21. {
    22.     if(!audio.isPlaying)
    23.     {
    24.         audio.Play();
    25.         audio.volume whatever affected by hit distance
    26.     }
    27. }
    --edit

    You can even make the audio sources 3D, so you can get the audio right in the player's ear with the correct direction. Doing so could also take place of adjusting the volume. Just set the audio source position to the hit.point from the linecast and the audio will get more near or far naturally. Here's a picture :p

    image.png
     
    Last edited: Jan 5, 2015
    magpie_games likes this.
  10. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    That's an awesome setup :D I think C sharp scripts needed the public class intro first so I added this :

    using UnityEngine;
    using System.Collections;

    public class WHOOSHAudioCollision : MonoBehaviour {

    and closed the caption with } but it gives an error as : Unexpected symbol 'if' in class, struct or interface member description. And gives an additional parsing error.

    Even if I dont add the monobehaviour it gives errors as : A namespace can only contain namespace declarations and again a parsing error.
     
  11. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    That was a chunk of code, not a class. If you're writing in C# you'll need to learn the organization of it, heh :)

    In fact, the chunk isn't complete either. I set it up to linecast from the right "ear", the right side of where ever the camera is facing (assumed this game would be first person view). I made too many assumptions for that code to be of any use, but it's useful to you in seeing how a raycast can be used to solve this problem.
     
  12. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    I just realised that if you use raycasting you won't really get a whooshing sound, but a rather cutout sound. The audio will start the moment raycast hits something and stop when it loses the hitbox, which means it will play and stop the audio instantaneously and not produce a smooth whoosh that fades in and out.
     
  13. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    if there is a hit -> if play sound is false -> set play sound to true, play smooth fade in whoosh
    if there is a hit -> if play sound is true -> play continuous whoosh
    if there is no hit -> if play sound is true -> set play sound to false, play fade out whoosh

    You can make use of !audio.isPlaying to stop them from overlapping / interrupting each other.
     
  14. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    Can I make a time counter for hitboxes ? That would be the perfect solution.
    Like if there is collision, it will start from 0 and increase as long as there is collision. And it will start decreasing back to 0 when there is no hit. There should be a clamp for it so the counter can never go above 1 or below 0. And the counter will define the volume of the looping whoosh sound.
     
  15. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    8,935
    With 3D sounds volume will automatically increase/decrease by distance,
    so just need to start playing the looping sound (have the sound on that swoosh object)
    when you are getting close enough (for example with that trigger enter)
     
  16. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    That means I have to manually place like 300 audio sources :S, aside from that, this many audio running at the same time will definitely go hard on the processor, just doesnt seem like an efficient solution.
     
  17. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    Look at the picture I put on the forum, the hand drawn ms paint one lol. You can use just 1 (2 when you have both sides done) and position it where the ray hits. When you have a RaycastHit in your linecast or raycast, it contains a lot of information about what the ray hit.

    When ever there is a hit, set the audio source position to the hit.point :)
     
  18. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    It's good and well but I have zero knowledge of scripting D: Could you help me out with the script ?
     
  19. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    This early in the morning the best I can do is suggest that you read the unity docs for examples of using raycasts and raycasthits. Is your project in C# or JS?
     
  20. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    It's planned to be a PC / android game so both C# and JS should work I think.
     
  21. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    I would advise against using both. I don't know if there is a workaround being planned for Unity 5, but at present you cannot access a JS script from a C# script both ways. You can only have JS access C# or C# access JS depending on if you put your JS files into I think standard assets or plugins. Then JS gets compiled first, so it can access C#. Knowing both is 1 thing, mixing both is another.

    For this project and future ones, it is my advice to learn both, but pick one. The current favorite among developers is C#.
     
  22. Barachiel

    Barachiel

    Joined:
    Nov 25, 2012
    Posts:
    147
    Something like this would work. It's in Unityscript (or Javascript if you prefer), so let me know if you'd rather it in C#.

    Code (JavaScript):
    1.  
    2. var whooshLayerMask : LayerMask; //This is the layer mask for the raycast, so we don't hit things we don't want to.
    3. var whooshSound : GameObject; //This is the object with the AudioSource on it. It's what plays the sound.
    4. var whooshFadeTime = 1f; //How long it takes for the sound to fade in from 0.0 to 1.0.
    5. private var fadeTimer = 0f;
    6. private var isPlayingWhoosh = false;
    7. private var newWhooshRight : GameObject;
    8.  
    9. function WhooshNoise()
    10. {
    11.     var rayHit : RaycastHit;
    12.     if(Physics.Raycast(this.transform.position, this.transform.right, rayHit, 10, whooshLayerMask))
    13.     {
    14.             if(isPlayingWhoosh == false)
    15.             {
    16.                 newWhooshRight = Instantiate(whooshSound,rayHit.point,Quaternion.identity);
    17.                 newWhooshRight.name = "WhooshRight";
    18.                 isPlayingWhoosh = true;
    19.             }
    20.             if(isPlayingWhoosh == true)
    21.             {
    22.                 newWhooshRight.transform.position = rayHit.point;
    23.                 newWhooshRight.audio.volume = 0.0;
    24.                 if(newWhooshRight.audio.volume < 1.0)
    25.                 {
    26.                     fadeTimer += Time.deltaTime;
    27.                     newWhooshRight.audio.volume += (fadeTimer/whooshFadeTime);
    28.                 }
    29.             }
    30.     }
    31.     else
    32.     {
    33.         isPlayingWhoosh = false;
    34.         fadeTimer = 0.0;
    35.         if(newWhooshRight.audio.volume > 0)
    36.         {
    37.             fadeTimer += Time.deltaTime;
    38.             newWhooshRight.audio.volume -= (fadeTimer/whooshFadeTime);
    39.         }
    40.         Destroy(newWhooshRight,5.0);
    41.     }
    42. }
    You make an empty GameObject and place the audio clip for the whooshing noise on there, then drag that object onto the whooshSound variable in the inspector.
    You can place the object somewhere out of the way or just make it a prefab and drag that in instead.
    Make sure you set the layer mask from the drop down menu that pops up in the inspector, and that the buildings or other objects you want this detecting are on that layer. You can use more than one layer for the layer mask.
    Set the time you want the clip to take to fade in (and out) and when you approach within 10 units of a wall it instantiates the object with the sound on it, sets it's volume to 0, fades the volume in by the time you specified earlier and follows you along the wall.
    If it's a 3D sound, it'll get louder the closer you are.
    When your raycast no longer detects a wall, it leaves the object at the last known position and fades it back out before destroying it.

    This doesn't work perfectly, it's just a basic idea of one way you could go about it.
    If you're character is constantly moving (or even always at high altitude), I'd go about having the whooshing noise always playing at a low volume, and increase it with velocity and proximity to a wall. You could always have the audio source on your character normally, and move it to the side of the closest wall when detected to get the 3D sound effect.
     
    Tomnnn likes this.
  23. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
  24. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    Wow, thanks for taking the time to write all this !

    So I just tried this on a new scene. Made a character controller and put the JS on it. Made a GameObject and put the 3D looping whoosh sound. Then dragged the GameObject onto the JS input box where it asks for a game object. Then I created a cube and selected 'City' as the layer, and set 'City' in the JS layer selection. It didn't give any errors or anything but it didn't move the GameObject with the looping sound at all. I moved near the cube back and forth but no change. I could only hear the sound when I got closer to the game object itself.
     
  25. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    Try standing next to it and having it on your right. The code as is is checking for the right ear, basically. You can add a velocity check later for movement, what you want now is to test functionality.
     
  26. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    Nope, I walked all around it in all directions, but no dice. The game object is still just standing there.
     
  27. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    Try adding a debug to see what's running or not.

    Code (JavaScript):
    1. if(Physics.Raycast(this.transform.position, this.transform.right, rayhit, 10, whooshLayerMask))
    2. {
    3.     Debug.Log("Hit a wall on the right");
    4. }
    Don't replace the code, just add this 1 line on the top. If you see output in your console, it is running and the problem is elsewhere. If you see nothing, there is an issue in the raycast. I've only used int layer masks, I didn't know there was a layermask type. If you make this change and get no output, try changing

    Code (JavaScript):
    1. var whooshLayerMask : LayerMask;
    to

    Code (JavaScript):
    1. var whooshLayerMask : int;
    and set the mask. What layer is your building mesh? If it's layer 10, set your layer mask like so

    Code (JavaScript):
    1. whooshLayerMask = 1 << 10;
     
    Barachiel likes this.
  28. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    Yep the it's the 10th layer. Tried everything above but no luck :( Even the debug log didn't show up a single message.
     
  29. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    would you mind posting the entire JS file, in a code tag?
     
  30. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    Code (JavaScript):
    1.     var whooshLayerMask = 1 << 10;
    2.     var whooshSound : GameObject; //This is the object with the AudioSource on it. It's what plays the sound.
    3.     var whooshFadeTime = 1f; //How long it takes for the sound to fade in from 0.0 to 1.0.
    4.     private var fadeTimer = 0f;
    5.     private var isPlayingWhoosh = false;
    6.     private var newWhooshRight : GameObject;
    7.    
    8.     function WhooshNoise()
    9.     {
    10.         var rayHit : RaycastHit;
    11.        
    12.            if(Physics.Raycast(this.transform.position, this.transform.right, rayHit, 10, whooshLayerMask))
    13.     {
    14.         Debug.Log("Hit a wall on the right");
    15.     }
    16.        
    17.         if(Physics.Raycast(this.transform.position, this.transform.right, rayHit, 1000, whooshLayerMask))
    18.         {
    19.                 if(isPlayingWhoosh == false)
    20.                 {
    21.                     newWhooshRight = Instantiate(whooshSound,rayHit.point,Quaternion.identity);
    22.                     newWhooshRight.name = "WhooshRight";
    23.                     isPlayingWhoosh = true;
    24.                 }
    25.                 if(isPlayingWhoosh == true)
    26.                 {
    27.                     newWhooshRight.transform.position = rayHit.point;
    28.                     newWhooshRight.audio.volume = 0.0;
    29.                     if(newWhooshRight.audio.volume < 1.0)
    30.                     {
    31.                         fadeTimer += Time.deltaTime;
    32.                         newWhooshRight.audio.volume += (fadeTimer/whooshFadeTime);
    33.                     }
    34.                 }
    35.         }
    36.         else
    37.         {
    38.             isPlayingWhoosh = false;
    39.             fadeTimer = 0.0;
    40.             if(newWhooshRight.audio.volume > 0)
    41.             {
    42.                 fadeTimer += Time.deltaTime;
    43.                 newWhooshRight.audio.volume -= (fadeTimer/whooshFadeTime);
    44.             }
    45.             Destroy(newWhooshRight,5.0);
    46.         }
    47.     }
     
  31. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    I figured as much :p

    I'm not great with JS, but that code looks correct. Where is it being called? You have defined it, but that's all I see, unless it's called in another class.
     
  32. Barachiel

    Barachiel

    Joined:
    Nov 25, 2012
    Posts:
    147
    The original object with the sound on it that you made isn't the one you want to be listening to at all, or anywhere near, just in case that's what's happening here. The script makes a new version of it and controls it at the point the ray intersects.
    Do the objects on the City layer have a collider?

    I also didn't write it with switching buildings without a break between raycast hits, so if the ray is hitting something on the City layer and then starts hitting a different object also on the City layer, without hitting nothing in between, the code won't work as intended. This is also why I kept the ray fairly short, at 10 units instead of 1000. =P

    As for the LayerMask type, it works the same as defining a layer the way you are now, but gives a handy dropdown menu in the inspector just like the camera has.

    Lastly, as Tomnnn says, you need to call that function somehow. This one is on me as I forgot to mention it in my original post though you'd said you were new to this. Custom functions like this don't just run automatically, they have to be told when to run, and how.
    For now, just put
    WhooshNoise();
    in the update function so that it's always being called.
     
  33. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    Yep, the buildings have mesh colliders. I tried with different ray lengths as well incase the map size was relatively out of proportion.
    So should I simple slap the 'WhooshNoise();' at the top ?
     
  34. Barachiel

    Barachiel

    Joined:
    Nov 25, 2012
    Posts:
    147
    It doesn't really matter where the function is (so long as it isn't inside another function).
    Make sure you have the Update function in there and call WhooshNoise from there.
    Something like this:
    Code (JavaScript):
    1. function Update()
    2. {
    3.     WhooshNoise();
    4. }
    Also, the scale used with these things, such as ray lengths and the like, can be checked by creating a basic cube. The primitive cube Unity provides is 1 unit high, wide and long.
     
    Tomnnn likes this.
  35. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    That's what I was getting at. There's a definition but not call to the function. Seems rather elementary, no? Maybe this isn't the best first task :p
     
  36. Barachiel

    Barachiel

    Joined:
    Nov 25, 2012
    Posts:
    147
    When I first started I dived in headfirst as well. Maybe not the best way to introduce yourself to coding, but it sure is fun. =P
     
  37. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    I start each language with tic-tac-toe lol. Maybe mr cactus would care to try getting used tot he 4.6 ui by making tic-tac-toe instead of building a dynamic ambient noise component for a beginning project?
     
  38. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    Added the update function, still no luck :( Although now the debug log says ''Null reference Exception"

    I'm a visuals guy, the code is always handled by someone else. But this is a personal project so I thought this was an easy task to handle without diving into the world of coding. I'd rather outsouce these small problems instead of getting into scripting at all.
     
  39. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    It seems simple enough. You could post your game in the job section and offer someone $2-10 to just make a full working example for you :D I don't think you can post the offer amount in the forums, but if you make it sound simple enough people will kinda get the idea.

    Null reference exception is a step in the right direction - the console has output! Double click on that line and paste here the line of code mono highlights.
     
  40. Barachiel

    Barachiel

    Joined:
    Nov 25, 2012
    Posts:
    147
    If it's something small you could always upload your project to dropbox or something and I'll be happy to have a tinker.
     
    Tomnnn likes this.
  41. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    Or that :D
     
  42. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
  43. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    Still can't figure it out the Null Reference issue.
     
  44. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
     
  45. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    WHOOSH code.WhooshNoise () (at Assets/WHOOSH code.js:54)
     
  46. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    Great, now post the source for that and we'll have a look at line 54 :D
     
  47. Cactus_on_Fire

    Cactus_on_Fire

    Joined:
    Aug 12, 2014
    Posts:
    675
    I posted above, incase you missed here it is.

    Code (JavaScript):
    1.       function Update()
    2.     {
    3.         WhooshNoise();
    4.     }
    5.  
    6.     var whooshLayerMask = 1 << 10;
    7.     var whooshSound : GameObject; //This is the object with the AudioSource on it. It's what plays the sound.
    8.     var whooshFadeTime = 1f; //How long it takes for the sound to fade in from 0.0 to 1.0.
    9.     private var fadeTimer = 0f;
    10.     private var isPlayingWhoosh = false;
    11.     private var newWhooshRight : GameObject;
    12.    
    13.     function WhooshNoise()
    14.     {
    15.         var rayHit : RaycastHit;
    16.      
    17.            if(Physics.Raycast(this.transform.position, this.transform.right, rayHit, 10, whooshLayerMask))
    18.     {
    19.         Debug.Log("Hit a wall on the right");
    20.     }
    21.      
    22.         if(Physics.Raycast(this.transform.position, this.transform.right, rayHit, 1000, whooshLayerMask))
    23.         {
    24.                 if(isPlayingWhoosh == false)
    25.                 {
    26.                     newWhooshRight = Instantiate(whooshSound,rayHit.point,Quaternion.identity);
    27.                     newWhooshRight.name = "WhooshRight";
    28.                     isPlayingWhoosh = true;
    29.                 }
    30.                 if(isPlayingWhoosh == true)
    31.                 {
    32.                     newWhooshRight.transform.position = rayHit.point;
    33.                     newWhooshRight.audio.volume = 0.0;
    34.                     if(newWhooshRight.audio.volume < 1.0)
    35.                     {
    36.                         fadeTimer += Time.deltaTime;
    37.                         newWhooshRight.audio.volume += (fadeTimer/whooshFadeTime);
    38.                     }
    39.                 }
    40.         }
    41.         else
    42.         {
    43.             isPlayingWhoosh = false;
    44.             fadeTimer = 0.0;
    45.             if(newWhooshRight.audio.volume > 0)
    46.             {
    47.                 fadeTimer += Time.deltaTime;
    48.                 newWhooshRight.audio.volume -= (fadeTimer/whooshFadeTime);
    49.             }
    50.             Destroy(newWhooshRight,5.0);
    51.         }
    52.     }
    53.  
    There's also the whole scene as a prefab, few posts above.
     
    Last edited: Jan 11, 2015
  48. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    Oops, I assumed there were updates or something.

    I don't know how strict unity-js is, but the issue could be trying to destroy newWhooshRight whether it exists or not ;) In what you posted there on line 50, there is an assumption without a check that newWhooshright exists. You defined it, but you can't access properties of it or destroy it if it is null already. Any one of those lines that access it without checking if it's null could be causing the error. At least, my C# instincts feel that way.