Simple (hopefully) questions on object referencing

I am building a script that is attached to the root of a GameObject that has several layers of hierarchy.

I am using GameObject.Find(“name”) to get access to various components (I know this is not the fastest way, that’s another story).

I can then manipulate the components and everything works fine. I then create a new pre-fab and drag my ‘functioning’ game object onto the pre-fab.

Problem is, when I instance the pre-fab multiple times only one copy of it works; the rest don’t. I think it has to do with the way I am getting to the components, which is slow to start.

The script is mean to drive an 8-wheel vehicle. I have 8 wheel colliders and 8 physical wheels; the colliders are a couple of levels deep in the hierarchy, so are the wheels. See the attached picture of the two instances of the pre-fab. I modify the script variables by manipulating them on the Inspector; note one of them has the wheels turning but the other does not.

I have also attached a picture of the hierarchy of one of the two pre-fab instances.

Here’s the script

function FixedUpdate ()
{
var left1Coll_go = GameObject.Find(“CollLeft1”);
var left2Coll_go = GameObject.Find(“CollLeft2”);
var left3Coll_go = GameObject.Find(“CollLeft3”);
var left4Coll_go = GameObject.Find(“CollLeft4”);

var right1Coll_go = GameObject.Find(“CollRight1”);
var right2Coll_go = GameObject.Find(“CollRight2”);
var right3Coll_go = GameObject.Find(“CollRight3”);
var right4Coll_go = GameObject.Find(“CollRight4”);

var left1Wh_go = GameObject.Find(“WheelLeft1”);
var left2Wh_go = GameObject.Find(“WheelLeft2”);
var left3Wh_go = GameObject.Find(“WheelLeft3”);
var left4Wh_go = GameObject.Find(“WheelLeft4”);

var right1Wh_go = GameObject.Find(“WheelRight1”);
var right2Wh_go = GameObject.Find(“WheelRight2”);
var right3Wh_go = GameObject.Find(“WheelRight3”);
var right4Wh_go = GameObject.Find(“WheelRight4”);

//
// Steering
//
left1Coll_go.collider.steerAngle = Steer;
left2Coll_go.collider.steerAngle = 0.75 * Steer;
left3Coll_go.collider.steerAngle = -0.75 * Steer;
left4Coll_go.collider.steerAngle = -Steer;

right1Coll_go.collider.steerAngle = Steer;
right2Coll_go.collider.steerAngle = 0.75 * Steer;
right3Coll_go.collider.steerAngle = -0.75 * Steer;
right4Coll_go.collider.steerAngle = -Steer;

left1Wh_go.transform.localEulerAngles.y = Steer;
left2Wh_go.transform.localEulerAngles.y = Steer/2;
left3Wh_go.transform.localEulerAngles.y = -Steer/2;
left4Wh_go.transform.localEulerAngles.y = -Steer;

right1Wh_go.transform.localEulerAngles.y = Steer;
right2Wh_go.transform.localEulerAngles.y = Steer/2;
right3Wh_go.transform.localEulerAngles.y = -Steer/2;
right4Wh_go.transform.localEulerAngles.y = -Steer;

//
// Thrust
//
left1Coll_go.collider.motorTorque = Gas;
right1Coll_go.collider.motorTorque = Gas;
}

218027--7934--$hier_117.jpg
218027--7935--$straddles_593.jpg

GameObject.Find(“name”) returns the first instance named “name” So I’d guess the duped prefabs are all returning the same object. you can traverse an object’s hierarchy to find an object in that parent like so

var left1Coll_go = GameObject.Find(this.gameObject.name + “/CollLeft1”);

you may or may not get errors on the string concatenation. i’ve never tried it like that. also, why not cache those variables in start so you don’t get slowed down every fixedupdate?

Thanks for the pointer Pete, however, I don’t think that’s the problem. If GameObject.Find(“name”) returned the first instance of that name, then I should be able to turn the wheels of the 1st object by manipulating the variable on any pre-fab. But that is not what happens, when changing the variable of the 2nd pre-fab, nothing changes.

I tried using the concatenation but I am getting exceptions; not sure exactly how to do it, tried both \ , \, / as hierarchy separators, but nothing seems to work.

I also tried using GetComponentInChildren but I can’t differentiate the different wheel colliders.

any other suggestions are appreciated!

Why don’t you link the child objects directly in the Unity editor? You could create in your vehicle scripts slots for all the child wheel gameObjects and link them directly. Would save lots of time on finding the corresponding wheel childs.

Martin,

Would you elaborate on exactly what you mean by linking the objects in the Unity editor?

Regarding the time optimization, I’m trying to get this to work first, then I will worry about optimization.

Never mind; I realized what you mean after thinking about it a bit longer. This does work and avoids any runtime search overhead, although it exposes 8 global variables on the script, which I guess is ok.

I am still trying to figure out what was wrong with the earlier approach, but at least I now have a working version.

Thanks.

Sure. What I mean is (like Pete said already) that your GameObject.Find will fail on multiple instances because it will search globally and probably pick up the wrong ones from a different model.

What I would do is create one instance, link it correctly (will explain below), make a prefab out of it and instantiate then the prefabs.

By linking I mean that you could have in the same script where you above mentioned the FixedUpdate()… you could set up in the beginning of the script one “slot” for each of your left1-2Col’s, right 1-4Cols etc, like this:

var left1Coll_go : GameObject;
var left2Coll_go : GameObject;
var left3Coll_go : GameObject;
var left4Coll_go : GameObject;

// same for the right ones

Now, when you click the object in the inspector where your above script is attached to, you should see some “slots” in the inspector of the type GameObject. Now, start and drag the leftCol1 object directly onto that leftCol1 slot in the script. Now you have linked it statically in the editor. Do the same for all other *Cols. That way you have now all your legs/wheels linked up correctly to its parent object. Finally, create an empty prefab and drag your newly created object onto the emtpy prefab. Voila, you have a ready-to-use prefab which you could clone now x-times and all will work fine. Does that help?

Ah, just saw your answer. Yes, what went wrong before is that GameObject.Find is looking over ALL gameObjects in the scene and it will probably find the wrong one and not the one below your root object of that vehicle.

What you could do is searching with a prefixed slash like this: GameObject.Find(“/<name”);

That should search below your model and not globally (if I’m not mistaken from the docs: file:///Applications/Unity/Unity.app/Contents/Documentation/Documentation/ScriptReference/GameObject.Find.html)

Incidentally, I just tried this and the concatenation worked fine when not a prefab. It returned the correct child of the parent object [not true as noted below]. Unfortunately, as a prefab with multiple instances, it returns the same object from all instances. Not sure how to solve atm and not much help - sorry! Confirmation at least :slight_smile:

var myChild : GameObject;

function Start()
{
	myChild = GameObject.Find(this.gameObject.name + "/CollLeft1");
}

Edit: I take it back. When not a prefab my objects had different names. Making them the same name returns the same object.

Good - at least I’m not crazy!

I will be doing some pretty complicated AI on multiple interacting vehicles each with multiple articulations so I am trying to make sure I’m not missing anything. Unfortunately, I can’t do much without using pre-fabs (which will be instanced at runtime) which is why I must use them.

Manual linking it is, I guess.

Thanks!

See my edit above. My bad. Not using prefabs won’t help.