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

Problem with random monster spawning

Discussion in '2D' started by Lamarqued, May 15, 2015.

  1. Lamarqued

    Lamarqued

    Joined:
    Jan 30, 2015
    Posts:
    9
    Hi everybody, I'm making a game with Unity2D, and I'm trying to make spawning monsters randomly.
    I have 3 monsters : Blob1, which is a classic one, with 85% spawn rate ; Blob2, a little bit stronger, with 10 % spawn rate; Blob3, a lot stronger, with 5 % spawn rate.
    My aim is to make a C# script that can use those random properties to make spawn my monsters on my map.
    For the moment, I have some issues with my scripts and they don't work... Could you help me ? :)
     
  2. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    968
    Maybe we could, but then you'd have to show us your scripts, tell us what the issues are and in what way they don't work.
     
  3. Lamarqued

    Lamarqued

    Joined:
    Jan 30, 2015
    Posts:
    9
    1. In fact, I've searched on google if some script could interest me.
    2. Here is the one I found more suitable :
    3. int[] weights;
    4. int weightTotal;

    5. struct things { //this is just for code-read niceness
    6. public const int Blob1 = 0;
    7. public const int Blob2 = 1;
    8. public const int Blob3 = 2;
    9. }

    10. void Awake () {
    11. weights = new int[3];

    12. //weighting of each thing, high number means more occurrance
    13. weights[things.Blob1] = 85;
    14. weights[things.Blob2] = 10;
    15. weights[things.Blob3] = 5;

    16. weightTotal = 0;
    17. foreach ( int w in weights ) {
    18. weightTotal += w;
    19. }
    20. }


    21. int RandomWeighted () {
    22. int result = 0, total = 0;
    23. int randVal = Random.Range( 0, weightTotal + 1 );
    24. for ( result = 0; result < weights.Length; result++ ) {
    25. total += weights[result];
    26. if ( total >= randVal ) break;
    27. }
    28. return result;
    29. }
    30. I don't really understand every things, and I don't know how to link it with my scripts...
    31. Sorry, I'm really a beginner on Unity, and I have to finish my game for next Thursday...
    32. Thank you guys !
     
  4. AlbinosMou

    AlbinosMou

    Joined:
    Mar 6, 2015
    Posts:
    22
    Your script is correct, as the function named RandomWeighted() properly returns a random monster index according to their respective weights.

    Now you need to make a funciton that actually instantiate a monster (let's call it Summon()), and inside of this function you will call RandomWeighted() to know which monster must pop at this moment.

    Let's say each monster is a prefab. You can create an array of prefabs that will be instantiated at each call of Summon() :
    Code (csharp):
    1. public GameObject[] blobs;
    So, you set it in the inspector, so that blobs[0] is your most common monster, blobs[1] the middle one and blobs[2] the rare one.

    Then the Summon() function you want only consists in getting the right index and instantiating it :
    Code (csharp):
    1.  
    2. // These two vars must be declared earlier :
    3. public Vector3 spawnPosition;
    4. public Quaternion spawnOrientation;
    5.  
    6. void Summon()
    7. {
    8.     GameObject.Instantiate(blobs[RandomWeighted()], spawnPosition, spawnOrientation);
    9. }
    10.  
    Wherever this funciton is called, a monster will appear. If you want to make it spawn at a precise interval of time, you can do it in the Update() function :

    Code (csharp):
    1.  
    2. public float spawnIntervalInSeconds;
    3.  
    4. void Update()
    5. {
    6.     if(Time.timeSinceLevelLoad % spawnIntervalInSeconds < Time.deltaTime) Summon();
    7. }
    8.  
    Hope this will help :)
     
  5. Lamarqued

    Lamarqued

    Joined:
    Jan 30, 2015
    Posts:
    9
    Wow man, thank you a lot, it's really kind from you and surely helps! ^^
    The only matter now is that I don't really figure out where to put this script ? (Thank you again, really helps me out ! My game is becoming bigger and bigger !)
     
  6. AlbinosMou

    AlbinosMou

    Joined:
    Mar 6, 2015
    Posts:
    22
    To make it simple :
    1) your scene contains GameObjects.
    2) those GameObjects contain Components (like a Transform, or a Collider, or a Rigidbody, etc).
    3) any script you write is also a Component that you can attach to a GameObject.
    4) a script is executed in your game if it exists in the scene as a Component.

    So, you have to create a GameObject in your scene (let's call it "BlobManager" since its purpose is to summon blobs), drag your script onto this GameObject, and it will work.

    Be sure to read the documentation to learn the scripting basics : functions like Start() and Update() are premade to make your work much simpler ! http://docs.unity3d.com/ScriptReference/MonoBehaviour.html

    And don't hesitate to look in the Script Reference for the variables and functions I used earlier (like Time and Instantiate).
    Also, aside from scripting, if you're just getting started with Unity, you might need the early chapters of the manual : http://docs.unity3d.com/Manual/UnityOverview.html

    Good luck and have fun ! :D
     
    theANMATOR2b likes this.
  7. Lamarqued

    Lamarqued

    Joined:
    Jan 30, 2015
    Posts:
    9
    Thank you !
    My script is now quasily finished, and after researches, still don't work...

    using UnityEngine;
    using System.Collections;

    public class RandomSpawning : MonoBehaviour {
    public Vector3 spawnPosition;
    public Quaternion spawnOrientation;
    public GameObject[] blobs;
    public Rigidbody2D Blob1;
    public Rigidbody2D Blob2;
    public Rigidbody2D Blob3;
    int[] weights;
    int weightTotal;

    struct things {
    public const int Blob1 = 0;
    public const int Blob2 = 1;
    public const int Blob3 = 2;
    }

    void Awake () {
    weights = new int[3];

    //weighting of each thing, high number means more occurrance
    weights[things.Blob1] = 85;
    weights[things.Blob2] = 10;
    weights[things.Blob3] = 5;

    weightTotal = 0;
    foreach ( int w in weights ) {
    weightTotal += w;
    }
    }


    int RandomWeighted () {
    int result = 0, total = 0;
    int randVal = Random.Range( 0, weightTotal + 1 );
    for ( result = 0; result < weights.Length; result++ ) {
    total += weights[result];
    if ( total >= randVal ) break;
    }
    return result;
    }
    void Summon(){
    GameObject.Instantiate(blobs[RandomWeighted()], spawnPosition, spawnOrientation);
    }
    }

    Then, nothing is happening, no monster is spawning, should I touch spawning ?