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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

How to make Marble sliding sound?

Discussion in 'Scripting' started by austint30, Aug 17, 2015.

  1. austint30

    austint30

    Joined:
    Jul 1, 2013
    Posts:
    72
    How do I detect if the ball is sliding? I want to play a sliding sound effect when the ball is moving slower or faster than it's rotation speed. How do I achieve this in C#?
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    Does your simulated marble actually roll? If so... check its angular velocity.

    If it doesn't roll, but instead just move with out rotation, but you're still using Rigidbody. Then check it's velocity.

    If you're moving it yourself, then check whatever value you store to represent it's velocity.

    When that velocity is in some range for a specific sound effect, make sure that sound effect is playing. If it's outside that range, and the soundeffect is playing, then stop it.
     
  3. austint30

    austint30

    Joined:
    Jul 1, 2013
    Posts:
    72
    My Marble does roll. It uses torque rotation and forces for air movement.
     
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    So, check its angularVelocity.
     
  5. austint30

    austint30

    Joined:
    Jul 1, 2013
    Posts:
    72
    I think it could probably be done by getting the speed, angularvelocity, and size of the ball and with some equation figure out if it is sliding or not.
     
  6. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    speed is just the magnitude of velocity, so if you have the velocity... you technically have the speed.

    Not sure what you need the size of the ball for.

    If it has velocity, in that the magnitude of the velocity is greater than 0, then it's sliding/moving. Unless you are using the word 'sliding' to mean something other than moving? In which case, you have to better define what it is you're talking about.
     
  7. austint30

    austint30

    Joined:
    Jul 1, 2013
    Posts:
    72
    The ball is going to be moving constantly as it is the player. The marble already has a sound that plays and adjusts the volume and pitch by the current velocity.

    I am making a game similar to a game called Marble Blast and that game plays a "squeaking" sound when the ball is on slippery surfaces or if the ball loses grip and spins. I'm trying to replicate that, but I have no idea how.
     
  8. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    OK, so we're operating with a very specific meaning for 'sliding'.

    If we want to calculate this, we need to define it very specifically.

    What is "sliding" on ice? Well... it could be defined as simply as "you're on ice", so you can play the sound when the ball is touching ice and in motion.

    If that's NOT the definition of it though, then we need a more specific definition.

    For example, maybe we define slipping as "when the angle between velocity and the direction of applied force is greater than X degrees for longer than Y seconds".

    We need a definition for what you consider "sliding".



    So, lets consider the 'loses grip and spins'. I suspect from this wording you mean that the ball is spinning, but that spin is not resulting in as much forward momentum as one would expect.

    Well... what we could do to determine this is.

    1) get the angular velocity and calculate the forward velocity that 'should' result. The linear speed is the angular speed around an axis * the radius in the direction of orthogonal to the axis. (angular speed should be in radians, convert if necessary)

    For example, if you have a sphere of radius 2. And the angular velocity is pi radians around the x axis. Because rotations around the x-axis rotate you in the direction of the z-axis, the linear velocity aught to be <0,0,2pi> per second.

    If the angular velocity has components around each of the three cartesian axes, than just calculate each individually and sum them together.


    2) get the actual velocity

    3) compare the magnitudes of both velocities. If they are not slipping they should be relatively equal (there's always error so they aren't going to be exactly equal). You should define a value of tolerance to consider 'slipping', and it should be a ratio not an exact number so that it scales appropriately with the increase of speed. Say maybe if the real velocity isn't within 10% of the estimated linear velocity, than we consider it slipping.

    4) when those conditions are not met (you're outside of the approved range), play the sound



    NOTE - I do not consider friction in this at all. I assume you're describing a perfect system where the friction is one to one allowing equal transfer of angular velocity to linear motion. And you're attempting to track the amount of motion loss in that transfer... which you call "sliding".
     
  9. austint30

    austint30

    Joined:
    Jul 1, 2013
    Posts:
    72
    Yes, this is what I'm trying to go for.

    I found this equation V = rs V is the calculated velocity. R is the radius, and S is the current angular velocity. I can probably use this in my code to do this!
     
  10. austint30

    austint30

    Joined:
    Jul 1, 2013
    Posts:
    72
    Alrighty, this is the code I've got so far:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class SlipDetectScript : MonoBehaviour {
    5.  
    6.     public AudioSource slipSound;
    7.     public SphereCollider SphereRadius;
    8.     public float CalculatedVelocity;
    9.  
    10.     // Use this for initialization
    11.     void Start () {
    12.  
    13.     }
    14.    
    15.     // Update is called once per frame
    16.     void Update () {
    17.         CalculatedVelocity = SphereRadius.radius * GetComponent<Rigidbody> ().angularVelocity.magnitude;
    18.     }
    19. }
    20.  
     
  11. austint30

    austint30

    Joined:
    Jul 1, 2013
    Posts:
    72
    Ok, I added an actualVelocity variable. During runtime, the calculated and actual velocity display the same number when the ball is rolling without sliding. When it does slide, the numbers become different. This seems to be going pretty well!
     
  12. austint30

    austint30

    Joined:
    Jul 1, 2013
    Posts:
    72
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class SlipDetectScript : MonoBehaviour {
    5.  
    6.     public AudioSource slipSound;
    7.     public SphereCollider SphereRadius;
    8.     public float CalculatedVelocity;
    9.     public float ActualVelocity;
    10.  
    11.     // Use this for initialization
    12.     void Start () {
    13.  
    14.     }
    15.    
    16.     // Update is called once per frame
    17.     void Update () {
    18.         ActualVelocity = GetComponent<Rigidbody> ().velocity.magnitude;
    19.         CalculatedVelocity = SphereRadius.radius * GetComponent<Rigidbody> ().angularVelocity.magnitude;
    20.  
    21.     }
    22. }
     
  13. austint30

    austint30

    Joined:
    Jul 1, 2013
    Posts:
    72
    Thanks for the help lordofduct! I now have a working script! It detects if the ball is slipping and plays the sound perfectly!

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class SlipDetectScript : MonoBehaviour {
    5.  
    6.     public AudioSource slipSound;
    7.     public SphereCollider SphereRadius;
    8.     public float CalculatedVelocity;
    9.     public float ActualVelocity;
    10.     public float SlipDifference;
    11.     public float SlipThreshold = 2;
    12.     public bool IsSlipping = false;
    13.  
    14.     // Use this for initialization
    15.     void Start () {
    16.  
    17.     }
    18.    
    19.     // Update is called once per frame
    20.     void Update () {
    21.         ActualVelocity = GetComponent<Rigidbody> ().velocity.magnitude;
    22.         CalculatedVelocity = SphereRadius.radius * GetComponent<Rigidbody> ().angularVelocity.magnitude;
    23.         SlipDifference = CalculatedVelocity - ActualVelocity;
    24.         if (SlipDifference > SlipThreshold) {
    25.             IsSlipping = true;
    26.         } else {
    27.             IsSlipping = false;
    28.         }
    29.     }
    30.  
    31.     void ConCollisionStay (){
    32.         if (IsSlipping == true) {
    33.             slipSound.Play ();
    34.         }else{
    35.             slipSound.Stop ();
    36.         }
    37.  
    38.     }
    39. }
    40.  
     
  14. austint30

    austint30

    Joined:
    Jul 1, 2013
    Posts:
    72
    This one works even better. It changes the volume of the sound instead.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class SlipDetectScript : MonoBehaviour {
    5.  
    6.     public AudioSource slipSound;
    7.     public SphereCollider SphereRadius;
    8.     public float CalculatedVelocity;
    9.     public float ActualVelocity;
    10.     public float SlipDifference;
    11.     public float SlipThreshold = 2;
    12.     public bool inAir = true;
    13.  
    14.     // Use this for initialization
    15.     void Start () {
    16.         slipSound.volume = 0;
    17.         slipSound.Play ();
    18.     }
    19.    
    20.     // Update is called once per frame
    21.     void Update () {
    22.         ActualVelocity = GetComponent<Rigidbody> ().velocity.magnitude;
    23.         CalculatedVelocity = SphereRadius.radius * GetComponent<Rigidbody> ().angularVelocity.magnitude;
    24.         SlipDifference = CalculatedVelocity - ActualVelocity;
    25.         if (inAir == false) {
    26.             slipSound.volume = SlipDifference / 50;
    27.         } else {
    28.             slipSound.volume = 0;
    29.         }
    30.     }
    31.  
    32.     void OnCollisionEnter (){
    33.         inAir = false;
    34.  
    35.     }
    36.  
    37.     void OnCollisionExit(){
    38.         inAir = true;
    39.  
    40.     }
    41. }
    42.  
     
    Last edited: Aug 18, 2015