- Home /
Instantiated prefab references point to first prefab instantiated
I have a loop that instantiates ship objects for a rts game im making. I have a selector script that selects references of objects based upon a raycast hit operation. When i have one ship (without instantiating others) my code for selecting works fine, and so does deselecting code(i loop through all ship tagged objects and see if they have the selection obj attached to them) but when i just instantiate a few more ship prefabs, my code breaks.
I touch any ship and it selects the first ship instantiated, not the one i touch or my original one in the scene. I use a debug string to output the obj name selected, and if i tap the original (which is named MainShip1) it shows the correct name of the object but selects a prefab instantiation rather than the ship hit by the raycast. If i tap any prefab instantiation it selects the first prefab aswell that is instantiated but shows the name "MainShip1(Clone)" which is what it would under instantiation of a prefab.
Here are images of my scene and problem (notice the debug output too in the upper left):
This is when i select my ship without other prefabs instantiating: Here is deselecting:
Here is before i select a ship when i have other prefabs instantiated: Here is after i select a ship (The one to the left of the white cube which is my original and the selected ship is the first prefab instantiated)
Here is my instantiation code:
Ship1 = (GameObject)Resources.Load("MainShip1");
for(int i = 0;i<8;i++)
{
GameObject ship = (GameObject)Instantiate(Ship1, new Vector3(-1435.566F + (i*7F),0,-1427.19F), new Quaternion(0,0,0,0) );
ship.tag = "Ships";
GameObject hull = ship.transform.Find("ShipHull").gameObject;
ShipVars shipVars = hull.GetComponent("ShipVars") as ShipVars;
shipVars.currentCommand = 0;
debugGText.permDebug("ship number " + i + " is named " + ship.gameObject.name + "and hullObj is named: " + hull.name + " and is on layer " + ship.layer + "and has tag " + ship.tag );
}
Here is my code for my raycast.hit code:
if ((hit.collider) && hit.collider.gameObject.transform.parent.gameObject.CompareTag("Ships")) //if my ray hit a "Ship" tagged object (collider is component and this references the object it is attached to?
{
//change to raycast all, as it stores an array of all objects hit and ray doesnt stop at first one
//or disable invisPlane collider until raycast finishes, then if no other colliders are hit reenable invisPlane collider and reraycast to determine move point.
//debugGText.setDebug("callingSelObjMethod");
//debugGText.permDebug("selecting ship from touch");
debugGText.permDebug("hitObj name: " + hit.transform.name);
selectThisObj(hit.transform.gameObject); //references hull
}
And here is my selectThisObj method:
public void selectThisObj(GameObject g)
{
g = GameObject.Find("ShipHull");
//debugGText.permDebug("insideSelObjMethod, gameObj name is: " + g.name);
ShipVars script = g.GetComponent("ShipVars") as ShipVars;
//debugGText.setDebug("after ShipVars referencing....");
if(script != null)
{
//debugGText.setDebug("script isnt null");
if(script.isSelected == false)
{
//debugGText.permDebug("SelectThis obj: script != null, isSelected var = f, selecting....");
script.isSelected = true;
selObjList.Add(g);
//create selected obj here and parent to selected obj ship
GameObject selectedObjGui = (GameObject)Instantiate(guiSel, g.transform.position, g.transform.rotation); //instantiate a prefab of my selection object at the colliders current coordinates
script.selGuiObj = selectedObjGui;
debugGText.permDebug("inSelectObj method and attaching selObj to: " + g.collider.gameObject.name + " and shipObj is " + g.collider.transform.parent.gameObject.name);
selectedObjGui.transform.parent = g.collider.transform;
selectedObjGui.transform.localPosition = Vector3.zero;
selectedObjGui.transform.localRotation = Quaternion.identity;
biggestDimension = script.biggestDimension;
selectedObjGui.transform.localScale = new Vector3((float)(biggestDimension/3.0F), (float)(biggestDimension/3.0F), 1.0F);
}
}
else
{
//debugGText.setDebug("script is null");
}
somethingSelected = true;
//debugGText.permDebug("calling populate list");
scrollListVert.populateList(2);
}
Here is my ship prefab hierarchy:
Well i hope i didn't scare anybody away with providing code and images. I just am super confuse don how to debug this and why this would happen.... :confused:
It might be the first line in selectThisObj. Are you getting the Hull of the selcted ship? If so, use transform.find to search within that object, currently you are looking for any object name "$$anonymous$$ainHull", which will return the first one it finds in the scene. You might want to consider using an ID system, either for na$$anonymous$$g or use on the ships script to identify specific GO's.
Answer by 1337GameDev · May 06, 2012 at 07:31 AM
I found the answer, i was modifying the arrayList i was iterating over. Here is my other post about it in case others have a similar problem: Other Post Link
I solved it by doing:
while(selObjList.Count>0) { //deselect first element }
Answer by 1337GameDev · Apr 25, 2012 at 12:14 AM
Hmm ok great find though, i was meant to find the hull of the parameter gameobject. But when i change it to g.gameObject.Find("ShipHull"); it complains giving this error:
Static member `UnityEngine.GameObject.Find(string)' cannot be accessed with an instance reference, qualify it with a type name instead
This method exists in the gameObject type, and takes a string as its parameter. Why would it be asking for a type? Is it a generic method?
you would say
var mainHull=g.transform.Find("ShipHull");
you need a new var for the mainHull object, then search the hit collider objs transform for its main hull
Using this code gives same error as before: Static member `UnityEngine.GameObject.Find(string)' cannot be accessed with an instance reference, qualify it with a type name ins$$anonymous$$d
and the code is: GameObject hull = g.gameObject.Find("ShipHull");
Answer by 1337GameDev · Apr 25, 2012 at 12:22 AM
isnt using the var keyword without a type intensive and could lead to type unsafe operations? I always try to declare my types so i make sure to be aware if it references the transform or gameObject.
You can type it as either, thats why i left it open(i should have specified the return tho).
If you code uses GameObjects, itll be easier for you to return it as ("$$anonymous$$ainHull").gameObject. Otherwise the function returns as Transform by default. http://unity3d.com/support/documentation/ScriptReference/Transform.Find.html>Transform.Find() Doc
Examples:
var mainHull:Transform=g.transform.Find("$$anonymous$$ainHull");
var mainHull:GameObject=g.transform.Find("$$anonymous$$ainHull").gameObject;
Also, use the comments button for comments as these are not answers. Thanks
Ok ya i used the transform to reference the objects and now they select. But they dont deselect. It doesnt reset thier script variable (isSelected) that is attached to ecah prefab for some reason. All the code now works on my original object i made, but none of my prefabs deselect. I put a debug string in my code and it is like they are skipping my deselect method.
Here is my code for deselect:
public void deselectObj(GameObject g)
{
GameObject hull = g.transform.Find("ShipHull").gameObject;
ShipVars shipVars = hull.gameObject.GetComponent("ShipVars") as ShipVars; //fetch ShipVars object to check values
//----------------
Destroy(shipVars.selGuiObj);
//----------------
shipVars.selGuiObj = null;
shipVars.isSelected = false; //set the current iterated ship variable to false
if(hull.transform.Find("SelectedIndicatorGui(Clone)") != null)
{
Destroy(hull.transform.Find("SelectedIndicatorGui(Clone)").gameObject); //ins$$anonymous$$d try looping through all selectGui objs and then delete each one (we want to delete them all in this case) (In later cases we can use raycast or a smaller loop, for selection boxes, to destroy selectionGui objs)
debugGText.permDebug("SelIndicatorGui isnt null");
}
for (int i = 0;i<selObjList.Count;i++)
{
if(hull.Equals( selObjList[i] )) //check if this check instance and not just duplicate obj (otherwise it will remove all objs in list)
{
selObjList.RemoveAt(i); //check if this looks at obj check and if the list has a function to find and remove the obj
debugGText.permDebug("");
}
else
{
}
}
}
Why would this work on my original ship object, but not my prefabs of the ship object? I really confused...
@Lord_Richard_2 You can do away with the .gameObject on the 2nd line since its already a GO. Also i would make a var for that Find("Selected...") since Finds are expensive calls and you already found what you were looking for. Im looking for a problem, but not really seeing anything but i have some ideas...
$$anonymous$$ake sure ShipVars is actually on the hull $$anonymous$$ake sure g is the correct object $$anonymous$$ake sure the spelling is correct on the indicator $$anonymous$$ake sure the selection function doesnt run during the deselection function ($$anonymous$$ost likely the case, since it seems to "Stay" selected)
Your answer
Follow this Question
Related Questions
GameObject variable points to instance instead of prefab when prefab gets instantiated 2 Answers
Accessing instance of prefab from its own script 1 Answer
Why is it important to create an empty gameobject for my prefabs? 0 Answers
Instantiating in Awake() v Setting up prefab instances in Editor performance difference? 1 Answer