I’ve never posted here before but I’m stumped. I wanted to try and avoid using GameObject.Find, and from my reading this is kind of a heated debate and it seems using Find for these two instances in my project wouldn’t be harmful. However, I’m dissatisfied with just accepting the fact GameObject.Find is working perfectly but wiring up in my inspector isn’t.
I’d like to learn from this and I’m pretty stumped.
What I’m doing is:
When Player dies (lives variable decremented) and new lives value passed to UIManager script component of Canvas to display amount of lives remaining.
Like @lordofduct , I’m having trouble nailing down your exact problem and the lack of code tags is mangling your post, but I can confidently say that, regardless, GameObject.Find is the wrong answer. It always is. In 12 years of using Unity professionally I have literally never seen a time when GameObject.Find was the right way to solve a problem.
And I’m so sure about this that I once wrote an article about the many reasons not to use it and what to use instead. This is probably a good use case for the singleton approach I think. BUT, be sure to read the article on the caveats of using singletons before you do, because it’s really easy to get into bad habits with singletons and use them where you shouldn’t.
Thank you, I edited my original post and hope that’s good enough.
I apologize, thanks for pointing that out. I was all flustered and quickly wrote the post lol. I updated it and hope it’s more clear. Just to be clear here; I’ve got an Image child element of Canvas that I’m using to display little ships to represent the amount of lives my player has.
If I use GameObject.Find(“Canvas”), everything works as it should and the images are in synch with player lives and update.
If I make a variable of my Canvas GameObject in player and attempt to reference it that way, everything works except the image updating. The Debug.Log’s fire and reflect all is working behind the scenes except the image updating.
I read the article. Some of it went a bit over my head, however it seems like what I’m trying to do here is:
Public member assignment via Inspector
public class CreepyFollower : MonoBehaviour {
public Transform target;
void Update() {
transform.LookAt(target.position);
transform.Translate(Vector3.forward * Time.deltaTime);
}
}
I guess why I’m confused is because the scripts are communicating and my code is working. The only thing that isn’t happening is the image isn’t being updated by the Canvas.
The only reason I questioned my instructor on this GO.F decision was because I had read to avoid them and I wanted to practice avoiding GO.F. Thank you for replying!
If you need further reasoning, it’s because GO.Find goes over all object in the scene and that, while very well optimized in unity 5+ it still takes a while.
if you do this on initialization(like i’ve said before) it’s ok because its normal for a program to take a few seconds to load.
but if you have a reference it doesn’t have run a search(and doesn’t slow you down during actual gameplay), and while it does take up a little bit of memory unless your on a tight budget for some reason(maybe low end mobile) it’s negligible.
I see. Do you know why I would be having this issue with my canvas’ image element only updating if I use GO.F?
My instructor in this course, is using GO.F like mad for multi-script communication every frame. It’s wild. Not only that we’re instantiating and destroying objects left and right every few seconds.
I built a parallel version using an ObjectPooler and the FPS is pretty remarkable. I wanted to see the performance differences between the methods. In my version with the ObjectPooler I’ll need to avoid using GO.F to have a good contrast.
If what I’ve posted isn’t good enough for anyone to understand fully what’s happening and make a sound observation I’d be more than happy to provide whatever you’d need. I’d really like to learn from this instance with the canvas.
I’m properly confused on instance vs prefab. I’ll go do some reading on this. Perhaps it’s my issue.
I decided to try variable assignment on two other GameObjects, one which calls a Coroutine on space bar and I get an error saying the object is Inactive. Even though visibly it isn’t. I used Debug.Logs to check active status before and after spacebar and it’s true before spacebar, the call goes to the coroutine method and then the object is called inactive.
I’m grateful for the opportunity to learn this and get past it now.
Prefabs are objects that you dragged and dropped into the project window. You can find prefabs in almost every project. The idea is that you construct your objects and then turn them into some sort of blueprint, that can be instantiated either during scene building, or through code.
Of course, scene objects can be duplicated as well, but they belong to the scene, whereas the prefabs are project assets and hence they’re available in your entire project.
As an example, if you build your scene, you’ll usually get into the situation that you import a model (or create an object in the scene), say a door, and the door needs a collider, a trigger area, perhaps a door script, some changes to its material or other components.
This is a setup that you might need multiple times, possibly in multiple scenes, so you want to save this as a compound object / object hierarchy with pre-defined components and certain values. You’d drag&drop the instance from the scene into the project, and now it’s become a complex asset that is easy re-usable.
Later on, you can always get back to that prefab and re-use it. When you create instances (either during scene building or at runtime), the instances can maintain their own individual state. And you can always reset them to match the state that was saved with the prefab.
The prefab system has recently faced a major revision+update, and is now even more powerful than before - but the above is the basic idea. Enough to get started. Defintely something that should have been covered by your instructor. I’m surprised this is new to you.
Coroutines are indeed bound to gameobject’s active state, i.e. they cannot be run / they are stopped when the object is either destroyed or deactivated. Looks like your code sets the object inactive.
Performance isn’t the only reason to avoid GameObject.Find, and using it in Start() doesn’t avoid its other problems (which are outlined in the article I linked above).
I’m just flat out confused. I’ve tried variable assignment, but one of my GameObjects calls two coroutines onkeydown spacebar. Even if I set it to active, it has no parent and doesn’t visibly deactivate it is false on spacebar. All debug log calls show it as active until the instant I push spacebar even if I setactive(true) on spacebar before coroutine calls.
Lol… GO.Find works perfectly. I don’t see how I’m doing variable assignment wrong in terms of getting the component and wiring it all up. I’m not confused about instances and prefabs (at least I think). The scripts communicate and everything is working find so I don’t think it’s my variable assignment.
I’ve googled and read TONS of other peoples “coroutine could not start because game object is inactive!” and it’s a rule regarding coroutines I’m failing to grasp? GO.Find NO errors? Lol.
So as for prefabs I was solid on what they were, I have even instantiated a bunch of things but I guess calling the active version of my prefab an instance confused me (I’m not sure why at this point). Instantiating… instance of prefab lol…
I appreciate your breakdown on it though.
GO.Find will call and fire the coroutines perfectly fine, even trying to setactive(true) won’t work and the GameObject is reported as activeinhierarchy and is visibly active before spacebar is pressed to fire coroutines.
GO.Find will work perfectly. When I try to use variable assignment to not use GO.Find, it breaks. I must be wiring them up wrong. I don’t know. I feel like I’m chasing my tail.
I made my main camera instantiate the SpawnManager (this has the coroutines).
Then, my GameManager on Spacebar down instantiates my Player
My Player communicates to SpawnManager to run coroutines that spawn enemies and powerups.
I made SpawnManager a SharedInstance. This worked. I’m so confused at this point I’m not entirely sure why. I think I made my SpawnManager a singleton??
So we’re running out of options. Can you add a screenshots that shows how you linked the instance to the field in the inspector? Pretty sure it’s just a small detail that we’re missing here.
It could be that you are updating the wrong UI Manager, in the Debug functions there is an optional parameter called “context”, if you pass in “this” as that parameter in your scripts it will allow the debug console highlight the object that issued the debug log when you click on them. You can use this to confirm that the right objects are being called.