Random Range, Smaller Selection, Static Var (Arrays?)

Hi All,

I’ve got a training excercise that I’m working on in which the trainee enters a number of samples (n) in an input field. The game should then select (n) numbers of serial numbers from a set range and display them.

Then, the student is to enter another number of samples (n2) that should be randomly selected from the serial numbers generated in (n). And display them.

Then, the student is to enter another number of samples (n3) that should be selected from the serials not selected in (n2) but left over from (n) and display them.

Then, it’s important that Unity keeps track of all of these serial numbers (n, n2, and n3) so we can check if the student actually went to the items whose serial numbers were presented.

I’ve got an OnGUI that asks for the inputs, and then generates the next input field, but am at a loss as to how to tackle the logic of these sequentially dependent random selections - and then even more perplexed as to how to store the randomly generated serials (a different number of them depending on the entry of the student) so they can be accessed accross game levels.

static var bigNDeclaration : String = "#";
static var nInput : String = "#";
static var n2Input : String = "#";
static var n3Input : String = "#";

private var shownInput : boolean;
private var shown2Input : boolean;
private var shown3Input : boolean;

function OnGUI () {
	if (ToolFunctionality.samplingPlanToolActive){
		bigNDeclaration = GUI.TextField (Rect (((Screen.width/2)-400), ((Screen.height/2)-270),100,20), bigNDeclaration, 25);
		if (GUI.Button (Rect (((Screen.width/2)-280), ((Screen.height/2)-270),100,20), "Submit")){
			show_nInput = true;
		}
		if (show_nInput){
			nInput = GUI.TextField (Rect (((Screen.width/2)-400), ((Screen.height/2)-155),100,20), nInput, 25);
			if (GUI.Button (Rect (((Screen.width/2)-280), ((Screen.height/2)-155),100,20), "Submit")){
				shown2Input = true;
			}
		}
		if (show_n2Input){
			n2Input = GUI.TextField (Rect (((Screen.width/2)-400), ((Screen.height/2)-50),100,20), n2Input, 25);
			if (GUI.Button (Rect (((Screen.width/2)-280), ((Screen.height/2)-50),100,20), "Submit")){
				shown3Input = true;
			}
		}
		if (show_n3Input){
			n3Input = GUI.TextField (Rect (((Screen.width/2)-400), ((Screen.height/2)+55),100,20), n3Input, 25);
			if (GUI.Button (Rect (((Screen.width/2)-280), ((Screen.height/2)+55),100,20), "Submit")){
				shown3Input = true;
			}
		}
	}
}

Any help on strategy would be greatly appreciated…

OK…so here’s where I am now. I’ve created an array that populates based upon the user’s input:

function OnGUI () {
	if (ToolFunctionality.samplingPlanToolActive){
		bigNDeclaration = GUI.TextField (Rect (((Screen.width/2)-400), ((Screen.height/2)-270),100,20), bigNDeclaration, 25);
		if (GUI.Button (Rect (((Screen.width/2)-280), ((Screen.height/2)-270),100,20), "Submit")){
			show_nInput = true;
		}
		if (show_nInput){
			nInput = GUI.TextField (Rect (((Screen.width/2)-400), ((Screen.height/2)-155),100,20), nInput, 25);
			if (GUI.Button (Rect (((Screen.width/2)-280), ((Screen.height/2)-155),100,20), "Submit")){
				RandomSerialGenerator(); //Generates the random serials
				show_n2Input = true;
			}
		}
		if (show_n2Input){
			n2Input = GUI.TextField (Rect (((Screen.width/2)-400), ((Screen.height/2)-50),100,20), n2Input, 25);
			if (GUI.Button (Rect (((Screen.width/2)-280), ((Screen.height/2)-50),100,20), "Submit")){
				shown3Input = true;
			}
		}
		if (show_n3Input){
			n3Input = GUI.TextField (Rect (((Screen.width/2)-400), ((Screen.height/2)+55),100,20), n3Input, 25);
			if (GUI.Button (Rect (((Screen.width/2)-280), ((Screen.height/2)+55),100,20), "Submit")){
				shown3Input = true;
			}
		}
	}
}

function RandomSerialGenerator(){
	nInputInt = parseInt (nInput);										
	var nInputArray = new Array ();								
	nInputArray.length = nInputInt;									
	
	var number = 0;														
	for (i=0; i<=(nInputInt-1); i++){								
		number +=1;
		nInputArray[i]=Random.Range (minSerial, maxSerial);		
		print  (nInputArray[i]);												
	}																		
}

So this does indeed generate the random serials (and prints them to the Console) - which is great. So I guess the question now is:

How do I have the next input (n2), pick a set number of random numbers from those now populating the nInputArray?

What you are describing is a inventory/item look-up reference screen. (The same type they use in Auto stores to look-up items) The problem that I see is that I can’t find a “List” object in Unity. I think one could be created using something like a set of Labels and a VerticalScrollbar, though I am not sure if you can get a mouse down event or even focus on a Label.

If that is really what you are looking for, you may wish to consider using a web page or true application to create this. Far more support for massive lists, searchs and displaying information like this.

If you are using Unity because of the 3d aspect. Lookup an item, display a 3d representation of that item. Then a combination of Javascript, Ajax, PHP and Unity is your answer. (HTML DOM would work perfectly for massive lookup tables)

The next part is that you really would want SQL behind this. "I want a torque converter for a 1979 Pontiac Sunfire… " Translates better than a random range of values. This is doable in Unity (locally by using a ADO connection object or remotely using the WWW object)

So what you are discribing is a 2 list system. List 1 is basically item name lists, and the 2nd is a multi object list where you click on an item and display specific information about that item.

Lets say you have a single array with 5000 serial numbers. You want say a range from 100 thru 500. Create a new Array with just the 401 serial numbers and display them. The user selects of those, Make a 3rd array, copy those numbers to it then display. This display should not allow multiple selection, and as you click on each item it updates the info sheet and 3d object) Click a back button and display the 2nd array list.

Thanks BigMisterB. Yeah, we need to keep it in Unity as it’s a 3D training simulation; and I’m just not fluent enough in any sort of SQL or tieing into outside databases to be able to get Unity to talk outside itself. Luckily, the number of serials is usually quite small (40 to begin with, 6 are picked from that for n, 5 for n2, and then 1 for n3). So there doesn’t need to be any really huge lists.

Where I’m at now is this:

var nInputArray = new Array ();
var n2InputArray = new Array ();

{then in here I call out RandomSerialGenerator after they've entered a value for n.  Then, call out SerialsFromNGenerator when they've entered a value for n2}

function RandomSerialGenerator(){
	nInputInt = parseInt (nInput);	
	nInputArray.length = nInputInt;	
	
	var number = 0;															
	for (i=0; i<=(nInputInt-1); i++){	
		number +=1;
		nInputArray[i]=Random.Range (minSerial, maxSerial);	
		print  (nInputArray[i]);											
	}																			
}

function SerialsFromNGenerator(){
	n2InputInt = parseInt (n2Input);
	n2InputArray.length = n2InputInt;
	
	var number = 0;
	for (i=0; i<=(n2InputInt-1); i++){
		number +=1;
		n2InputArray[i] = nInputArray[Random.Range (0, n2InputArray.length)];
		print (n2InputArray[i]);
	}
}

So I’m down to two issues. Both of these generators work fine, but sometimes, it generates the same number twice (which is no good for this situation). Secondly, with this array populated here, if I swap to another Level, won’t the values populating the arrays here be lost?

Hello there!

I’m not 100% certain that I understand what you want to achieve in your first description so I can’t give you any exact solutions.
However I shall try to provide you with the means to solve your problem!

This is how you get a random result which is part of an array:

randomValue = inputArray[Random.Range(0, inputArray.Length)];

Now if you want to make sure the random value has not already been chosen you will have to compare it to the previously chosen values:

var pickedValues : int[];

function GetRandom() {
    var randomValue = inputArray[Random.Range(0, inputArray.Length)];
    while(!Validate(randomValue))
        randomValue = inputArray[Random.Range(0, inputArray.Length)];
    // Add randomValue to pickedValues
    return randomValue;
}

function Validate(value : int) {
    for(var i = 0; i < pickedValues.Length; i++) {
        if(value == pickedValues[i])
            return false;
    }
    return true;
}

I’m a C# coder, so I apologize if I got some of the JS jargong wrong, but at the very least it should provide some assistance.

That part is actually the easiest… :wink:

var test1 : Array= Array(1,2,3,4,5,6,7,8,10,23,25,67,69,88,89,90,95,98,99);

function Start(){
	print(test1);
	print(PickRandomValues(test1, 5, false));
	print(test1);
	print(PickRandomValues(test1, 5, true));
	print(test1);
	print(PickRandomValues(test1, 5, true));
	print(test1);
}

function PickRandomValues(array : Array, count : int, removeFromList : boolean){
	// error checking
	if(count < 1) return Array();
	if(count >= array.length) return array;
	
	var newArray : Array = array;
	if(!removeFromList){
		newArray = Array();
		for(i = 0; i<array.length; i++){
			newArray.Add(array[i]);
		}
	}
	
	var arr : Array = Array();
	for(i = 0; i<count; i++){
		n = Random.value * newArray.length;
		arr.Add(newArray[n]);
		newArray.RemoveAt(n);
	}
	return arr;
}

Thank you much, both! Give me lots to learn about - but gives me a real direction. Thanks much!