- Home /
compare raycast hit with list of gameobjects c#
Hi,
I'm working on a simple game which is made out of seperate cubes on a grid. if i clicking a cube (saved, elsewhere in the code, as RayCastHit hitOG), it adds the cube left/right/above/below to a list (so 4 cubes).
now, I'm trying to get it that after clicking the cube, i want an action to occur only when clicking one of these cubes in the list.
this is my (simplified) code:
if (Input.GetMouseButtonDown(0))
{
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray,out hit,100))
{
//when clicking the same cube, this part works.
if (hit.transform.name == hitOG.transform.name)
{
//reset the game
}
//now I check "public List<GameObject> GOs" which is in another script.
foreach (GameObject gObj in makeSphere.GOs)
{
if (gObj.transform.name == hit.transform.name)
{
//do something important
}
}
}
}
I cannot get the foreach to work. it is a problem comparing raycasthit with gameobjects? I've looking at this all day, but cannot find a solution. I hope someone can help.
Many thanks!!
Nothing jumps out at me. To start debugging, I would add Debug.Log() calls where you print out the name of the hit object, and then the names of each object in the list.
thanks for the replies. the gObj are prefabs yes. I've tried to Debug.Log(makeSphere.GOs.Count) and write it out in OnGUI() but it always returns 0 even though the elements are given in the inspector of unity when i pause the programme.
Still stuck on this one.. :(
also tried: Debug.Log(makeSphere.GOs[0].transform.name);
but got this error:
ArgumentOutOfRangeException: Argument is out of range.
Parameter name: index
System.Collections.Generic.List`1[UnityEngine.GameObject].get_Item (Int32 index) (at /Applications/buildAgent/work/b59ae78cff80e584/mcs/class/corlib/System.Collections.Generic/List.cs:633)
$$anonymous$$ain.Update () (at Assets/Scripts/$$anonymous$$ain.cs:97)
update: it has something to do with the makeSphere.GOs because when i write Debug.Log(makeSphere.GOs.Count) in makeSphere (so Debug.Log(GOs.Count)) it gives the correct amount. somehow my original file wont read out the List I created in the other file.
-this doesn't solve the problem as i really need it in the first file.. :/
Do you have an instance of makeSphere in the other file, or are you trying to access the class statically? In other words, are you sure that the "makeSphere" in one file, and the makeSphere that you're looking at in the makeSphere file are the same?
I don't think I do. I'm afraid I don't know how to do that within unity, could you point me in the right direction. $$anonymous$$any thanks!
Answer by whydoidoit · Apr 22, 2013 at 05:29 PM
The name of an instantiated prefab has "(Clone)" appended to it - so your name test won't work - you could do:
if(hit.transform.name.StartsWith(gObj.name))
{
}
Answer by kmeboe · Apr 23, 2013 at 11:25 PM
Judging by your comments above, it sounds like you might not be accessing the correct makeSphere object.
There are a couple of ways you can make sure that you can fix this. Probably the easiest way would be to add a public member to the class where you want to access makeSphere. Here's some quick code:
//makeSphere is of type "Foo" in this example.
public class classWhereMakeSphereLives : MonoBehaviour
{
// You could also replace these two lines with a property, as desired.
Foo makeSphere;
Foo GetMakeSphere(){ return makeSphere; }
}
public class classWhereYouWantToAccessMakeSphere : MonoBehaviour
{
// classWhereMakeSphereLives doesn't actually live here. Instead, you
// will use the inspector to drag the object that has classWhereMakeSphereLives
// into the following public field:
public classWhereMakeSphereLives makeSphereOwner;
// You can now access makeSphere here, like so:
void Update
{
Foo makeSphereReference = makeSphereOwner.GetMakeSphere();
makeSphereReference.GOs[]......
}
}
Why are the class names so long? That's self-documenting code, baby! :D
thanks for all your effort (the long classnames really help :D), this sounds like the correct direction to solve the problem. After implementing this code I get the error:
NullReferenceException: Object reference not set to an instance of an object
I had to make
-Foo Get$$anonymous$$akeSphere(){ return makeSphere; }
public to access it in the other class.
Good catch on the "public" part.
I'm guessing the problem is that you need to create the makeSphere object. So for example, you could do this:
Foo makeSphere = new Foo();
That would go in place of the current definition. Or you could do it inside Start, like this:
void Start()
{
// Note: no leading "Foo" here, since it's already declared as a field in the class.
makeSphere = new Foo();
// Now you can populate makeSphere or whatever.
}
I'm very sorry, but I can't get it working. I created the line you ask in both files (didn't understand which one) but for both it didn't solve the problem.
$$anonymous$$y c# skills are probably not far enough to comprehend this problem. I'll report my code here again, maybe I'm just asking the wrong questions..
So this is the first class called "$$anonymous$$ain":
void Update ()
{
//click mouse
if (Input.Get$$anonymous$$ouseButtonDown(0))
{
Debug.Log ("GOs count: " + makeSphere.GOs.Count); //this results in 0 at all times.
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray,out hit,100))
{
//this piece happens after the codeblock under here.
if (playerActive == true && hit.transform.name != "dice")
{
if (hit.transform.name == hitOG.transform.name) //if ray hit is the same as prev click
{
Debug.Log("I clicked the same activesquare");
playerActive = false;
//destroy all created stuff here
}
foreach (GameObject gObj in makeSphere.GOs) //this part doesn't work
{
if (gObj.transform.name == hit.transform.name) { /*succes!!*/ }
}
}
//so this piece of code happens first
if (playerActive == false && hit.transform.name != "dice" && stillActive == false)
{
Debug.Log("I started player active. B succesful");
hitOG = hit;
Debug.Log("Created hitOG = " + hitOG.transform.name);
playerActive = true;
Instantiate(sphereSelect, hit.transform.position, hit.transform.rotation); //here i create a prefab with the other class "maakSphere"
}
} //end if raycast
} //end if input
} //end update
Then this is the code from the prefab, called "maakSphere":
public class maakSphere : $$anonymous$$onoBehaviour {
//list of all collided GOs
public List<GameObject> GOs = new List<GameObject>();
//find sphere and move/kill
public List<GameObject> killThem$$anonymous$$aak = new List<GameObject>();
// blackcube as selection outline
public GameObject blackSelect;
//this is your code
maakSphere makeSphere;
public maakSphere Get$$anonymous$$akeSphere(){ return makeSphere; }
void OnTriggerEnter (Collider Other)
{
GOs.Add(Other.gameObject);
// i know i'm instantiating objects on the same position atm...
foreach (GameObject gob in GOs)
{
Vector3 blackObject = gob.transform.position;
blackObject.z = blackObject.z + 2;
Instantiate(blackSelect, blackObject, gob.transform.rotation);
}
//and that this is a mess...
GameObject[] killThem$$anonymous$$S = new GameObject[10];
killThem$$anonymous$$S = GameObject.FindGameObjectsWithTag("selSphere");
foreach (GameObject gobble in killThem$$anonymous$$S)
{
killThem$$anonymous$$aak.Add(gobble);
}
foreach (GameObject gObj in killThem$$anonymous$$aak)
{
//Destroy(gObj);
//test
gObj.transform.Translate(0,0,10);
}
killThem$$anonymous$$aak.Clear();
}
You can remove my code from maakSphere; this isn't the right spot for it.
We'll try to figure out what to do next. Did you drag your maakSphere class onto an object in your scene? What's the name of that object?
thanks so much for your help.
maakSphere is connected to a prefab called selectSphere, which is instantiated on line #34 of the $$anonymous$$ain class. This is a spherecollider that (in maakSphere) looks for which objects it collides with and adds it to List GOs (line #16 in maakSphere)