Search Unity

Wave/Level Manager

Discussion in 'Scripting' started by piggybank1974, Oct 17, 2019.

  1. piggybank1974

    piggybank1974

    Joined:
    Dec 15, 2015
    Posts:
    621
    The last few days I've been toying with the idea of a more dynamic Wave Manager, for a prototype I'm working on.

    This information comes in two parts one in unity and the other in a WinForms application I created for test purposes.

    While I was driving home the other day I came up with this little routine in unity:

    Code (CSharp):
    1.      
    2. for (int wave = 1; wave < 100; wave++)
    3. {
    4.  float mREalTime = Time.realtimeSinceStartup;
    5.  float MonstersWaves =  (  (Convert.ToSingle(wave) / 1.5F) + 20) / mREalTime;
    6.   Debug.Log(string.Format("Wave count {0} realtimeSinceStartup {1}", MonstersWaves, mREalTime));
    7. }
    8.  
    1.5 and 20 are just some arbitrary numbers to get the ball rolling.

    this would have to be run at the start of the game as realtimeSinceStartup increases based on how long the game has been running, although you could do something to mitigate that problem.

    As it can take a while to start and stop a project in unity I decided to dust off my Winform skill and create something that might work.

    I've posted the link to little Winforms program if anybody is interested.

    but the following is what it displays:

    TimeSlice: 0 Start: 1.428404, 0 = wave number(should be 1 but its an index) 1.428404 represents realtimeSinceStartup

    Value: 14.0016431808472 Wave: 14 14 = the number in the First Wave, and should gradually increase.

    Wave: 1 Name: Monster 06 , Value: 0.68 the 0.68 represents the random valued generated
    Wave: 1 Name: Monster 08 , Value: 0.82
    Wave: 1 Name: Monster 04 , Value: 0.55
    Wave: 1 Name: Monster 01 , Value: 0.05
    Wave: 1 Name: Monster 04 , Value: 0.55
    Wave: 1 Name: Monster 07 , Value: 0.77
    Wave: 1 Name: Monster 06 , Value: 0.66
    Wave: 1 Name: Monster 05 , Value: 0.61
    Wave: 1 Name: Monster 09 , Value: 0.96
    Wave: 1 Name: Monster 03 , Value: 0.44
    Wave: 1 Name: Monster 07 , Value: 0.79
    Wave: 1 Name: Monster 07 , Value: 0.69
    Wave: 1 Name: Monster 07 , Value: 0.73
    Wave: 1 Name: Monster 08 , Value: 0.81

    in your opinion does this idea have any legs, or is their another idea.

    Cheers.
     

    Attached Files:

  2. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    You haven't clearly explained what your goal is, or what problem you are trying to solve.

    Your sample output was obviously not generated by the code that you posted.

    If the code only works properly when Time.realTimeSinceStartup has a specific value, then you should almost certainly remove all references to Time.realTimeSinceStartup from your code. (But I can't judge why it's there in the first place, because I don't know what your code is for.)

    Seeing stuff like
    mREalTime
    and
    Convert.ToSingle(wave)
    makes me cringe a little.

    If you have an idea you want to share, I suggest you try to explain the concept clearly, clean up your example code, and generate your example output using your example code.
     
  3. piggybank1974

    piggybank1974

    Joined:
    Dec 15, 2015
    Posts:
    621
    @Antistone

    Actually I thought I explained it well enough, in the first few paragraphs, but I'll try to enhance the information.

    In general, you can go down two routes of wave design "number of monsters per level/wave" e.g I can think of a predetermined data whereby when the game starts "it's all the same" e.g the first wave generates 14 monsters all the time or a form of some sort of randomness built-in to the system.

    As you can see for an idea I picked the second version, remember a prototype is by design a prototype you are feeling the water to see if your concept works, whether you like the code or not that is immaterial, what realtimeSinceStartup does is count in very small increments up from the start of the project you are running, so it helps to generate randomness, and yes it would need to be figured out differently in a production scenario, the actual Winforms project doesn't have this type of property available so I came up with another idea, but the general idea is the same.

    for your information, I've spent many prototypes creating close to production code for them to be canned so this time I've reeled this back, and seeing if the idea fully or lose to it works or thereabouts before I make things better.

    Slagging somebody's code off is just not very nice and not helpful, no matter how you feel about it, I read and write code every day, it's what I do good or bad.

    If you would have taken the time to download the WinForms test project you would off seen the example in action, I just did not want to post several needless pages into the forum.

    Thanks for replying.
     
  4. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    If your code is just for your personal experimentation, you can make it as messy as you want. But when you post it to a public forum and ask for comments, then it's no longer a personal experiment; it's now a product being consumed by other people. If you want those other people to view it favorably, it should look presentable.

    Consecutive raw clock values make awful random numbers, and there's no reason to use them that way, because there's lots of easy off-the-shelf options for generating random numbers; for instance, UnityEngine.Random or System.Random. No one is going to look at code that divides by time and think "aha, they're trying to randomize this".

    And if your whole concept was just "what if I multiply the number of monsters in each wave by a random number?", you could have just said that. That's a moderately common thing to do, although usually you would constrain the multiplier to a specific interval to limit the range of variation, and often you'd use a non-uniform distribution so that certain results are more common.

    But the number of monsters isn't really a great variable to randomize, because it's strongly related to game difficulty, and you probably want difficulty to be relatively predictable. It would be more common to focus on randomizing the type of monsters, the locations they appear, the actions they take, and maybe the timing.
     
  5. piggybank1974

    piggybank1974

    Joined:
    Dec 15, 2015
    Posts:
    621
    @Antistone

    Actually using the random class is not as random as you may think, yes you can seed it but that's always been a grey area, anyways the use of the realtimeSinceStartup method was to use it as a factor, I want to increase the monster count over time, by using something like that it produces a steady upwards "increasing the difficulty" to not too steep for example waves 1 - 3 might be 13 monsters, and wave 4 might be 14 but it will never dip below the previous wave.

    As you don't know the game I'm prototyping, the locations don't matter as the move across a board from one end to another, similar to a TD game but different, It's another take on it, for mobile.

    Furthermore, how clean would you want 5 lines of code 3 if you take out the brackets, I could of taken out the converting of the wave from an int to a float as long as a single variable is a float it should by rights convert fine, but I'm sure you could read it and understand what the point of it was?

    I've never stopped helping others here or in person, just because I didn't write the code to the standard I believe it should be, if it works is it wrong? no, yes it could be improved but that was not the point or exercise here, it was a illustration, I coded a quick and dirty work around in the zip file, I wanted to know if others had any thoughts on this matter.

    Actually I forgot to mention that in the Winforms it was a weighted system, although I was looking into making that Increase/decrease when certain levels where hit, say a bonus level if you will

    Thanks again.
     
    Last edited: Oct 18, 2019
  6. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
    Welcome to CS 101.

    The most common way to seed a random number generator is with a time value. If the generator is even marginally reasonable, then seeding it with the clock can't possibly be worse than using raw clock values with no obfuscation.

    But any competent professional will tell you that you should never use something like "seconds since startup" as your seed, because that has a high degree of both consistency and predictability. Normally you use the finest granularity of time you can possibly access, and preferably you measure relative to some reference frame that is totally unrelated to the operation you are performing.

    You are wary of using the off-the-shelf solution because you heard somewhere it's not theoretically perfect, and so instead of researching and understanding the issues, you have made up your own naive alternative that still has all the same problems, plus more.

    Your algorithm tends to produce higher numbers for later waves because you multiply by the wave number (a technique that has nothing to do with what kind of random numbers you use).

    Your use of the time actually has the opposite effect, because you are dividing by the time, so as time increases you get smaller results.

    No, I had absolutely no idea what the point of it was. My first guess was that you were trying to somehow calculate the appropriate time at which a wave should spawn (why else would you be using the time?)

    Your code has misleading variable names (why is the number of monsters within a wave called "MonsterWaves"), uses the libraries in weird ways without explanation (pretending the time is a random number), and has no comments. The only preface you offered was to describe it as "the idea of a more dynamic wave manager", which could mean at least a dozen different things.

    You appear to be suffering from the curse of knowledge.

    Different standards apply when you are asking for help with a problem compared to when you are offering an idea for others to consider or use.

    But even if you were asking for help, step one for that particular code would have been "I have no idea what you're trying to accomplish here; you need to clarify your intent before we continue." I can't help if I don't know the goal.