So here's another project that ended up being a lot more code than game, but I'm fine with that. Those tend to be my projects that are best received by other devs anyway, and in particular my experimentations with Twine and Unity have apparently been helpful to some folks, so this month started out with an experiment in improving my Unity/Twine integration and parser, and ended up with me making more additions to the Typogenic library for Unity and a simple demo of where I'd like to go with Unity/Twine integration.
This month, I revisit Typogenic, now with a twist of Twine and twee.
I've worked on integrating Twine and Unity as a game, and on request ended up going into more detail about how that worked. I also spent some time a couple of months ago adding feature to Typogenic to support clickable text and some additional rendering options. Now, with time to look at this again, I wanted to work on actually using Typogenic and Twine together to really put a Twine story into a 3D environment, but there was a minor problem.
The click detection didn't work for what I needed. The click detection support I myself added to Typogenic. Whoops.
It wasn't that it didn't work, but rather that its requirements didn't work for me. Click detection was based on offsets in the text mesh, so if the text object was rotated, the click detection didn't work correctly anymore. Time to write some more code.
Typogenic Click Support, Round Two
So as it turns out, this month's major project was to revise Typogenic's click support to track each glyph's location as a 3D Bounds object, which could be moved and resized to match the rotation of the text mesh. While this still means click detection is less accurate the further your text mesh is from orthogonal to the axes, it's still far better than the previous solution.
The good news is, this solution works nicely for what I need, and Thomas Hourdel, original creator and benevolent maintainer of Typogenic, has rolled these changes into the release version of Typogenic, available now for your enjoyment and at the remarkable price of free on the asset store and on GitHub.
Back to Twine
With click detection working, it was back to working on a general-purpose Twine integration. As in my previous project, I found the best way to handle this was to use Twine's tags to pass information to Unity. Aside from the basic formatting, I added the idea of Handlers. When a passage is displayed, using a prefab with a TypogenicText component and my PassageHandler component, one or more event handlers can be attached, as specified by the passage's tags. These components receive various events from the PassageHandler, which can make each passage behave differently just by changing its tags.
As it stands, a passage and its tags can control:
- Font face and styling (body and link text)
- Font size
- Passage location
- Camera location
- Custom events (fired when the passage is displayed)
- Custom event handlers (components added to the passage when created)
- Linking to external URLs
Here's an example tag set from a simple passage that falls in from above when displayed:
anchor:default camera:defaultCamera size:7 handlers:Defaults,Mover start:sky moveSpeed:30
So this, along with the inherent flow control you get from driving your program via Twine links, allows the use of Twine as a visual scripting tool. Honestly, it might be worth investigating using Twine just to trigger events and manage program flow, as a user-controlled state machine.
Circus Tricks With Text
Now that I'm using Typogenic instead of basic Text Mesh objects, I get all the fun of its great rendering options, and with click support properly dealing with arbitrary rotation, passages can be displayed pretty much anywhere in a 3D environment, and can even move around while remaining interactive.
Not exactly. What I do have is a demo of how this works, and in case this too is of interest to those other brave souls attempting to get Unity and Twine combined into the storytelling tool they really want, I'm including my code as a Unity package. It's not an out-of-the-box solution, but it's close - add a StoryManager prefab to a scene, assign it a Camera Rig (which can just be a Camera object - it's the object that will be moved around when a camera move is requested), and modify the PassageHandler and Driver scripts as necessary. The StoryManager prefab comes with the anchors I used in the demo - they're just GameObjects with the Anchor marker class, so the StoryManager knows to remember them as potential targets for passages and/or the camera. Hopefully that's enough to give anyone who's interested a starting point for using Twine and Typogenic together.
It's not a game, but I'm okay with that - it's a prototype, and it's a contribution to a very useful open source library, and it's my own demo code that might help out some other similarly-minded developers out there. Works for me.
Note: the following builds are available for testing purposes but I don't have the ability to test them. These are Unity builds so I don't anticipate any serious issues, but I can't vouch for correctness or performance of these builds.