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

How can I make objects fall at random speeds?

Discussion in 'Scripting' started by tomowale, Aug 30, 2016.

  1. tomowale

    tomowale

    Joined:
    Feb 14, 2015
    Posts:
    308
    Hey guys, I am making a game where silver , bronze and gold coins fall from the top of the scene and you have to collect the coins in a barrel without letting any fall to the ground. I've made pretty big progress and I have managed to get the coins to all fall from the top scene[via 3 empty game objects]. However, to make the game challenging, I want the coins to fall down at a random speed each frame. Although, I'm not sure how to go about it. Below is my current code for the silver , gold and bronze coins [they are all basically the same]. Any help is appreciated.Thanks in advance.

    Bronze Coin code.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class InstantiateBronzeCoin : MonoBehaviour {
    5.     public GameObject BronzeCoin;
    6.     private float SpawnBronzeCointimer = 2f;
    7.     // Use this for initialization
    8.     void Start () {
    9.    
    10.     }
    11.    
    12.     // Update is called once per frame
    13.     void Update () {
    14.         InstantiateBronzeCoin1();
    15.  
    16.     }
    17.  
    18.     void InstantiateBronzeCoin1()
    19.     {
    20.         SpawnBronzeCointimer -= Time.deltaTime;
    21.         if (SpawnBronzeCointimer <= 0)
    22.         {
    23.             Instantiate(BronzeCoin, new Vector3(-1.76f, 7.53f, -0.55f), Quaternion.identity);
    24.             SpawnBronzeCointimer = 2f;
    25.         }
    26.     }
    27. }
    28.  
    29.  
    Silver Coin code

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class InstantiateSilverCoin : MonoBehaviour {
    5.     public GameObject SilverCoin1;
    6.     private float SpawnSilverCointimer = 2f;
    7.     // Use this for initialization
    8.     void Start () {
    9.    
    10.     }
    11.    
    12.     // Update is called once per frame
    13.     void Update () {
    14.         InstantiateSilverCoin1();
    15.  
    16.     }
    17.  
    18.     void InstantiateSilverCoin1()
    19.     {
    20.         SpawnSilverCointimer -= Time.deltaTime;
    21.         if (SpawnSilverCointimer <= 0)
    22.         {
    23.             Instantiate(SilverCoin1, new Vector3(1.62f, 7.53f, -0.55f), Quaternion.identity);
    24.             SpawnSilverCointimer = 2f;
    25.         }
    26.     }
    27. }
    28.  
    Gold Coin code.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class InstantiateCoins : MonoBehaviour
    6. {
    7.     public GameObject GoldCoin;
    8.     private float SpawnGoldCointimer = 2f;
    9.  
    10.     // mess with the drag function on the rigidbodies of the coins so they fall slower
    11.     // Use this for initialization
    12.     void Start()
    13.     {
    14.  
    15.     }
    16.  
    17.     // Update is called once per frame
    18.     void Update()
    19.     {
    20.         InstantiateGoldCoin();
    21.     }
    22.  
    23.     void InstantiateGoldCoin()
    24.     {
    25.         SpawnGoldCointimer -= Time.deltaTime;
    26.         if (SpawnGoldCointimer <= 0)
    27.         {
    28.             Instantiate(GoldCoin , new Vector3(0,7.53f,-0.55f), Quaternion.identity);
    29.             SpawnGoldCointimer = 2f;
    30.         }
    31.     }
    32. }
    33.  
     
  2. ciaravoh

    ciaravoh

    Joined:
    Dec 16, 2009
    Posts:
    252
    Hello

    You may want to change the mass for the different coins in order to change their speed.
     
  3. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    assuming they're falling under their rigidbody gravity... if not, how are you moving the coins?
     
  4. tomowale

    tomowale

    Joined:
    Feb 14, 2015
    Posts:
    308
    Well , this may work but can I randomize the coins' mass' via script so the mass [ speed] changes each frame?
     
  5. tomowale

    tomowale

    Joined:
    Feb 14, 2015
    Posts:
    308
    The rigid bodies on the coins all have their gravity checked. I am moving the coins by hooking each coin script up to an empty game object. Which instantiates the coins at different positions , and then they fall via the gravity function on the RB component.
     
  6. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    As a student of physics I was very worried when you said changing the mass would change the fall speed (It doesn't work that way in the real world!). So testing it showed it definitely did not change the fall speed.
    What you want to do is change the Drag property of the rigidbody. Both RigidBody and RigidBody2D have a .drag property you can adjust. Setting it to 1 seems to be about half speed. 2 about 1/3 speed. its a float so you you probably want a random range between 0 and 2. Note: this will only slow them down.

    If you want to speed them up the solution is increase gravity itself overall. this will speed everyting up.. then you just slow things down based on this new speed. Physics.gravity = new Vector3 (0,-yourValue,0);

    This will cause all you coins to have differnent accelerations, but their accelerations will be constant. If you wanted to have an individual coin look like it was slowing down and speeding up, you'd want set each coin with a minDrag and a MaxDrag. Then each Update it would have a chance to pick a new drag in that range. this would cause it to look like the coin was speeding up or slowing down after it started falling.
     
  7. tomowale

    tomowale

    Joined:
    Feb 14, 2015
    Posts:
    308

    A bit confused. So if I set each coin script with a min drag and max drag , I know I would enter
    rb = GetComponent<Rigidbody>();. I would then access each rb's drag using rb.drag. But , how would I then make the Update function choose between a min and a max drag each frame to alter each coins speed? Something like this?

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class TestDragScript : MonoBehaviour {
    5.     public Rigidbody rb;
    6.     private float minDrag;
    7.     private float maxDrag;
    8.  
    9.     // Use this for initialization
    10.     void Start () {
    11.         rb = GetComponent<Rigidbody>();
    12.         minDrag = rb.drag;
    13.         maxDrag = rb.drag;
    14.     }
    15.  
    16.     // Update is called once per frame
    17.     void Update () {
    18.     // Now how would I get unity to choose a new drag each frame?
    19.     }
    20. }
     
  8. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    Code (CSharp):
    1. // We don't want to constantly change speeds.. just sometimes
    2. // this value will adjust how often that happens on avg;
    3. [Range(0.0f,1.0f)]
    4. public float speedChangeChance;
    5.  
    6. void Update()
    7. {
    8.             if (Random.Range(0.0f,1.0f) < speedChangeChance)
    9.             {
    10.                        rb.Drag = Mathf.Lerp(minDrag,MaxDrag,Random.Range(0.0f,1.0f));
    11.             }
    12. }
    So we want to make it so there is only a chance each update the speed changes.. that way it moves a little bit with the new speed each time. You can play with speedChangeChance, 0.0 would mean it never changes, 1.0 mean it changes nonstop. Mathf.Lerp picks a linearly interpolated value between MinDrag and MaxDrag based on a value betwen 0.0, and 1.0 we give it. 0.0 returns MinDrag, and 1.0 returns MaxDrag. We just give it a random value in that range.

    Now our coin will start falling and after a little bit of time, randomly get a new Drag and start falling at that speed. eventually it will trigger and change speeds again. and so on.
     
    Last edited: Aug 31, 2016
  9. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,727
    The problem with Unity is there is no gravity multiplier that can be assigned to each individual rigid body, unlike other game engines. This makes this challenging to do with rigidbodies. Personally, I would eliminate the use of gravity on these coins and manually control the y positions in a script, rather than trying to fight with the physics engine every frame.
    The drag is not meant to be used in this manner.
     
  10. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    Well after playing around some I noticed RigidBody2D (which I assume your using since it probably a 2D game with coins falling from the sky?) Has an extra property that RigidBody component doesn't. Gravity. This number defaults to 1 and affects how much gravity affects the component its attached to. You could use this instead of drag. The setup would be almost exactly the same.. MinDrag and Maxdrag would just be minGravity/maxGravity. The only advantadge of using .gravity instead of .drag is you wouldn't have to initially set Physics.Gravity. You would just manipulate how much gravity is affecting this directly. <1 would speed it up and >1 would make it go faster versus the default setting.

    @TTTTTa is right about 3d RIgidBody Component, but RigidBody2D do actual have a individual rigid body gravity multiplier
     
  11. tomowale

    tomowale

    Joined:
    Feb 14, 2015
    Posts:
    308
    I left home so I can't try out the code yet. However , by looking at takatok's code it seems like it works. In response to takatok and TTTTTa , my game is 3D so I don't think I could manipulate RB2D.

    Will try out the code soon. Thanks!
     
  12. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    Well even if you are 3d you can just do the initial idea of making Physics.gravity bigger than using the min/max drag idea.

    Also I made a mistake when i said:
    It definitely does NOT give a random value.. It gives a linearly Interpolated one based on the 3rd variable given. That is why *that* variable needs to be random. If you set the 3rd variable to 0.5 it will give you the exact middle between MinDrag and MaxDrag. I've edited so other people don't read the misinformation there.
     
  13. tomowale

    tomowale

    Joined:
    Feb 14, 2015
    Posts:
    308
    Played around a bit with the script and it doesn't seem to work. Maybe I'm doing something wrong? Should I just change each coins drag value and hope that is challenging enough?

    After a few tests , I think making the speed at which each coin falls , random ,may cause some issues

    Screenshot of coins is available
     

    Attached Files:

    Last edited: Aug 31, 2016
  14. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    I'd have to see your scripts to see whats going wrong.
     
  15. tomowale

    tomowale

    Joined:
    Feb 14, 2015
    Posts:
    308
    I attached this script to my silver coin object.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Dragscript : MonoBehaviour {
    5.     public Rigidbody rb;
    6.     private float minDrag;
    7.     private float maxDrag;
    8.     [Range(0.0f, 1.0f)]
    9.     public float speedChangeChance;
    10.     // Use this for initialization
    11.     void Start () {
    12.         rb = GetComponent<Rigidbody>();
    13.         minDrag = rb.drag;
    14.         maxDrag = rb.drag;
    15.     }
    16.    
    17.     // Update is called once per frame
    18.     void Update () {
    19.         if (Random.Range(0.0f, 1.0f) < speedChangeChance)
    20.         {
    21.             rb.Drag = Mathf.Lerp(minDrag, MaxDrag, Random.Range(0.0f, 1.0f));
    22.         }
    23.     }
    24. }
    25.  
     
  16. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    its because your setting minDrag and MaxDrag to the same value (rb.Drag). So every update your randomly choosing a number from say 1 to 1. and not suprrising your random number is 1 :)

    Anyway you should change these:
    Code (CSharp):
    1.  private float minDrag;
    2. private float maxDrag;
    to both be public and set them in the editor

    then delete this lines:
    Code (CSharp):
    1. minDrag = rb.drag;
    2. maxDrag = rb.drag;
    Basically if you choose minDrag to be 0, and maxDRag to be 2 in the editor.. it will randomly make the speed somewhere between full Speed and 1/3 speed. You can play around with those values till you get something you like.
     
  17. tomowale

    tomowale

    Joined:
    Feb 14, 2015
    Posts:
    308
    Thank you so much. Gonna try it out soon, and get back to you once I do [ will edit this post when I try, so there is no unnecessary double post]


    UPDATE: Code is working! gonna play around with the drag variables to get the speed I like. I also hope this helped people with a similar problem. Thanks takatok :) !
     
    Last edited: Aug 31, 2016
  18. Taimoor_Masaud

    Taimoor_Masaud

    Joined:
    Mar 23, 2022
    Posts:
    1
    You can also use the command rb.velocity = new Vector3(0, Random.Range(0, -5)); which will add random velocity to your coins between 0 and -5 when they fall down, no need to play with gravity, drag or mass of coins.
     
    aroosafazal likes this.