Playing a sound proportionally to the force of an impact, via C# script

Picked up Unity a couple of months ago, and have been working on a first project for a while now. Currently, i’m working on audio, and got stuck on making my collision sound volumes proportional to the force of the collision between the player (a cube) and another object (an obstacle). The problem here is, i’m using a script sitting on an empty game object to manage the sounds in the scene, that activates the actual sound playing script that sits on the player itself. Whenever I want to play a sound, i trigger the sound management script via whatever other script i want using “FindObjectOfType().Play(”[the name of the sound i want to play]");.

To set the sounds i want and create the editable window in the editor, I’m using the following piece of code:

[System.Serializable]
public class Sound
{
    public string name;

    public AudioClip clip;

    [Range(-1f, 1f)]
    public float pitch;

    [Range(0.1f, 3f)]
    public float volume;

    public bool loop;

    [Range(0f, 1f)]
    public float spatialBlend;

    [HideInInspector]
    public AudioSource source;

}

And the sound’s properties are set in the audio manager via the Unity editor, using the following code:

void Awake()
    {
        foreach (Sound s in sounds) 
        {
            s.source = gameObject.AddComponent<AudioSource>();
            s.source.clip = s.clip;
            s.source.volume = s.volume;
            s.source.pitch = s.pitch;
            s.source.loop = s.loop;
            s.source.spatialBlend = s.spatialBlend;
        }
    }

For the code that triggers the obstacle hitting sound, i’m using a collision detecting script that sits on the player:

    void OnCollisionEnter (Collision collisionInfo) //this is ran on any initial collision moment.
    {
        if (collisionInfo.collider.tag == "Obstacle") //if the object with which the player collided is an obstacle:
        {
            movement.enabled = false; //disables the player movement script
            FindObjectOfType<FailState>().crashedIntoObstacle(); //triggers the fail state of obstacle collision
            obstacleHitSound = Random.Range(1f, 3f);
            obstacleHitSound = Mathf.Round(obstacleHitSound);

            if (obstacleHitSound == 1)
            {
                FindObjectOfType<AudioManager>().Play("Obstacle Hit 1");
            }
            if (obstacleHitSound == 2)
            {
                FindObjectOfType<AudioManager>().Play("Obstacle Hit 2");
            }
            if (obstacleHitSound == 3)
            {
                FindObjectOfType<AudioManager>().Play("Obstacle Hit 3");
            }
        }

(I’m very cheaply randomizing the collision sound with “Random.Range(1f, 3f);”).

Essentially, what i want to do, is in the section that runs the “Play” code in AudioManager, take the current collision force using “collisionInfo.impactForceSum” (or something else; i don’t know if that will work), and set a volume value in “s.source.volume = s.volume;”, in the AudioManager script, proportional to that collision’s impact force. How can i modify this code to make so? i’m a complete begginer to the C# language and unity in general, and don’t even know where to start. Any help would be greatly aprecciated!

Oh, and the audio manager is 99% based of off a tutorial from Brackeys on youtube, since I had no idea on how to work with audio; this is basically my first game developing experience, so this is a big learning process for me.

To figure out the collision force you need to map the change in velocity over time.

The simplest way to do that is to, on collision, subtract the velocity in the last frame from the current velocity.

The more frames you buffer (across multiple positional data points) before during and after the collision the bigger a picture you can draw about the collision.


But they all really boil down to mapping velocity change over time.

Were you able to solve this?