SamSuka
StudioKlondike
StudioKlondike

patreon


[Background Blog] Astatos - Log Menu

Hi Patrons!

Compymono here. Today I wanted to go into a few details on some UI design and implementation work I recently did for the Astatos game by taking a look at the log menu you can find in the story mode.

Designing A Log Menu

So first things first, we have to define the bounds of what the design needs to accomplish. 

Then break that down to the functional requirements.

Then work out the constraints.

So above we can see the standard layout for the story mode, complete with a random non-spoiler image for the background and our Likulau stand-in! In the top right we have the button for the log and the pause menu. I'm already starting with these buttons in place as I knew I'd be adding the log functionality into the future when I designed this UI last year.

The easiest place to display the menu was over the scene view in the middle of the screen. This way the buttons at the top remain accessible to close the menu and you can still see the current dialogue / decision at the bottom of the screen. 

The background is pretty variable in this position so we need to make sure everything remains easy to read even with bright scenes behind it. My solution is to stretch a black to transparent gradient texture over the display area. The panel fades in so it gives a nice gradual appearance to how the menu shows up. On top of this the text objects have a light drop shadow on them so they remain somewhat readable even with white on white. (As a part of our text implementation this shadow is actually applied to all text but it's only noticeable in situations like this.)

Once the basic layout is completed I build out all the objects needed to replicate it in the Unity scene.

[I'll be getting into some Unity stuff here so feel free to skip if you're not familiar with what's going on]

Here LogDisplay is the parent of the menu. Background is our gradient, Parent is where we'll be putting the list of dialogue, Title is the object that says "Log" in the top left, and Scrollbar is the scrollbar on the right hand side of the menu.

Digging into Parent, this has a scroll rect component that acts as a scrollable area. The view of this area is Parent itself and the scrolling content is Layout. Beneath that Layout is set up with components to expand its height and position based on how many DialogueParent objects there are. Each DialogueParent object is one entry in the log list. Character Name and Dialogue Text are pretty straightforward, while Arrow is a sprite that appears next to the hovered or selected element in the list. Arrow and Character Name are grouped under ArrowParent which has a layout component that adjusts the position of the arrow to adjust to the length of the character name since its size varies.

Now going to the start of the code that generates the menu itself. (There's a few more functions to this script but this covers the broad strokes)

The Init (initialisation) function takes two arrays of strings, one for the character names, and one for the lines. We do a quick check to see if the strings are empty and to throw a warning if it does. (However, I already made sure this menu won't open if no lines have been displayed yet so it's just a precaution)

Then we do a quick loop to clear out any remaining lines on the object from the last time we opened the menu.

Next we loop for the number of lines we have to display. Each loop we copy DialogueParent and set it to be a child of Layout. Then we set that object to be visible and initialise it with the data it needs.

Now we have the menu built all we need to do is show it, so we make some calls to the animation plugin we use to tween the transparency of the menu from invisible to visible and make the menu intractable.

Last thing we do is set the last line in the menu to be the one selected by default.

With that and a few more complex functions for animation and navigation of the menu, we're good to go!

As far as polish goes, there's a couple things to go over. There's a slight animation for the selected option in the list where it is made brighter and given an arrow so you know where you are when using a keyboard/controller. Clicking on a line in the list will jump it to the centre, as does moving up or down with a keyboard or controller. The dialogue list fades out at the top and bottom using a custom UI masking shader. (Took me a while to find a good solution for this so I'm happy I finally having it working!)

Plugins Used: LeanTween UnityUIExtentions SoftMaskForUGUI 

A few things to note with the code above. I made this more on the quick side of things than the performant side. Destroying and Instancing a bunch of GameObjects in Unity in the same frame can be pretty bad for garbage cleanup and might cause hitching. On the other hand this solution is simple and works robustly. One solution for the future is probably going to be re-using the objects that are instanced rather then destroying and ranking them each time you open the menu. At the moment though, to combat any potential issues with performance, the display limit of the log menu is set to the previous 50 lines of dialogue. There's not anything hardware demanding going on with the graphics and systems in this system so it's not worth the extra time to optimise it for now.

Overall this was a pretty fun little menu to build across a day so I hope players appreciate it when the game is released! (I sure appreciate a log in any game since I'm a massive butter-fingers with the advance button and miss stuff all the time)

In any case, thanks for reading this little post. Hope to be able to share more with you guys in the future.

- Compymono

[Background Blog] Astatos - Log Menu

More Creators