Krilling Dev-Log #4

Published February 12, 2024
Advertisement

With deadlines approaching, and the delays we have had due to several team members ending up in the ER or urgent care in the past month, this week it was time to get a lot done. Last week I mentioned I was going to assist with some UI work, however, I ended up being not needed for that and I was shifted to working on the tutorial. I was tasked with the following:

· Adding animations to the AI based on what task they are doing

· Making Staff notice possessable objects that are not in the correct place and return them

· Starting work on the tutorial

First, for the animations, I was given some preliminary animations to add to the AI so that they could be fine-tuned later. Before the AI just went into their idle animation whenever they started a task. So, the only thing that needed to be done was to have a way of tracking the type of task and when they start the task play the relevant animation. I achieved this by adding to the ObjectiveType enum and in the StartTask function playing the animation for the given ObjectiveType.

Next, I worked on making the staff notice and return misplaced possessables. Most of this functionality was already created, as the staff already was able to notice a possessable missing from its starting location, search for it, and return it. The new task was to make it so when the staff sees a possessable and notices that it is not where it should be it chases after it, picks it up, and returns it. This boils down to essentially the same system as before, but skipping the search step. Luckily this was as simple as creating a SearchTaskTracker like before, but instead of adding the search, hunt, and return subtasks, we only add the hunt and return subtasks.

The only other issue to solve is the staff noticing the objects. The staff already has a trigger around it for when it is near a starting location of a possessable, so I simply used the same functionality for when the staff walks near a possessable. It gets the possessable’s starting location and asks it if the possessable is missing, if so it starts the hunt task.

The bulk of my work this week was spent on the tutorial. Specifically I spent a lot of time on the dialogue system. Another one of our team members created a basic dialogue system to display lines of dialogue and let the player skip through them. I started by moving the dialogue information to a sciprtable object rather than existing in a serialized field on an object in the scene.

This is much safer since the object in the scene could be deleted or changed and the reference to the dialogue could easily be lost. This way the dialogue exists on a saved file and can be dragged in to fields of objects in the scene to be used. I then made some edits to the dialogue system to allow different characters to talk back and forth. Originally this was somewhat possible by chaining dialogue sequences together, but this is less than ideal and difficult to work with. So, I changed it to be based on these Dialogue scriptable objects that contain a list of Dialog objects. Dialogue being the plural and Dialog being the singular. The Dialog objects contain a name and a list of sentences. This allows one Dialogue to contain multiple different names that are writing sentences.

After this I started work on adding the dialogue into the actual tutorial scene. This revealed a couple of problems. How can we tell when a dialogue is finished to start the next part of the tutorial. Also, we want to pause the game so the player can not do anything while the dialogue is running, but our current pause function brings up a pause menu and sets the time scale to 0 which breaks the dialogue box. I decided to tackle the first problem and aspects of the second at once, specifically the time scale 0 issue. To solve the time scale 0 issue the only thing that needs to be done is to get the dialogue box completely off the main thread. The main thread gets halted when time scale is set to 0, but any secondary threads will continue as normal. At the same time asynchronous work assists with the first problem of not knowing when a dialogue is done. One solution would be to provide some sort of information back to the TutorialManager after a dialogue finished, whether by an event raise or by a callback function. This is a bit messy and would require separating all of the sections of the tutorial into different functions that get called by either the even or as a callback when the dialogue finishes. However, by making the dialogue system asynchronous we can make the tutorial also asynchronous, and then simply await the dialogue task. I do this by creating a Queue of Dialogue in the DialogueManager that is in charge of displaying dialogue. As dialogue is started an asynchronous function is called on them. This asynchronous function is in charge of displaying the dialogue and only finishes when the whole dialogue has been run through. The asynchronous function instantly returns a Task that holds the information of its completion. The thread continues running utilizing the output Task while the function runs on the side and once it is completed it will inform the Task variable that it is done. This Task is assigned to the Dialogue object.

This allows the tutorial manager to await the Task on the object halting its process until the Dialogue is finished running. However, what if another Dialogue is started before the last one finishes. This is what the queue is for, the task is still created and assigned to the variable, but the process of displaying the dialogue is halted until the previous dialogue is done displaying. At that point the next dialogue in the queue is popped out and told that it is ready to be displayed, at which point the process will continue. This allows us to start two dialogues at once and await them in a predictable way without concern.

For the second issue we have already solved the problem of the dialogue running during a pause. However, we still have the issue of pausing without bringing up the pause menu, and what happened is dialogue starts, then the player tries to pause and the unpause. We don’t want the game to actually unpause, so we need to find a way to handle this. To solve this problem, I created a new freeze time function. This behaves completely separately from the pause function, except that the pause button will not affect the time scale of the game if the game is currently frozen. This means pausing and unpausing will work as expected during dialogue. However, what if the player pauses and then dialogue finishes, normally time would be unfrozen, but then the player has the pause menu open, but the game is running. To solve this, when time is unfrozen the time scale is set based on the pause state of the game. Thus, if dialogue finishes while the pause menu is open the game will remain paused.

Here is an example of how this all comes together and is used in the Tutorial Manager. As you can see it becomes very easy to start dialogue and wait for it to finish before moving on.

Lastly, I created a simple script for highlighting possessables in the tutorial. They are lights that once triggered flash on and off until the possessable they are highlighting get possessed, then they turn off. This is to help guide the player during the tutorial. I did this by just creating a highlight script that listens to a TutorialEvent for starting highlighting before turning on. While the highlight is on, it runs a coroutine that turns the light on and off with delays in between.

Then it listens to the OnPossess GameEvent, and if the possessed object is the same as the object it is highlighting it turns off.

That is all for this week. I was able to get a ton done this week which should be making up for how far I fell behind while I was sick. Next week will be more work on the tutorial, hoping to get a lot done next week as well as our release day is quickly approaching. With the dialogue system fully fleshed out, progress on the tutorial should speed up significantly. That is the hope at least. Either way I will be returning next week for another post.

0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement
Advertisement