Forum rules - please read before posting.

Randomising dialogue option positions from an array of positions

Please can anyone recommend a stress free and dependable way of shuffling the position of dialogue options in AC? I don't want the options to appear at the same place every time so the player actually has to read through the options to select the right one. (I hooked up the dialogue menu using Unity's UI) I have spent an inordinate amount of time trying to get the Fisher Yates shuffle (piped through a function created in a dedicated script which is then called when required through an AC action list) to work, however, it does not return entirely unique positions every time, sometimes the positions overlap, sometimes, the last index stays fixed to the same spot no matter how many times you shuffle the options. From what I've seen so far, the Fisher Yates Shuffle, has it's quirks and those quirks are not aligning too well with what I need.

I've tried to think if there was a way I could hook up AC's variable: Check Random Number, but it doesn't seem possible without a monstrously sized action list editor with complicated nodes.

Here's the function I've been struggling with, this is the closest I got to something stable, I've tweaked it a gazillion times with the issues referred to above not going away:

public void ShuffleBtns()
    {
        a = new int[dialogueMenuBtns.Length];
        foreach (GameObject y in dialogueMenuBtns)
        {
            for (int x = 0; x < dialogueMenuBtns.Length - 1; x++)
                {
                a[x] = x;
            }
        }

        for (int i = 0; i < a.Length - 1; i++)
        {
            foreach (GameObject z in dialogueMenuBtns)
            {
                int randomIndex = Random.Range(i, a.Length - 1);
                int temp = a[i];
                a[i] = a[randomIndex];
                a[randomIndex] = temp;
            }
       dialogueMenuBtns[a[i]].transform.position = dialogueBtnLocations[i].transform.position;
        }
    }

Comments

  • I've battled with it some more and cobbled up a solution that seems to be close to 90% effective (I still have overlapping buttons - occasionally - but the incidence is greatly reduced and relatively acceptable for my needs). I may be strapping on belts and braces here but at least it's now getting somewhere. This thread was helpful, as were many others. Being able to isolate the actual shuffle function as separate from the position swapping function was helpful in figuring out what to do.


    public void ShuffleBtns()
        {
            a = new int[dialogueMenuBtns.Length];

            ShuffleArray(dialogueMenuBtns);
            ShuffleArray(dialogueBtnLocations);
      
            for (int x = 0; x < dialogueMenuBtns.Length; x++)
                {
                    a[x] = x;
                }

            ShuffleArray(a);

            foreach (int z in a)
            {
                dialogueMenuBtns[a[z]].transform.position = dialogueBtnLocations[z].transform.position;
            }
        }

        public static void ShuffleArray<T>(T[] xArray)
        {
            for (int i = xArray.Length - 1; i > 0; i--)
            {
                int randomInt = Random.Range(0, i + 1);
                T tempIndex = xArray[i];
                xArray[i] = xArray[randomInt];
                xArray[randomInt] = tempIndex;
            }
        }
  • AC's Variable: Check random number Action simply uses Random.Range as you are, so it wouldn't give much difference.

    Are you overriding the Conversation's options in a single ActionList, or having each option run its own DialogOption ActionList.  If the latter, you could instead use the randomisation to re-order the Conversation's options List, as opposed to re-positioning the options - which may solve the overlapping problem.
  • Sorry I got sidelined on some other project before I was done testing this out. Happy to report Chris, that using the randomisation to re-order the Conversation's options list like you suggested, works pretty well. It took a while to figure it out, but I'm happy now. Many thanks for the tip!

    Here's how I fixed it in code for anyone else trying to do the same thing: 

    /* I already had 3 conversations being chosen at random using the Variable: Check random number, each time the conversation hotspot was clicked. I made these accessible in the script via the inspector (greenConv, redConv, greyConv) and used the shuffle function as before. Only difference to note here is that in this version, you have to change the list type to <ButtonDialog> and refactor the code accordingly. This gives me a nice randomisation of the 3 conversations, AND their options at the same time, meaning the player can't just memorise the position of the right answer to each conversation, but would have to read through each option everytime, to find the right one. The difficulty level can be increased by increasing the number of conversations in the set*/

     public Conversation greenConv;
     public Conversation redConv;
     public Conversation greyConv;

      public void ShuffleBtns()
        {

            for (int x = 0; x < greenConv.options.Count; x++)
            {
                ShuffleDialog(greenConv.options);
                ShuffleDialog(redConv.options);
                ShuffleDialog(greyConv.options);
             }

        }


        public static void ShuffleDialog<ButtonDialog>(List<ButtonDialog> dialogArray)
        {
            for (int i = dialogArray.Count - 1; i > 0; i--)
            {
                int randomInt = Random.Range(0, i + 1);
                ButtonDialog tempIndex = dialogArray[i];
                dialogArray[i] = dialogArray[randomInt];
                dialogArray[randomInt] = tempIndex;
            }
        } 
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.