- Home /
Classes. After creating objects. How do I find my objects by class rather than their objects?
So I created a WorldTile class to handle the objects my game generates terrain.
using UnityEngine;
using System;
namespace WorldGenerator
{
public class WorldTile
{
private string worldTileName;
private Vector3 worldTilePosition;
private GameObject worldTileGameObject;
private Terrain worldTileTerrain;
private TerrainData worldTileTerrainData;
private float[,] worldTileTerrainDataHeights;
private TerrainCollider worldTileTerrainCollider;
private int worldXPosition;
private int worldZPosition;
public WorldTile(float terrainXsize,
float terrainYsize,
float terrainZsize,
int heightMapResolution,
Vector3 position,
Transform parent,
int Layer,
string terrainLayer,
int worldX,
int worldZ)
{
worldXPosition = worldX;
worldZPosition = worldZ;
worldTileName = "WorldTile_" + worldXPosition.ToString() + "_" + worldZPosition.ToString();
worldTilePosition = position;
worldTileGameObject = new GameObject ();
worldTileGameObject.name = WorldTileGameObject.name = WorldTileName;
worldTileGameObject.transform.position = worldTilePosition;
worldTileGameObject.transform.parent = parent;
worldTileGameObject.tag = terrainLayer;
worldTileGameObject.layer = Layer;
worldTileTerrain = (Terrain)worldTileGameObject.AddComponent ("Terrain");
worldTileTerrain.terrainData = new TerrainData ();
worldTileTerrainData = worldTileTerrain.terrainData;
worldTileTerrainData.name = WorldTileName + "_TerrainData";
worldTileTerrainData.heightmapResolution = heightMapResolution;
worldTileTerrainData.size = new Vector3(terrainXsize, terrainYsize, terrainZsize);
worldTileTerrainDataHeights = worldTileTerrainData.GetHeights (0, 0, worldTileTerrainData.heightmapHeight, worldTileTerrainData.heightmapWidth);
worldTileTerrainCollider = (TerrainCollider)WorldTileGameObject.AddComponent ("TerrainCollider");
worldTileTerrainCollider.terrainData = WorldTileTerrainData;
}
public string WorldTileName
{
get{return worldTileName;}
set{worldTileName = value;}
}
It goes on and has other functions to get/set variables.
So after these objects are created I want to occasionally find and build arrays of them.
using UnityEngine;
using System;
using System.Linq;
namespace WorldGenerator
{
public class WorldTileManager
{
public WorldTileManager()
{
}
public WorldTile[] WorldTiles
{
get{WorldTile[] worldTileObjects = GameObject.FindGameObjectsWithTag("Terrain");
return worldTileObjects;
}
}
}
}
Obviously this wont work as FindGameObjectsWithTag will return a GameObject[] rather than WorldTile[] class.
I had a fleeting moment of "I'll loop through the GameObject[] array and build a WorldTile[] by passing the GameObject to a function and have it return the WorldTile."
However, I have no idea how to have it go from the GameObject back to WorldTile.GameObject. My brain is just not making this connection.
If anyone can point me the right direction.
What are you using GameObject.Find
for? You already have the array, so doesn't WorldTiles[tileNum].worldTileGameobject
quickly find whichever GO you need?
Do you have raycasts or collisions hitting your tiles, and need to know "O$$anonymous$$, what's the number on that tile?"
TBH it all looks wrong to me. Your WorldTile constructor creates a GameObject but that GameObject isn't a WorldTile, doesn't know that it's has anything to do with WorldTiles. I think you probably want to restructure things... make your WorldTile class derive from $$anonymous$$onoBehaviour, and have your WorldTile$$anonymous$$anager create GameObjects with WorldTile components. Then you'll be able to find them (using FindObjectsOfType()) and access all their WorldTile stuff through their WorldTile components.
BonfBoy: Well, yes, it seems like about 10 lines starting with new GameObject();
could be replaced with a single call to Instantiate.
There are two ways to set up class+object: class goes on the object (what you suggested,) or class is created in a script and points to the object (which I think is what the worldTileGameObject
is for.)
I don't know why my comment did post earlier but I went both your suggestions. I moved the creation of WorldTiles into WorldTile$$anonymous$$anager. I ran into some issues with using "new" when trying to create the singleton of WorldTile$$anonymous$$anager. I ended up making WorldTile$$anonymous$$anager and WorldTiles extend $$anonymous$$onoBehaviour and then added them as components to new game objects.
Then to instantiate the new pieces
GameObject buildWorldPiece(Vector3 newPosition,Quaternion wprot,int worldXPosition,int worldZPosition)
{
//create terrain out of thin air
GameObject worldTileGO = new GameObject();
WorldTile worldTile = (WorldTile)worldTileGO.AddComponent("WorldTile");
worldTile = worldTile$$anonymous$$anager.BuildWorldTile(worldTileGO,
worldTile,
terrainXsize,
terrainYsize,
terrainZsize,
terrainHeight$$anonymous$$apResolution,
newPosition,
transform,
terrainLayer$$anonymous$$ask,
terrainLayerTag,
worldXPosition,
worldZPosition);
return worldTile.WorldTileGameObject;
}
@Owen and @Bonfire Boy. Thank you for your suggestions. I ended up making both my WorldTile and WorldTile$$anonymous$$anager extend monobehaviours.
Sometimes it's the simple act of saying ,"WTF!?" which tells me I'm in the wrong direction. Thanks for taking the time to help me.
I made my WorldTile class serializable and can see all my values in the inspector on each object. This works great.
Now to find WorldTiles I have it search for components of worldtile type in worldcreator (blank object) children.
Answer by Anxo · Jan 28, 2015 at 06:08 PM
I am not sure its such a good idea, but if you already have the objects in an array you could
using System.Collections.Generic
GameObject[] objectsToSearch;
List<GameObject> objectsWithComponent;
void CollectObjects(){
objectsWithCompoent = new List<GameObject>();
foreach(GameObject obj in objectsToSearch){
WantedClass classToCollect = obj.GetComponentInChildren<WantedClass>();
if(classToCollect!=null){
objectsWithComponent.Add(classToCollect.gameObject);
)
}
}
WUCC
but I do not think I would do this, Instead I may have an object that the wanted class finds and registers itself to, that way you do not search for it, you just ask the "resitar" what it has. Check for spelling and compiler issues. WUCC
Answer by gheeler · Jan 29, 2015 at 09:33 AM
WorldTile[] myWorldTiles = GameObject.FindObjectsOfType<WorldTile>();
Didn't realise they weren't MonoBehaviours...
In that case you just have to keep track of them after creation.
That will find no objects. WorldTile is not a $$anonymous$$onoBehaviour. The GameObjects being created know nothing about WorldTiles.