silverua / slay-the-spire-map-in-unity

Implementation of the Slay the Spire Map in Unity3d
MIT License
273 stars 65 forks source link

Set Seed #10

Open Denaton opened 3 years ago

Denaton commented 3 years ago

Trying to use Random.InitState(seed); and i put it on top in the GenerateNewMap() method but its still random each time i generate with the same seed.

Should i convert it all into System.Random instead?

silverua commented 3 years ago

Personally, have not tried this, but, yeah, I think, for setting the seed System.Random is definitely the way to go. Because you can make instances of it and they are not affected by any other code, unlike the static Random class.
Check out this article if you have not seen it already: https://blog.redbluegames.com/generating-predictable-random-numbers-in-unity-c97b7c4895ec

sdg9 commented 3 years ago

@Denaton I can confirm switching everything to System.Random works, i.e. System.Random newRandom = new System.Random(seed); and then pass newRandom everywhere you need to generate a number.

Specifically in

I also added a new extension to help

using System;

namespace Map
{
    public static class RandomExtensionMethods
    {
        public static float NextFloatRange(this System.Random random, float minNumber, float maxNumber)
        {
            return (float)(random.NextDouble() * (maxNumber - minNumber) + minNumber);
        }
    }
}

I'd submit a pull request but it's all baked into my app at this point.

This is a super handy feature for me as I plan on doing multiplayer, much easier to send a seed and have all clients generate an identical map compared to sending a json object representing the generated map.

lucde commented 9 months ago

@Denaton I can confirm switching everything to System.Random works, i.e. System.Random newRandom = new System.Random(seed); and then pass newRandom everywhere you need to generate a number.

Specifically in

  • MapGenerator.cs
  • MapManager.cs (if you want to pass a seed into MapGenerator.GetMap()
  • MinMax.cs
  • ShufflingExtension.cs

I also added a new extension to help

using System;

namespace Map
{
    public static class RandomExtensionMethods
    {
        public static float NextFloatRange(this System.Random random, float minNumber, float maxNumber)
        {
            return (float)(random.NextDouble() * (maxNumber - minNumber) + minNumber);
        }
    }
}

I'd submit a pull request but it's all baked into my app at this point.

This is a super handy feature for me as I plan on doing multiplayer, much easier to send a seed and have all clients generate an identical map compared to sending a json object representing the generated map.

Hello @sdg9 , I was wondering if you succeed implementing a method that would allow to replicate a map identical to the host one for all the other players in the room. I am a bit lost on the strategy to use. I am using photon pun for the multiplayer apsect. I saw your method using System.Random. you were still working on it. did it do well ? Best,

sdg9 commented 7 months ago

@lucde yeah it worked great for multiplayer.

I made sure I could generate the same map from a seed every time. Then I synced the seed over the network and had each client generate an identical map layout. I did this back in Jan 2021 so it's not fresh in my mind but I added these extension methods and made sure to use System.Random w/ the seed as it's deterministic.

using UnityEngine;
using System;

namespace Map
{
    public static class RandomExtensionMethods
    {
        public static float NextFloatRange(this System.Random random, float minNumber, float maxNumber)
        {
            return (float)(random.NextDouble() * (maxNumber - minNumber) + minNumber);
        }
        public static double NextDoubleRange(this System.Random random, double minNumber, double maxNumber)
        {
            return random.NextDouble() * (maxNumber - minNumber) + minNumber;
        }

        public static int NextIntRange(this System.Random random, int minNumber, int maxNumber)
        {
            var retVal = random.Next(minNumber, maxNumber + 1);
            // var retVal = random.Next() * (maxNumber - minNumber) + minNumber;
            // Debug.Log($"RandomExtensionMethods.NextIntRange: Generating betwen {minNumber} and {maxNumber}, randomized {randomNumber} to produce {retVal}");
            return retVal;
        }
    }
}

Then I passed the instance of random to everything that needed it, e.g. image