- Home /
how to make public variables unique to the gameobject it is attached to?
Hi,
I'm very new to coding.
Idea: I want to use the single script to different game objects, each game object will have different values assigned. On click on a particular GameObject it has to debug its own values.
Issue: The Debugs will be of the first object to which this script is attached to. - no matter which object you click.
Can anyone please help me on making the class unique to individual game Object? Here it is - different script file:
[Serializable]
public struct ElementInfo{
public string VariantName;
public Sprite VariantIcon;
public Material VariantMaterial;
}
[Serializable]
public class ElementVariants{
public string ItemName;
public List<ElementInfo> Variants = new List<ElementInfo>();
}
Customizer script:
public class ObjectCustomizer : MonoBehaviour {
public List<ElementVariants> Elements = new List<ElementVariants> ();
void Update(){
//If Clicked, get the Object by Ray Hit. and Populate the UI elements
if (Input.GetMouseButtonDown (0)) {
if (!EventSystem.current.IsPointerOverGameObject ()) {
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast (ray, out hit)) {
Debug.Log (hit.transform.gameObject.name);
OnPopulate ();
}
}
}
}
void OnPopulate(){
for (int i = 0; i < Elements.Count; i++) {
//Display All Element Names
Debug.log(Elements[i].ItemName);
//Display All Variants of each Elements
for (int j = 0; j < Elements [i].Variants.Count; j++) {
Debug.log(Elements[i].Variants[j].VariantMaterial.name);
}
}
}
}
Screenshot of script on how it looks in editor:
Is the ObjectCustomizer class attached to multiple gameobjects? That would cause some issues for sure.
Yes. I did add
"if (hit.transform.gameObject == this.gameObject)"
after
"if (Physics.Raycast (ray, out hit))"
in the update function. and this solved the issue :)
Answer by Ermiq · Sep 01, 2018 at 11:16 AM
As it is now, your ObjectCustomizer
should be attached to all of these different objects so it could instantiate new ElementVariants
instance for every gameobject. And it seems like you use only one ObjectCustomizer
. Where is it attached to by the way?
It creates only one new List<ElementVariants> ();
at the start of the game and then it uses just this instance only.
So, you need to add new ElementVariants
instances to every object you click on.
For example, you could add new ElementVariants
in some MonoBehaviour script which is attached to evey gameobject.
Another way is: you still can use only one ObjectCustomizer
but you need to add new ElementVariants
to the object you click on (if it has not added yet). You could do this in Update when you get the object's info:
if (Physics.Raycast (ray, out hit)) {
Debug.Log (hit.transform.gameObject.name);
// Check if this clicked object has no 'ElementVariants' yet
if (!hit.transform.gameObject.GetComponent<ElementVariants>()) // this will return
//'false' if the gameObject has no component of type 'ElementVariants' attached
{
// if so, add it
hit.transform.gameObject.AddComponent<ElementVariants>();
// now you could see the new 'ElementVariants' script being attached
//to the gameobject in the Inspector (or nothing will happen if the
//gameObject had a component already).
}
OnPopulate();
}
Then... To print individual values for every object in the console, you have to say your script which object's data you want to see (again, if you use only one ObjectCustomizer
).
To say this, you could send a reference to the desired instance of ElementVariants
into your OnPopulate()
method:
if (Physics.Raycast (ray, out hit)) {
Debug.Log (hit.transform.gameObject.name);
if (!hit.transform.gameObject.GetComponent<ElementVariants>())
{
hit.transform.gameObject.AddComponent<ElementVariants>();
}
// Lets take the instance of 'ElementVariants' attached to the gameObject
// that we just clicked .Now we're sure
//that it has one attached, so the following string will get this component
//and assign a reference to this component to the local variable 'ev'
ElementVariants ev = hit.transform.gameObject.GetComponent<ElementVariants> ();
// send this reference to the method.
// Now, everytime you click on some object, it will send that object's individual
// 'ElementVariants' instance to the method
OnPopulate (ev);
}
// make the method to take an 'ElementVariants' instance as a parameter
void OnPopulate(ElementVariants ev) {
// now all debug data will be individual to the instance we send in as a parameter.
// Just replace 'Elements' (we don't need this because it's not the instance of EV we need now)
// with the 'ev' which represents exactly that instance of 'ElementVariants' which
// is attached to the gameObject we had clicked in Update()
for (int i = 0; i < ev.Count; i++) {
//Display All Element Names
Debug.log(ev[i].ItemName);
//Display All Variants of each Elements
for (int j = 0; j < ev [i].Variants.Count; j++) {
Debug.log(ev[i].Variants[j].VariantMaterial.name);
}
}
}
Thank you so much.. this is a brilliant answer.
tried adding a line after
in update function.if (Physics.Raycast (ray, out hit))
if (hit.transform.gameObject == this.gameObject)
This solved it.
But, ideally, I've to follow your conventions. :)
Your answer
Follow this Question
Related Questions
Mouse Action on a GameObject member of a class 3 Answers
updating a gameobject variable from another script attached to another object 3 Answers
Access collider custom script's variables 1 Answer
How could I instantiate to a GameObject variable in a class? 1 Answer
How do I call a function in another gameObject's script? 5 Answers