I have one script which gets each instantiated object with a script on it (I have checked, they DO have the scripts).
public InfiniteParkourObject InfiniteParkourObject; // "InfiniteParkourObject" is the name of a script
private void OnTriggerEnter(Collider other)
{
InfiniteParkourObject = (InfiniteParkourObject)FindObjectOfType(typeof(InfiniteParkourObject));
InfiniteParkourObject.OnReset();
}
What this is SUPPOSED to do is run the “OnReset” function (in the InfiniteParkourObject script):
public void OnReset()
{
if (gameObject.name == "Cube1") // Name of inital object
{
if (gameObject.name.Contains("(Clone)") == false) // Gets original object, with no "(Clone)" marker
{
CubeID = 0;
Debug.Log("Set");
this.gameObject.GetComponent<MeshCollider>().enabled = true; // Does this instead of deleting so script still works
this.gameObject.GetComponent<MeshRenderer>().enabled = true;
thisCubeTouched = false;
MaterialID = UnityEngine.Random.Range(0, 20);
GetComponent<Renderer>().material = GridMaterials[MaterialID];
}
}
if (CubeID > 0) // Refers to every other object
{
Destroy(this.gameObject);
Debug.Log("Deleted");
}
}
When this happens, all the debug logs show up, and some things are changed (like the CubeID in the script on the original object), but everything else doesn’t change, even after repeated triggers. Does anyone know why this is happening?
I mean using FindObjectOfType
will find only the first instance in the scene hierarchy. If you have multiple instances, you probably aren’t going to get the behaviour expect.
What is your end goal here, exactly? What type of mechanic in what type of game are you trying to do with this? I’m getting infinite runner vibes here.
That said… why is the second code excerpt checking its own name? Basing your logic on a game object’s name is an incredibly fragile. If you want to know if a game object is an instance, you can compare its equality to the original instance or its original prefab.
2 Likes
You needn’t find this object every time a callback happens. Much less should you keep finding it all over again every time, at a minimum there should be a != null
check. But better yet: “find” the object when the script instantiates, ie in Awake or Start or OnEnable.
This is what Spiney mentions as brittle. Everyone will tell you to NOT find or compare objects by name. There are much better, more reliable, and faster means of keeping references to objects or identifying them if you look around.
Curious that you still keep the this.gameObject
when you can clearly see it’s wholly superfluous.
Generally speaking, you practically never ever need to prefix anything with this
in Unity scripts. The few cases where you might have to, it’s obvious.
Do note that MeshRenderer and Renderer will get you the same component (unless you have multiple renderers on that object which I’m not even sure is possible), so you just get it once, assign it to a variable, to avoid having the CPU do the same thing all over again.
So it turns out the issue was I was having the InfiniteParkourObject script from a single gameObject, as a [SerializeField].
I changed the code to look like this:
InfiniteParkourObject[] myItems = FindObjectsOfType(typeof(InfiniteParkourObject)) as InfiniteParkourObject[]; // Gets each object
foreach (InfiniteParkourObject item in myItems)
{
item.gameObject.GetComponent<InfiniteParkourObject>().OnReset(); // Refers to the script within the object
}
I did change the gameObject.name and switched back to an ID var which I used earlier though, so thanks for that!
You needn’t find this object every time a callback happens
I do this because every time the reset occurs, the cloned objects would have been deleted and (I assume) wouldn’t be stored still. Not only that, but there may be more clones than last time it was called.
Appreciate the help! :]