Sound upon collision?

Hey all,

I know this has been posted before so I apologize for the repetition. However, I have come into a snag while creating my game. I have created a maze (the maze mesh was created in Blender) and want a “bump” sound to occur when my first person controller collides with it. I am new to Unity and coding in general and have tried various scripts from these forums and have consulted the documentation, but to no avail. I have a sound clip and have tried everything and am now getting very frustrated. Could there be a problem with the fact that my maze model was imported from Blender?

If anyone knows of a script that might work for this scene, I would be very appreciative!

Thank you!

audio.Play();

Would work. You have to create an AudioSource. Drag your sound into Unity if you haven’t already done it. Since the sound is directly linked with the maze you could attach it to that, or create a empty object. Add component audio/audio source. Then drag and drop your audio sound and play it with the play command within your desired function.

Note that you will probably want to turn off 3d audio.

Audio source found HERE on references.

Thanks Foestar, for your reply! But I am still running into issues. This is what I’ve done so far:

I have created an AudioSource to the maze, and added the soundclip to it (2D sound). In terms of the script, I added the script listed above to the inspector of the maze, also. No luck. Am I missing something blatantly obvious here?

I assume I have to add the “bump” script to the maze, and not to the first person controller, right?

Thanks again.

Whatever object your collision is connected to add the audiosource to that component and put the audio.Play in the collision function.

I added the Audiosource to the Maze, since that is the object that I want to set off the “bump” sound when my first person controller collides with it.

Sorry about this, but can you expand on what you mean by “play in the collision function”?

I added audio.Play(); in the object component. Thoughts?

Have you tried this code from doc:

(I deleted some code you probably dont need)

using UnityEngine;
using System.Collections;

public class Example : MonoBehaviour {
    void OnCollisionEnter(Collision collision) {

        if (collision.relativeVelocity.magnitude > 2)
            audio.Play();
        
        Debug.Log(collision.collider.name);
    }
}

You can also take this part away, or try smaller value:
collision.relativeVelocity.magnitude > 2

I added debug line (prints name of the collided gameobject to consol)
Debug.Log(collision.collider.name);
If you dont get any info to consol, there is something wrong with your collision. In general, to get collision info you need to have rigidbody component added to gameobject you have the collision script. If you are using character controller which doesnt use rigidbody, you can use OnControllerColliderHit.
more info: Unity - Scripting API: MonoBehaviour.OnControllerColliderHit(ControllerColliderHit)

Thanks Chelnok, but I’m getting this error message:

Assets/Bump_scipt.js(1,6): UCE0001: ‘;’ expected. Insert a semicolon at the end.

?

looks like you are using unityscript (javascript)… my example scripts are in C# (and not tested) Check the links from my prev post, docs have example code for both c# and us (js).

Hi Chelnok.

My mistake, I inputed the code again (this time in C#), and while the game runs, it doesn’t work. What else could be wrong?

To reiterate, here are my settings:

I have an Audiosource on my maze (mesh collider); does it need to be a rigidbody for this code to work? Can it have both a mesh collider AND a rigidbody component? The script above is also in the inspector for the maze (and not the first person controller). Is this correct?

As for the first person controller: are there any particular settings required?

Is there anything else I might be missing (audio settings, etc), that don’t have to do with the script?

Thanks so much again.

Did you add the sfx to the audio source?

By that, do you mean adding the actual sound file to the audiosource? If so, yes, the audiosource contains the soundfile.

Post your code using the code tags.

AudioSource.PlayClipAtPoint() is easy way to play one shot sounds. Below is simple example in javascript how it can be used to play collision sounds when a character controller hits walls. Just add the script to your character, and set the sound clip.

One trick to play good sounding collision sounds is to do a little filtering. For example the character controller will have collision on each frame when it tries to stay on ground. These are pretty easy to filter out using the hit.moveDirection.y. I’m also filtering out collisions which occur when the character is moving slowly by checking the character speed.

Next, you may still have multiple collision events happening per frame when sliding along walls.

One way to handle this is to keep track of the state if the character is colliding with wall or not. In the example, the character is treated to be colliding with wall if there has been a collision within the last 0.25 seconds. Try to set that to 0.0 to see how it affects the behavior when sliding along walls.

#pragma strict

public var bumpSound:AudioClip;

private var character:CharacterController;
private var characterCollided;
private var collisionDelay:float;

function Start () {
	character = GetComponent(CharacterController);
	characterCollided = false;
	collisionDelay = 0.0;
}

function Update () {
	if (characterCollided  collisionDelay <= 0.0) {
		// Character collided, and we're not in collision state, play sound.
		AudioSource.PlayClipAtPoint(bumpSound, transform.position);
	}
	// Update collision state.
	if (characterCollided)
		collisionDelay = 0.25;
	else
		collisionDelay = Mathf.Max(0.0, collisionDelay - Time.deltaTime);

	characterCollided = false;
}

function OnControllerColliderHit(hit:ControllerColliderHit) {
	// Skip collisions from below	
	if (hit.moveDirection.y < -0.3) 
		return;

	if (character.velocity.magnitude > 0.5) {
		characterCollided = true;
	}
}

Hi Mikko,

What you’re describing is exactly what I’m looking for. I do have one question (and I apologize, I am new to all this): when you say “set the sound clip”, what do you mean exactly?

Thanks so much for this.

The public variable:

public var bumpSound:AudioClip;

Will appear as a parameter in the editor UI when you add the component. Just drag a sound clip from your assets to the inspector UI and you’re done.

Note that some of the if statements above do not have their brackets in both sets of code.

As for the collision, all you have to do is add a collider to each object and check in an if statement if they collide like the above codes do. This kinda task would be more simple using the OnCollisionEnter function.

Ok, I have added the soundclip to the audiosource in the inspector. No dice :confused:

Foestar: can you be more specific as to the errors in the code?

My example assumes that your maze has a mesh collider, and that you are controlling your player using character controller and that the script I posted is added as component to the player game object. Just to triage things, if you add: Debug.Log(“Should be playing sound”); inside the if, just above the play sounds, do you see that text in the unity console when you move around in your scene?

Nope :confused:

But yes to everything in your first sentence.

Update:

After inputting the debug log, I am getting this error message (though, the game still runs):

UnassignedReferenceException: The variable bumpSound of ‘Thud_wall’ has not been assigned.
You probably need to assign the bumpSound variable of the Thud_wall script in the inspector.
UnityEngine.AudioSource.PlayClipAtPoint (UnityEngine.AudioClip clip, Vector3 position, Single volume) (at C:/BuildAgent/work/cac08d8a5e25d4cb/Runtime/ExportGenerated/Editor/BaseClass.cs:773)
UnityEngine.AudioSource.PlayClipAtPoint (UnityEngine.AudioClip clip, Vector3 position) (at C:/BuildAgent/work/cac08d8a5e25d4cb/Runtime/ExportGenerated/Editor/BaseClass.cs:762)
Thud_wall.Update () (at Assets/Thud_wall.js:35)

To clarify, my script is called “Thud_Wall” and the name of my sound clip is “Thud”.

Here is the code I have right now:

#pragma strict
public var bumpSound:AudioClip;


 


private var character:CharacterController;


private var characterCollided;


private var collisionDelay:float;


 


function Start () {


    character = GetComponent(CharacterController);


    characterCollided = false;


    collisionDelay = 0.0;


}


 


function Update () {


    if (characterCollided  collisionDelay <= 0.0) {


        // Character collided, and we're not in collision state, play sound.
Debug.Log("Should be playing sound");
        AudioSource.PlayClipAtPoint(bumpSound, transform.position);


    }


    // Update collision state.


    if (characterCollided)


        collisionDelay = 0.25;


    else


        collisionDelay = Mathf.Max(0.0, collisionDelay - Time.deltaTime);


 


    characterCollided = false;


}


 


function OnControllerColliderHit(hit:ControllerColliderHit) {


    // Skip collisions from below   


    if (hit.moveDirection.y < -0.3) 


        return;


 


    if (character.velocity.magnitude > 0.5) {


        characterCollided = true;


    }


}

Thoughts?