- Home /
Return Transform by String Parameter
Hello everyone, I have a singleton class called WorldManager. I want this class to hold some transforms. In the awake function, I create some gameobjects, and also reach some transforms by tags and store them, as a result, after the awake call has finished, I have some Transforms stored in the class. What I would like to do is, I want to reach these transforms whenever I want from another script, this should be easy since the class uses singleton. I know I can do something like this:
void Awake()
{
// storing all transforms like camera,player,light
}
public Transform GetObject(string objectName)
{
if(objectName == "Player")
return Player;
if(objectName == "Camera")
return CameraTransform;
if(objectName == "Light")
return Light;
else
return null;
}
I know this works, but I do not want to write an if statement for every object that I want it to be reached, so is there any way like this :
public Transform GetObject(string objectName)
{
return the transform which named objectName ?
}
Thanks :)
I think you'll end up junking this for a better system, anyway. manager.cam
is just as good as manager.getObject("Camera");
. And string lookups are a pain (they don't auto-complete.)
Answer by Baste · Feb 10, 2015 at 03:15 PM
Yes, you would do this by using a HashMap. The built-in one in C# is Dictionary, which you'll get hold of by putting "using System.Collections.Generic" in the top of your script.
It works like an array, but you index stuff by a custom property - in your case a string - instead of an int. So you'd do:
Dictionary<string, Transform> itemDict;
void Awake() {
itemDict = new Dictionary<string, Transform>();
itemDict["Player"] = GameObject.FindWithTag("Player").transform;
...
}
public Transform GetObject(string objectName)
{
//Will cause an error if you haven't stored an item with the name objectName
return itemDict[objectName];
//If you want to be safe, do this instead:
if(itemDict.ContainsKey(objectName))
return itemDict[objectName];
else {
//handle the objectName key not existing. Like, print an error, return null.
}
}
Nice and easy. If you're interested, I could tell you why what you're doing is wrong, and is basically something you should never, ever do. Seriously, it's a horrible idea. But if you just want a solution, that's it.
So I got that dictionary is the way, but yes you can tell me why does it cause performance problems, im gonna be using this just in the start call in some classes, im gonna get transforms and store them in another private transforms in other classes, still a bad way ?
Essentially, finding the objects you're looking for by the way of a string is a really bad idea. There's some performance issues - comparing strings is a bit expensive - but that's not the big problem here.
The big one is essentially that if any of the strings changes, you'll have no idea where it's been referenced. If you misspell one of the strings, you won't know until you run the code, and then only when you try to run the offending thing.
A much better way, if you have to cache the data somewhere, is just to save the objects directly. Ins$$anonymous$$d of having a dictionary with "Camera" bound to a camera's transform, why not just have the Camera set as a public variable? Or accessible from a public method? You can just do:
public Transform playerTransform;
void Awake() {
playerTransform = GameObject.FindWithTag("Player").transform;
...
}
which is the same thing, but you'll get a compilation error when you spell something wrong ins$$anonymous$$d of the game blowing up at you at some completely unrelated point because the string sent in didn't match.
Alright I got it totaly right now, thanks for the answers :).
Answer by Landern · Feb 10, 2015 at 03:17 PM
Use an enum and dictionary. A dictionary can't have duplicate keys, so keep that in mind.
an example
Dictionary<ObjectTransformName, Transform> objectDic;
public Awake()
{
objectDic = new Dictionary<ObjectTransformName, Transform>();
objectDic.Add(ObjectTransformName.Player, GameObject.FindGameObjectByTag("Player").transform);
objectDic.Add(ObjectTransformName.Camera, Camera.mainCamera.transform);
// etc etc
}
public enum ObjectTransformName
{
Player,
Camera,
Light,
// others
}
public Transform GetObjectTransform(ObjectTransformName otn)
{
// Do some checking here for null and objectDic.Count > 0 or even the key existing
return objectDic[otn]
}
Your answer
Follow this Question
Related Questions
Huge objects dissapear 1 Answer
moving random objects to random positions 1 Answer
How to make a object face another object 1 Answer
Move Object to location of Trigger? 1 Answer