Random Numbers and Array Assignments

OK, this is most likely an easy one.

I have a gameObject with 10 children (asteroid meshes).

I have a script that “targets” any of the 10 children successfully (prints debug.log msgs saying “Asteroid Targeted”).

I also have an “AsteroidLogic” script (the targeting script reads data from this). Basically, all the Logic script does is give you a composition percentage of the asteroid (e.g: 60% noble content).

I have two problems:

1.) How do I make it so that clicking on EACH asteroid gives me DIFFERENT random values? Currently, they’re ALL saying %36 percent, or ALL saying 80%. Each roid should be different.

2.) How do I STORE these values? Should I store them in the parent object? Correlate them to unique gameObject ids? Use an array? Hash table? When I say “STORE”, I mean if someone leaves the asteroid field, and it is destroyed – but they later return to the same field. Once the prefab is re-instantiated, Ideally the values should be the same as the last visit.

I’ll point out that these two scripts are the product of other Unity Answers/Forums threads, and while they might be cool, I assure you I am not very good at this, so to get to this point was a miracle to say the least.

TARGET SCRIPT:

// Found at:
// http://forum.unity3d.com/threads/84582-Enemy-health-only-to-appear-when-target-is-clicked-on.

static var playerTarget : Transform;
function Update() {
    //check if the left mouse has been pressed down this frame
    if (Input.GetMouseButtonUp(0)) {
        //empty RaycastHit object which raycast puts the hit details into
        var hit : RaycastHit;
        //ray shooting out of the camera from where the mouse is
        var ray : Ray = Camera.main.ScreenPointToRay(Input.mousePosition);
		
        if (Physics.Raycast(ray, hit, 55000)){

        	if (hit.collider.gameObject.CompareTag("Asteroid")) {
        		//print out the name if the raycast hits something
        		playerTarget = hit.collider.transform;
        		var mf: MeshFilter = playerTarget.GetComponent(MeshFilter);
				bounds = mf.mesh.bounds;
				corners = new Vector3[8];
       		    var asteroidLogic : AsteroidLogic = gameObject.GetComponent("AsteroidLogic");
        		var objectName : AsteroidLogic  = gameObject.GetComponent("AsteroidLogic");
        		   	Debug.Log( playerTarget.name + " is " + asteroidLogic.worthyCompoundRemainder + " percent noble, " + hit.distance + " meters." );
        			}
        			else {
         			Debug.Log(hit.collider.name + " no tag");
        		}
     	}
   } 
}

ASTEROID LOGIC script:

static var worthyCompoundRemainder : int;
static var objectName : String;
static var inertCompoundPercentage = Random.Range(0, 100);

function Start () {
}

function Update () {
		for(var n = 0; n < 10; n++) {
	    	worthyCompoundRemainder = 100 - inertCompoundPercentage;
		}
}

I would love any help, thanks!

PS - edited with help from Eric5h5 to be more visually pleasing.

static var inertCompoundPercentage = Random.Range(0, 100);

You'll only ever have one value of this variable at one time. If you want each asteroid to have it's own value, don't make this and your `worthyCompoundRemainder` static.

For taking the values between visits, however, you could use a static variable in the form of a collection or list. For a good run down of which type you should use, check out this wiki entry. It depends on what kind of data you want to hold on to.

Unfortunately, doing that breaks the whole thing.

Updated AsteroidLogic.js:

var worthyCompoundRemainder : int;
static var objectName : String;
var inertCompoundPercentage = Random.Range(0, 100);

function Start () {
}

function Update () {
		for(var n = 0; n < 10; n++) {
	    	worthyCompoundRemainder = 100 - inertCompoundPercentage;
		}
}

I now get this over and over once PLAY is hit:

ArgumentException: RandomRangeInt  can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread when loading a scene.
Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.
UnityEngine.Random.Range (Int32 min, Int32 max)
AsteroidLogic..ctor () (at Assets/Scripts/AsteroidLogic.js:4)

Thanks,

var worthyCompoundRemainder : int; //public but not static
var objectName : String; //as of now you’re not doing anything with this
var inertCompoundPercentage : int; //public but not static

function Start () {
    inertCompoundPercentage = Random.Range(0, 100);   //make sure random code is in it's proper place (i.e. here)
    worthyCompoundRemainder = 100 - inertCompoundPercentage;
}

function Update () {
    //whatever other logic you want your asteroids to have
}

This code needs to be attached to each asteroid gameObject.

Sorry for that comment above; it’s not a very good (or accurate) explanation. It was my end of day and my brain was a little fried.

Taking another look through your amassed code, there’s a number of things going wrong. In your targeting script, you’re calling var asteroidLogic : AsteroidLogic = gameObject.GetComponent("AsteroidLogic"); which, if this script is attached to each asteroid, would be fine. I suspect this is not the case, however as this targeting script looks like it’s supposed to be associated with the camera or some player-type object. That code is assuming that there’s a component called “AsteroidLogic” attached to the current gameObject and, if that’s not the case, will assign a null value to it (leading to the null reference exception you see when you try to call on it below).

var playerTarget : GameObject;

function Update() {
    //check if the left mouse has been pressed down this frame
    if (Input.GetMouseButtonDown(0)) {
        //empty RaycastHit object which raycast puts the hit details into
        var hit : RaycastHit;         //pretty sure you don't actually need this
        //ray shooting out of the camera from where the mouse is
        var ray : Ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        if (Physics.Raycast(ray, hit, 55000)){

            if (hit.collider.gameObject.CompareTag("Asteroid")) {
                //print out the name if the raycast hits something
                playerTarget = hit.collider.gameObject;

                var mf: MeshFilter = playerTarget.GetComponent(MeshFilter);
                bounds = mf.mesh.bounds;
                corners = new Vector3[8]; // not sure what all this stuff is doing

                var asteroidLogic : AsteroidLogic = 
                                         gameObject.GetComponent("AsteroidLogic");
                Debug.Log( playerTarget.name + " is " + 
                           asteroidLogic.worthyCompoundRemainder 
                           + " percent noble, " + hit.distance + " meters." );
                }
            else {
                    Debug.Log(hit.collider.name + " no tag");
            }
        }
    } 
}