I'm just starting with Unity and got pretty excited when I saw that the Event System existed, and I could create custom events. The event I need is 'IInventoryMessage::NewItemInInventory', so I went ahead and created the interface for that, set it up on my Inventory.
Then it came time to trigger the event, and the documentation threw me a little.
ExecuteEvents.Execute<IInventoryMessage>(target, null, (x,y)=>x.NewItemInInventory());
My confusion is that it seems to be passing in the target.
My hope was the Unity would keep track of all the components with the message's interface and call that when it was executed. But it seems I have to pass in the GameObject myself.
Is it the case that I'm supposed to keep a list of all the GameObjects I want to receive the message, and the loop over them to pass them into Execute? Why do I need the EventSystem at that point, if I'm already looping over the objects I know need to be called?
I use ExecuteEvents only inside my custom input system where the target it's always known and up to date (according to the pointer raycast). Whenever I want to send a message or trigger an action when something happened, I use the standard C# events, as BugFinder said.
Related
I'm working on a system that automatically generate and release scriptable object that represent uniqueness for gameobject with a given component attach.
The generation process seems to be working really fine, but I'm facing problem when I want to release the scriptable object.
The given script is tagged "ExecuteInEditMode" and is implementating OnDestroy method to advertise a manager that his scriptable object should be deleted.
The problem is that OnDestroy is called in 4 situation from what i can tell :
Click on play
Switching scene
Manual removal (the only one I want to work with)
On editor shutdown
I've been able to avoid the 2 first on with this :
if (Application.isPlaying == false && Math.Abs(Time.timeSinceLevelLoad) > 0.00001f)
But I don't find any good solution for "On editor shutdown" I've seen that EditorApplication.quitting can be use for that case, but documentation warn that this event is not called when unity crash or is forced to quit, and I don't want to lose all my scriptable object if the editor crash.
I'm looking for a robust solution to avoid this problem if someone can help me please.
Thanks, have a nice day
Just handle the application quitting event.
this event is not called when unity crash or is forced to quit, and I don't want to lose all my scriptable object if the editor crash.
When unity crashes, so will your program, so it won't work any ways. Just make sure that under normal operating procedure (so a normal shutdown) you save your modifications.
In Unity3D if you edit your scene and you don't save, if the editor crashes you lose all your changes. The same will happen for what you're building here. In order to mitigate this risk (since prevention is reasonably difficult if not impossible) you can opt to save every minute, always save each change to a temporary location, or save for example every play.
For example i added a script to my project that autosaves the scene(s) whenever i press play, so when editing the scene i press play now and then to test, and it all gets autosaved.
The official example put SceneManager.LoadSceneAsync in the coroutine
But it also works well when I call it directly.
Why the official example call it in the coroutine? What is the difference?
When you put it in the coroutine you are able to easily check the AsyncOperation state. SceneManager.LoadSceneAsync will load the scene anyway but if you want to check if the scene loaded completely or in what percent (and this is the main reason you are calling LoadSceneAsync) you need to check the AsyncOperation state.
You could check it in the Update method but it makes more sense to use a coroutine so you only check it when you load the scene. You don't need or want to check if the scene has loaded in Update every frame but only in the beginning when the scene loads.
There is no particular reason other than following the good practice of encapsulation.
My guess would be that the Unity-Engineer himself used the loading in a coroutine and just used that snippet for the documentation. I think he knew a lot of people would start with the snippet and go from there. Resulting in a lot of people who now have encapsulated scene-loading. I like that he cared for this.
I pretty much already made a little quest game for Android, and it only just occurred to me that I have to save player's progress.
I have a lot of interactive game objects (they share a script InteractiveObject that I made), which has an integer "CurrentPosition" parameter, that tracks how the player interacted with it. I need to save that parameter for all of those game objects.
What I figured I will do is pass this data to some "manager" singleton class after every interaction, and compile it into the list.. only I have nothing to identify those game objects by. GetInstanceID is unique, but not persistent, so its useless for this purpose.
Of course, I could just add "ID" parameter ty my script, and fill it by-hand in editor.. but that seems to be a suboptimal solution. There are a lot of those objects.
Any suggestions?
You need to somehow "register" your buttons
This is basically the same idea as "give them all an ID manually" except replace manually with "using code."
The first problem you have is that all of your buttons are hand-placed in your scene and all of their interactions are done by hand and all of this was done manually with no regard to "I'm going to need to be able to identify these later" which is how you've ended up here.
Option 1:
Have your code create, place, and name your buttons. As your code is yours it will just automatically generate the required ID and retrieve the state from the save file because you built it to handle this requirement from the get-go.
As you haven't already set your project up this way, this will be a lot of work spent refactoring your project to do it this way.
Option 2:
Do it manually as you stated you don't want to do. You may have to decide that this is the least work-intensive solution that is also reliable.
Option 3:
Create a class that all it does is have a registerButton function that shoves the buttons into an array so that they have an index ID value. When your buttons run their Start() method (if they do not have a Monobehavior script yet, give them one for this purpose) calls this registerButton method, which returns an ID (its literally just the button's index in the all_the_buttons array). Use this as your serialization ID.
Note that while this is deterministic (in that the buttons will register themselves in the same order every time) it occurs in an unknown order. If you delete, clone, create, or move the button around in the scene hierarchy, you will affect what IDs your buttons have, possibly invalidating any existing save files.
you can use playerprefs to save the game data , take a look at this link https://docs.unity3d.com/ScriptReference/PlayerPrefs.html
I am experimenting with a unidirectional data flow from a Manager object down into the components which it manages, and I need to know if I can trust that, for any objects present in the Scene at load time (those which are in the Scene Hierarchy in the editor), ALL of their Start methods will be called before ANY of their Update methods are called.
The documentation on MonoBehaviour.Start() says the following:
Start is called on the frame when a script is enabled just before any
of the Update methods is called the first time.
This certainly insinuates that what I am asking is correct, but it could just be odd wording. All my tests have shown that this is how it works, but I still want to verify before I start using this pattern everywhere.
Thanks!
Yep, all your Start methods will run first, and you can look at Awake as well if you are dependent on these methods.
I'm using CCAnimate to animate my CCAnimations. What I want is reuse CCAnimate action, so, when I want to play another animation I do something like:
[_animateAction setAnimation:animation];
This works more ore less, the problem is that the internal elapsed time for the animation is not reset, setAnimation is just setting the new animation. Is there any way reset an action in cocos2D? I have been lurking through the code and documentation, and it doesn't seem to exist any method to accomplish this.
Does anyone know what is the "best practice" in this situation?.
There's been a lot of confusion about reusing actions in Cocos2D. Apparently the docs say you should "initialize" the action again but this may not be working for all actions and it's definitely considered a bad practice to send the "init…" message to an already existing object again. This is similar to how you're not supposed to send dealloc manually to an object, yet you can do it.
Nevertheless, that's the way it is supposed to be for Cocos2D actions, so in your case to re-use the same animation action you would have to send it the appropriate init… message again:
[animation initWithDuration:5 animation:anim restoreOriginalFrame:YES];
[_animateAction setAnimation:animation];
As a side note, there's been a suggestion for mutable actions in the Cocos2D issue tracking system for two years now. The submitted code patch isn't going to work without modifications with the current Cocos2D version but it may be used to create your own mutable actions should the need arise.