|||

04 - Huzzah for Naninovel!

When I created this file to start writing this devlog, I had a quick look at my previous posts to check how I formatted the filename and… it’s almost been two months since my last devlog. Cough

Well, two months ago I was working on learning and implementing the Generic Character system from Naninovel for my game and was… sort of getting somewhere. At least, I thought I was.

But when I started to try to actually program my script, I naturally discovered that I hadn’t quite gotten things down. Since I was using the Generic Implementation, I had to handle character appearances and disappearances myself. At first I just had it set up to activate the parent object of my sprites, but that felt way too abrupt once I started actually putting it in the game.

That then sent me down a deep rabbit hole of trying to get a crossfade working that didn’t involve having to babysit every single individual sprite of a character while also not having weird semi-transparent artifacts. I found a solution to the first issue in the community plug-in Nested Fade Groups, but this solution still had weird issues with doubled up transparency. I figured Ah well, I’ll just make the animation real quick so hopefully no one will notice.’

A while passed, and I worked on the script of my game, then one day while poking my head into the Naninovel Discord group, I noticed someone asking questions like I had been months ago. I decided to say a few things about what I’d learned and ended up in a conversation with an Admin, then eventually the Main Developer.

Long story short: All my dreams are possible - Layered Characters can now have animated sprite parts.

I’m not entirely sure if this was always possible, or if there were some tweaks made behind the scene, but I honestly don’t care. It works!

So today I spent the morning setting up and testing a test version of my main character using this new setup. Tada!

And as it turned out, I did end up using the Nested Fade Group plug-in. The way I’d been getting the mouth animation to work with multiple mouth types, was by putting all the not speaking images in one object and all the animated talking ones into another and using the On Started Speaking and On Finished Speaking methods from the Layered Character script to active and deactivate the relevant mouth group.

For Generic Characters and Layered Characters where all the animations are routed to an Animator Component, this worked fine, but I found when I tested it with this set up that uses Layered Expressions, the animations would get stuck.

Based on my research before into Unity’s Animator, as well as my own testing, I’ve found that sometimes the act of activating (or deactivating) an object can be interrupted by animations playing. I’m not entirely sure why exactly this happens (like, is it an intended feature, or just the result of cascading design decisions coming from elsewhere), but either way, it means using my old method to do lip syncing isn’t an option.

So it’s a good thing I learned about that Nested Fade Group plug-in!

To my great shock, using the On Started Speaking and On Finished Speaking methods to set the Alpha of the Nested Fade Group parent to 1 or 0 as needed completely solves the issue. In fact, it also allows for a character’s mouth to be changed while they’re still talking (as seen in the above GIF) by using nested Naninovel character commands like this: As a short aside, the way Layered Characters are controlled is through Layer Composition Expressions that looks like this: All that above is directly from the Naninovel online guide here.

Finally, I also tested one last thing with this new system that may not be so relevant to other games, but is quite relevant to how I want to do things and that’s where the testpose in the curly brackets comes in.

In Naniscript (the language that Naninovel uses), Custom Variables are called within a script by putting their names in curly brackets. This may seem odd if you’re coming from a programming background, but is actually a feature of Naninovel. In Naniscript, dialogue is the default while everything else (commands, variables, labels, etc) must be denoted. This makes it a lot more straightforward for writers to just get writing and not have to constantly be putting things in quotation marks or whatnot.

Going back to my testpose shenanigans, the reason why I have it inserted there is that earlier I set the value of testpose to A and, if you look at my Layered Character… You can see that each of my preset poses (or Composition Map) also has a letter in front of this.

This way, I can set the pose of the character with my Custom Variable testpose then say what expression I want without having to remember what pose the character is currently in.

This also works for calling individual layers within the sprite as well which is why I’ve labelled my objects like this: This isn’t required from a Naninovel point of view, but is instead how I plan to implement multiple poses for my character and perhaps even different outfits. I’ll have to see if this works in a production context, but for now, I’m happy with it!

Time to get back to writing the ending of the game then.

Up next Urasawa Naoki - The Lies Mangaka Tell 05 - Changing Engines & Changing Projects
Latest posts The Undead 6 The Undead 5 The Undead 4 The Undead 3 The Undead 2 The Undead 1 The Undead (fan translation) 06 - back to Ren'Py & Concept Art 05 - Changing Engines & Changing Projects 04 - Huzzah for Naninovel Urasawa Naoki - The Lies Mangaka Tell Xian Xie Fate Is... Fate Is 3 Fate Is 2 Masahiro Sakurai - Broad Input, Broad Output A Collection of Inkle Wisdom Inkle and UX 03 - Learning to Move 02 - An Adventure From Ren'Py to Naninovel 01 - Engine Woes Head In The Stars