Descant is a Unity 2022.3.x or later dialogue system plugin. The Unity Asset Store is chock full of many such types of plugins, ranging from feature-rich, to ultra-minimalist, to downright bad. Descant aims to hit the sweet spot between quality UI, powerful features, and easy-to-lean functionality, while also addressing many of the game-specific consequences of the standard dialogue manager setup. Besides acting as a standard tool for creating, saving, and actualizing non-linear game dialogue, it also pushes the envelope by adding optional dialogue-enhancing node components that introduce features to break away from the overused and underwhelming trends seen in many interactive fiction games. These enhancements act similar to Unity’s standard GameObject Component system, and can be applied at-will to nodes. This modular approach is so-far not explored in the world of Unity dialogue systems. The project will be free (and collaborative open-source) forever. Feel free to send me a message or submit a pull request if you want to make any changes.
Timeline
- Basic node functionality
- Some QOL changes
- Grouping
- Dynamic number of Choice outputs
- Started work on saving
- Added Mac turds line in .gitignore
- Added separate files for features, interaction research, pitfalls & successes
- Added a proper README, that I'll try to update as time goes on and I add more references in
- Loading and saving to files not on the root
- Added 'needs-to-be-saved' asterisk when not auto-saving
- More rigorous connection data checking
- Added close button for graphs
- Started work on the Runtime scripts
- Finished small tweaks to the Editor files
- Cleaned up the Runtime controller, so that's ready to go
- Started adding in-depth comments to most of the files
After the comments are done, I can start doing the actual creative work of adding the node and conversation components
Monday, October 9th
The base system has finally been settled! I have the Editor script all done (save for a few QOL or functionality tweaks), the saving works pretty well, and I’m now getting started on the Runtime scripts. While I do that, I’ll be working on the unique aspects of Descant. That’s where the real creativity will start to shine through, and I’ll be journalling a lot more (I hope). Presently I’m going to try writing one of these journals every 2-3 commits. To coincide with my general pattern of milestones. I’ll also be ramping up my explanations in commit messages, going beyond the standard dry descriptions of changes.
I’m nearing the proof-of-concept milestone that I played out for myself originally. I’m feeling good about my progress, though I know that the ‘components’ system that I had dreamed up will take some finagling to get working. I think that my next steps for the project are to make a ‘build’ of the current package, build a super simple runtime testing interface, then get going on the ‘components’ system. On Jonathan’s recommendation, I’ll also try to classify and narrow my sights down to just 2-3 for each of the node, graph, and actor scopes. I’ll be doing that soon too I hope.
- Updated to version 0.2.0
- Created testing scene
Wow! It finally works! I knew that theoretically it does work in runtime, but now I'm able to fully test Descant graphs in-game. Feels amazing. Obviously I still have tweaks to do, but it's almost production ready (at least in a basic operational sense).
I think I need to get started on the juicier features soon, so that will be my focus the next time I work on it.
Monday, October 16th
I’ve added a new file to the documentation, detailing all of the ‘components’ that I will be writing for the system. I have node, actor, and full conversation components. Theoretically, these will be able to be added to their respective types in a totally free, totally modular fashion. Presently, I’m just getting a hold of how I’m going to program it. I’ve added a bunch of TODOs, and have started on about half of the node components. Some are invokable, meaning that they trigger some effect when the node they’re attached to is reached, but some are just for data storage, to be accessed by other scripts which might want to make use of their properties (e.g. a TimedChoice component won’t ever trigger anything itself, but its data members will be necessary for the DescantConversationController scripts to reference when updating countdowns and moving to the next node).
I’m feeling really good about what I’ve got done so far, but it’s definitely going to be a lot of work. Maybe more than I thought. I think it might be best to push my prototype date a week or so into the future, giving me time to get these all working. Instead of doing user testing right away, I’ll run a seminar where folks can comment openly, and I can discuss it in a casual manner. Until then, I’ll keep coding away at these components.
- Made a list of all the components that I'll need for nodes, actors, and conversations
- Started work on an Actor script
- Started adding some of the node component scripts (some of which inherit from an invokable interface)
- Made it so that components have access to the controller, and can affect it at runtime
- Made it so that the controller never touches the components, save for invoking them and updating them
- Finished 90% of the node components
- Reorganized the interfaces so that it's more in line with the new schema
Wednesday, October 25th
I’ve decided to focus on the node components for the moment. Once I get them down and working, then I can add the Actor and Conversation components if I want to / have time to. I’ve been able to get most of them half-written, I started work on saving them, and I’ve added probably 90% of their UI implementation in the Editor. Now I just need to read the data when saving, load it properly, and get it working in runtime. I’m quite pleased with my progress, though I know that I need to start interviewing / demoing the software soon, to get an idea regarding the UX and feasibility. I’ll want to meet with Jonathan soon too to discuss my progress.
As a sidenote, I also reorganized the project so that it only uses one Assembly Definition. This way I can avoid circular dependancy. This wasn’t an issue before, but now that I have the Components going, it’s come up. The Components use both the Editor and the Runtime, and those both use the Components. So I had to put them all in the same Assembly Definition.
- Started work on saving Components
- Finished almost all of the Editor Node Components UI
- Working on connecting the Editor to the Runtime via the components
- Added a new attribute to group the component parameters by group name instead of number
- Made their generation in-editor more steamlined
- Added yet more TODOs
- The next step is actually being able to save them!
Tuesday, November 7th
It’s been a little while since I last check in, and a lot of organizational changes, QOL tweaks, and bug fixes have come along. Most importantly, I finally settled on an appropriate package folder structure. I’d been messing around with a 2-folder and 2-folder systems with just as many Assembly Definitions, but I’ve settled now on what I like the best. It allows for Runtime scripts to reference Editor scripts, and allows for them to both reference Components scripts. When the Components will have to start referencing Runtime though, that’ll be a problem. We’ll figure it out as it comes. I also added a bunch of comments to new scripts, converted my Descant Graph files from .desc to .desc.json, and hid the Components scripts for the mean time, as I prepare to push a v0.1.1 build up to GitHub.
The reason for all this organization is the fact that I’ll be demoing Descant in its current state and talking about the future design goals with this semester’s CART 415 class. I had talked with both Jonathan and Jongwoo Kim regarding possibly doing a Descant workshop in their more practice-based classes. The students would benefit from using my system for their game jams (albeit in its simplified state), and I would get feedback regarding usability and my future goals. I was worried about getting it all working and buildable by tomorrow, when I’ll be doing the workshop, but everything is working perfectly now, and I couldn’t be happier!
The next goals after the workshop are to continue developing the Component system by allowing the Components to be saved to the DescantGraphData file. After that, it’s onto run-time implementation, which will be no small feat.
- Separated Components assembly (and commented out its external references)
- General organization and cleaning up
- An unfathomable bug has appeared that makes the dialogue system completely unbuildable due to the fact that omch.descant.editor doesn't seem to want to be referenced by omch.descant.runtime
This reverts commit 2e2ab0add860c32eff64ec906d245ffab31a42a8.
Future TODOs:
- Component integration with runtime
- Autosaving check for components
- Runtime Component invocation
- Smoother runtime scripts and scenes
- Added the ability to chain multiple Response nodes one after the other
- Created a new DescantActor class
- Created a DescantActor Editor
- Made the DescantActors available to the DescantConversationController
- Better component and actor saving
- Added a new way to pass data between the components Assembly and the Runtime assembly
- Renamed some stuff
- Added ChangedNode functionality
- Improved DialogueUI hiding and showing
Future TODOs:
- Finish implementing other Components
- Add comments
- Smoother runtime scripts and scenes
- Added ChangedResponse, Interruptable, and LockedChoice Components
- Added a typewriter option
- A bunch of small tweaks here and there
A few remaining todos:
- Proper error handling
- Possibly adding a DescantIfNode
- New comments
- Easier implementation
- Tutorial
Thursday, November 23rd
By this point in the project, I’m starting to think about the end of the independent study. I’ve been able to get a little bit of user testing through some students in Jongwoo’s class, and I plan to run a Descant workshop in TAG as well (either in December or in the new year). As for the project itself, it’m getting close to the end! I’ve successfully implemented pretty much every single Component! I just have to iron out a fair number of bugs, add comments to nearly everything, and develop some proper test scenes. I aim to get most of that done in the next week or so.
After that, the remaining tasks for the independent study are to write the report and get the ball rolling for actually publishing the package on the Unity Asset Store. I feel great about the current status of the project and hope to push forward just a bit more to see it to completion. The possibilities that it’s already affording are truly fantastic.
- Added TODO file with easy, medium, and hard fixes
- Fixed a major ChoiceNode issue with choices that have no connections
- Closed off a bunch of possible error messages with temporary TODO markers for future custom error messages
- Added text filtering for graph editor and components
Gonna try this out the next time I'm working on the project
- Renamed all instances of 'conversation' to 'dialogue'
- Made a more streamlined process for Invoking UnityEvents, and made all Components that do so use it
- Added proper error messages with a unified formatting
- Added a NoFiltering attribute to make certain fields in the Components not subject to being filtered
- Made TMP text styling work with the typewriter
- Added text filtering to the Actor Editor
- Unified EventScript and ObjectScript into one Component (if the ObjectTag field is empty, it simply acts as an EventScript)
- Started adding comments (gonna be a looot of work)
- Added comments to the Runtime scripts
- Fixed a few small issues with Components calling scripts with no name or method name
Friday, December 8th
The semester is coming to close, and I’ve completed the functional aspects of the system. All the editor, runtime, saving, and loading scripts are done (save for a few tweaks), and I just need to put together proper test scenes and documentation before I publish on the Unity Asset Store in January. The report is finished too.
In the spirit of reflection, it’s interesting to see how the project has both slowed down and sped up over its lifetime. Development took a long time, and meant that I wasn’t able to accomplish all my goals, but now I’m able to create Components extremely quickly, and demonstrate it live. The development is practically done, even though it took a while. I think that now my goal should be polish. Make it look nice, make it feel nice, and get to ready for public viewing.
As mentioned below, I plan to demonstrate Descant in TAG at some point in the new year. I was talking with Jonathan today and he recommended I showcase the project in an academic showcase/conference coming up in May, which is very exciting. I’ll definitely be applying. Good things are on the horizon, though I definitely deserve a break.
- Added actor portrait functionality
- Added Component that can be used to change portraits
- Fixed some rounding and calling bugs
- Added comments to the parts changed
- Added a proper Usage section in the README
- Cleaned up README
- Started work on a Component Directory file to help explain the Components
- Divorced the dialogue data from the DialogueUI script (so it's simpler to use)
- Created new simple runtime script to call the beginning of the dialogue
- Added some help text to the example scene
- Added a few more TODOs
- Updated README slightly to have better links
- Made sure nodes created in the graph editor spawn in the right positions
- Started work on the documentation website (housed outside of this repo)
- Added an option to inject actor variables into Choice or Response text
Also updated to v1.0.0 for the upcoming release!
- Added comments to all uncommented remaining files
- Updated README a bit
- Added website
- Updated package.json
- Added autosave back in
- Now saving a graph panned position and scrolled scale
- Added the framework for a search function (not fully implemented)
- Added a comment box under each node and each group
- Added DescantActor references to the default components
- Added a SerializableDictionary to the DescantActors
- Added a ton of new DescantComponent variable types that can be added
- Added a small version indicator in the editor
- Updated the screenshots
- Updated the README and the website
- Added a null check for player portraits
- Turned Action callbacks into UnityEvent callbacks (so they can be accessed in the editor)
- Various other small bug fixes
- Added SpeakerName, Speaker Colour, Override Speaker and speaker name functionalities to nodes
- Responses now only appear after a typewriter has finished typing