I have a question about menus and their possible effect on performance. I'm making this game called "The Abandoned Planet":
https://store.steampowered.com/app/2014470/The_Abandoned_Planet/
As you can see in the screenshots, there are these directional arrows that allow the player to navigate through the game. Each Unity scene has anywhere from 10 to 30 backgrounds, and there are something like 300 navigable backgrounds in the game. Each background has its own "MoveDirection" menu (the menu with the arrows). Each one of those 300 "MoveDirection" menus references the exact same UnityUI prefab.
What I noticed yesterday is that, as each menu is instantiated, the MoveDirection menus start to pile up in "DontDestroyOnLoad".
This is a problem for my game, right? This is probably not going to be good for performance if 300+ menus are sitting in DontDestroyOnLoad, right? Is there a way for AC to save changes to those menus without them sitting in DontDestroyOnLoad? Can Unity destroy those menus? Not all those menus have data that changes. Can there be an option for the menu to be destroyed after it's Locked?
Looking forward to hearing back. Thanks!
It looks like you're new here. If you want to get involved, click one of these buttons!
Comments
To be clear: you have 300 MoveDirection menus in AC's Menu Manager, each one linked to a separate background?
If a Menu's Source property is set to Unity Ui Prefab, then it's intended to be accessed globally within the game, and so must survive scene changes. You can set it to Unity Ui In Scene to have it only reference scene objects, without instantiation/scene-surviving.
Since the layout of the Menus is the same across all usages, though, it makes more sense to either:
Thanks for responding, Chris. Yes, I have around 300 MoveDirection menus in the AC Menu Manager, even so, each one is referencing the same Unity UI Prefab.
But you're right! Especially your first suggestion.
To be honest, I didn't know that a Cutscene or Interaction (InScene or Actionlist) could be referenced by a Unity Event, but this makes sense.
What I can do is just have the arrow click event reference a Cutscene/Interaction that checks the local int variable, "Which location is player at?" (since my backgrounds are numbered), and then depending on that, it plays another Cutscene that transitions the camera, changes which arrows are disabled, etc.
Looks like I have another month of redoing everything. My bad. But I guess it's not gamedev if you don't have to do it twice. lol
Thanks again!
If you've a separate Cutscene for each instance of the menu, you'd be best off handling the logic entirely through a script you can attach to each menu.
AC variables and components can all be accessed through script - see the Scripting Guide's first page for a quick overview, but I can advise if you want to share details on exactly what needs doing.
It'll be worth it - your demo's great.
Thanks for the response, Chris! And I'm happy to hear you enjoyed the demo and I appreciate the offer for advice.
Here's what each click on the MoveDirection (Up, Down, Left, or Right) is doing:
https://imgur.com/a/EiuxvU9
How would you advise I achieve this through scripting? And do you think I should just have one MoveDirection menu, or maybe a MoveDirection menu for each Act (Five Acts)? Any questions you have for me?
Are the Actions involved here typical of a background-change? If so, all the Actions here (including those in the cutscene) can be parameterised, allowing for a single ActionList that is called for any background-change.
Unless you're keeping track of multiple Players across different scenes, you could move the location variable either to a Global integer, or attach it to the Player prefab directly via a Variables component. That way, you can refer to it within ActionList assets and then parameterise its value as well - no need to run a separate Cutscene.
Scripting would be more on the side of processing the clicks on your MoveDirection menu buttons - if you were to reduce it to a single Menu and one set of directional buttons. This'd reduce the number of menu Actions in your ActionList as well.
Thanks for the response. Great suggestions here. To be honest, I have no idea why I didn't think of using parameters. Probably just bad AC habits from back when I was developing my last game. lol
Anyways, at this link, I added another screenshot with an example of how I would "parameterise" the actionlists I was previously using.
https://imgur.com/a/EiuxvU9
Do you think that would suffice?
Also, things to consider:
How would you recommend sending a signal to the MoveDirection menu arrows that need to be disabled or enabled? (You know, like, on background 1 you can go left and down, but then when you go left to background 2, you can then move right and up... for example). If the MoveDirection UnityUI prefab is sitting in the Scene, should I add those as gameObjects and parameterise those as well?
How would you recommend I keep track of MoveDirection arrows that are turned On by a solving a puzzle? For example, you open a door and now the upArrow on the MoveDirection menu is enabled for background X. Since those happen only a certain backgrounds, should that just be another parameterised actionList checking local variables?
If I were looking at some custom scripting, where would that come in? What would you recommend?
Let me know what you think. I very much appreciate your input!
I can't see parameters in the screenshot - did you repost the last image by accident?
The neatest way I can see the system being handled is through a script that is used for each "mini" location in your scene. This script would store the necessary data about its associated camera, available directions, and have functions to move around.
Here's a (very) basic example - put your current scenes aside for the moment and give it a try in a new scene:
Add some locations to your scene as you've done before, but add this component to each backgroud sprite as you do so - filling in their Inspectors with a GameCamera and direction info.
The script will auto-set the visibility of arrows within a menu - the naming convention is important. You'll need to have a menu named "MoveDirection" with elements named Up/Down/Left/Right - or you can amend the strings in the script itself.
To switch to a specific location, use the Object: Call event Action to run the script's Enter function for that location's MiniLocation component. Note that this needs to be the specific component instance - not the script.
Then, to move in a given direction, use the same technique to call the GoUp / GoLeft etc functions.
To quickly test things without using Actions, the component's context menu has items to run these same functions.
Things can be extended with the ability to enable/disable directions (and record their states in save-games), but see if this is along the right lines.
Hey Chris. Thank you for that. First of all, about the screenshot, try this:
https://i.imgur.com/3hTrJtL.png
This is the screenshot I took of my parameterised ActionList. As you can see here, there are a few extra things that happen besides just changing the camera and enabling/disabling MoveDirection arrows. I have the MapMenu to consider as well as Ambience tracks to potentially swap out.
But I'm open to anything that improves performance!
I'm trying out your script. I have a menu called MoveDirection and the elements are called up, down, left, right. When the scene starts, I use Object: Call Event to run the **Enter **function for the script placed on MiniLocation 0. This works great. But then, I can't go anywhere. So...
One thing I need a bit of clarification on is this:
How are you suggesting the arrow keys reference these functions? Through an actionlist? If so, how will the single Menu MoveDirection differentiate between the MiniLocations and their associated scripts?
First, just test out the behaviour using the Inspector's context menu - we'll need to make sure the fundamental location-switching works from there before we incorporate it into a menu.
Assuming so: for the menu buttons - are you using Unity UI? What we could try is overriding the click behaviour (unset the ActionList on click fields and call via script). Here's an updated script that should do that:
Thanks for that. Yeah, I'm using Unity UI.
For that suggested script, I got a console error on line 43:
button.uiButton.onClick.AddListener (() => {Move;});
But I changed it to:
button.uiButton.onClick.AddListener (() => {Move();});
I also had to add IsEnabled to the GetElementWithName line from the first script. Otherwise, when using the context menu Enter function, the MoveDirection arrows wouldn't enable or disable correctly.
Anyways, it works! You can see this in the video here:
https://imgur.com/mD8GU2s
What's the next step?
It should be that the move direction menu buttons also work - have you tried using them to navigate?
Assuming so, the next step would be to add the ability to enable/disable directions per-location, as well as record such changes in save-games.
Share the updated script and I'll amend it with those features.
Thank you. Now, I went back and tried the arrow directions... while the ContextMenu GoLeft, GoRight, etc work, the UI arrow buttons do not work. I have the arrow buttons in the MoveDirection menu in the AC menu manager set to Click Type: Custom Script. Those arrow buttons are called "Up, Down, Left, Right", and I doubled check to make sure there were no spaces or anything. Not sure what's going on.
Here is the updated script:
Revert back to my script - you've removed the call to UpdateUIButton which sets up the onClick behaviour.
This function also sets the IsVisible property, so they should display correctly. Regardless, does that then give you the click functionality?
Gotcha -- OK. It "works". Here is the script as of now:
There are some strange things that happen though:
Maybe I'm getting ahead of myself though. Thanks for helping with this! Looking forward to getting it sorted.
Here's an update that should sort out the click/navigation issues. It also provides EnableUp / DisableLeft etc functions that can be called in a similar way to enable/disable specific directions:
As for the blocking/background issue: the Object: Call event Action should only ever run a single frame. If you enable the AC Status box via the bottom of the Settings Manager, and view the ActionList in the ActionList Editor at runtime, do they both indicate that its this Action that is running forever?
Hey Chris, that's great, and it works great as well! There was an error with this:
private void OnEnable () { EventManager.OnMenuElementClick += OnMenuElementClick; } private void OnEnable () { EventManager.OnMenuElementClick -= OnMenuElementClick; }
So, I just removed this one:
private void OnEnable () { EventManager.OnMenuElementClick -= OnMenuElementClick; }
I think it was because there were two private void functions called "OnEnable".
Anyways, it works with just the first one. It also solved the issue with running the OnEnter function in the background or pausing gameplay. Both work great.
I think the next step is:
Looking forward to seeing the next step. Thanks!
My mistake - but don't delete it. Rename it instead to OnDisable - I've amended it above as well.
I've also added an "ActionList On Enter" field that will run (if set) when a location is entered. To instead use ActionList assets, replace "ActionList" with "ActionListAsset".
To save the arrow states, attach this Remember component to each MiniLocation:
Thanks for that! I haven't gotten to test the saving because I encountered a bug with the initial script. It's difficult to describe accurately, so I filmed a little screen recording with narration to explain:
https://www.loom.com/share/5cc7e37fcbb14cbcabc12a9921c7fe2b
So, if I were to write down the problem, I guess I would say:
Does that make sense?
As an aside, I added UpdateMenu on each public void enable/disable for obvious reasons. Like this:
public void EnableUp () { SetDirectionState (up, true); UpdateMenu ();}
public void DisableUp () { SetDirectionState (up, false); UpdateMenu ();}
I look forward to sorting this out. Thanks!
Thanks for the video. I wonder if it's a case of the click being processed for both locations (i.e. clicking "up" is processed for the location that follows).
We can test this out by simply having a delay when switching location. Create a new Cutscene with an e.g. Engine: Wait Action of 1s, and assign it to each MiniLocation's ActionList On Enter field.
The issue with that is that it'll update the UI even if the location you're updating isn't the one currently shown. I've added a static variable to the script above that keeps track of the active location, so that UpdateMenu will only be called if there's a match.
Thanks. First, the static variable you added works great. Previously, I added the "UpdateMenu" function because if you were to enable a direction arrow through an actionlist, it wouldn't activate that arrow until OnEnter was run again. But your solution works great. I can now enable an arrow through an actionlist and when gameplay resumes, it's enabled.
Now, I tried the Engine:Wait suggestion... same issue. Interestingly (and this occurred even during my last post but I left it out), when on MiniLocation 3, clicking the up arrow (or pressing w) will not go to MiniLocation 4. It's as if it's stuck between 1 and 3. Up on 1 goes to 3. Down on 3 goes to 1, but up on 3 goes nowhere (here's a demonstration):
https://www.loom.com/share/aa350e0b6e3e47ebbd0d2d5e3718806e
This is also the case if I disable GameObject 3 completely, and make 2 go to 4. It'll get stuck between 1 and 4 then, and won't progress to 5. If that makes sense.
I'm not a great coder (trying to get better), but nothing seems awry to me as I look at the MiniLocation script. Even so, I have a question about Unity:
I look forward to hearing back. I know I've said it before, but it bears repeating; I appreciate you taking a bit of time each day to respond.
--
Also, not sure if you use GitHub, but my project is in GitHub (I use GitHub desktop). I could temporarily add you to the project. Let me know.