From the Burrow

TaleSpire Dev Log 492

2026-01-25 21:56:21 +0000

Friday went well enough. I was preparing to rewrite the editor code that runs the effects, as I need to make it work outside of play-mode.

This was a good time to restructure the project, so I was doing that and experimenting with what Unity allows it terms of spreading the definitions of scriptable objects over multiple assemblies. The answer is, in short, it doesn’t. The C# compiler is happy enough with it, but Unity’s runtime is not. It’s fine though, it was simply an effort to keep the codebase cleaner by separating the code that is needed at runtime from the parts that are not.

Tomorrow I’ll be getting stuck into getting particles back on screen, and exploring ExecuteAlways, which is something I’ve only used for very simple systems before now.

Seeya in the next dev-log

Disclaimer: This DevLog is from the perspective of one developer. So it doesn’t reflect everything going on with the team

TaleSpire Dev Log 491

2026-01-23 12:56:50 +0000

Hey all,

Decent progress yesterday .

  • Fixed cases where curves connecting nodes were laid out incorrectly during certain inputs
  • Dedicated types for various internal IDs
  • Added the ability to drag/drop resources from the Unity project directly into the canvas.
  • Improved debugger integration
  • Users can now replace connections without removing the old ones first.
  • Added a way to specify default values for connectors
  • Got user-defined functions to compile correctly when used in other effects.

The drag/drop one is simple but it’s nice to be able to drop a texture into the graph and get a texture node immediately. The same is true when dropping in a user-defined function asset.

drag-drop texture asset drag-drop function asset

The connection replacement, too, is a nice quality-of-life improvement. Previously, connectors could be turned into value slots with a right-click action. However, based on feedback, we’ve moved to showing the value slot whenever a connection is not made. It doesn’t always make sense to have a slot though, for instance, you wouldn’t want to type a texture!

modifying connections and showing default value slots

Today I’m going to focus on improving resource handling. In the graph, resource-nodes are nodes where the value comes from the CPU, rather than being computed on the GPU.

Seeya you then.

Disclaimer: This DevLog is from the perspective of one developer. So it doesn’t reflect everything going on with the team

TaleSpire Dev Log 490

2026-01-21 21:34:11 +0000

Heya folks,

As promised, the minimally viable dev log!

I’ve continued work on the fixes post my major refactor of the particle tooling. Today has involved

  • A bug in node deletion
  • Fixing deserialize as it wasn’t preserving node-inputs with fixed values (as opposed to a connection to another node)
  • Improvements to the user api
  • And assorted small fixes and improvements

Next up, I’m making it so removing a connection from an input automatically turns it into a value input (I’ll show a gif tomorrow).

Then hopefully I’ll probably be back to the runtime code.

Seeya tomorrow.

Disclaimer: This DevLog is from the perspective of one developer. So it doesn’t reflect everything going on with the team

TaleSpire Dev Log 481

2025-09-02 17:27:31 +0000

Howdy all,

Today, I’ve been back working on our GPU particle system, which will eventually be used for our weather effects.

Our artists will need to be able to script the particles’ behavior, so we’ve gone down the very tried-and-true route of having them make these scripts via a node graph.

WIP version of the node graph. Not final

A while back I wrote a good chunk of the compiler and, although I’ve got more to add, it’s already producing decent compute shaders. Since then we’ve been working on making the user exerience for the artists nicer.

The current task I have for this is adding support for allowing the artists to make their own nodes (essentially functions), which themselves are defined as node graphs.

Hopefully, this’ll only take a few days. After that, I think I’ll be back on dice. We’ll see how it goes.

Until next time folks.

Disclaimer: This DevLog is from the perspective of one developer. So it doesn’t reflect everything going on with the team

TaleSpire Dev Log 480

2025-09-01 19:44:49 +0000

A quick one today.

I put in some basic code for handling language in fuzzy name search. I’m 80% sure I’m going to have to tweak how it works when we work out the UX, so I’m not stressing about it being perfect right now.

After that, I did a little work on the Discord and got set up to work on particles again. Next up, I want to add support for user-defined functions.

Back soon with another dev-log.

Disclaimer: This DevLog is from the perspective of one developer. So it doesn’t reflect everything going on with the team

TaleSpire Dev Log 479

2025-08-29 18:53:17 +0000

Heya folks.

Today I’ve continued working on tags. The big remaining task on my todo list is adding language support to the fuzzy name search. So, of course, I distracted myself working on search performance.

First off, a quick overview. In TaleSpire today, you can search for creatures using tags. In an upcoming version, you’ll be able to search not only by tag but also by the creature’s name. We also intend to make search results update live as you type, rather than having to hit return before it starts the search.

The code to do this is fairly straightforward. We take the text you typed in the search field and loop over all the creatures names computing a score which indicates roughly how different your text is from the name we are checking. If the score is low enough we include the creature in the result.

The score is a not based on real research, it’s mostly a couple of levenshtein distances with some tweaks that got us good results back when I wrote the search last time. For now I’m sticking with this approach so I just wanted to make it faster.

I first wrote the search as a Burst compiled job. Along with some common sense tweaks to avoid lots of allocations, the time to search for a tile (fuzzily comparing against the name of every tile) was ~3ms [0].

This seemed slow, so I turned to the Levenshtein distance function, where the meat of the processing is happening.

The implementation was very nieve, it filled out the entire table of scores before extracting the result (see the linked article above for pictures of these tables). A very simple optimization comes from looking at how the table is filled and realizing that you only ever need two rows in memory, the current one and the previous one. For a long asset name of 50 characters that means only needing 100 elements rather than 2500.

Next up, I decided to cap the portion of the name we would compare to 254 characters. This mean that the highest number ever stored in the table was 255, so we could use a byte. This means 1/4 of the entire row can fit in one cache line. It also means that we only need 512 bytes of data for the two rows.

Lastly, I looked at the fact that I computed two scores. One comparing the search term to the whole name[1], and one comparing the search term to a subset of the name. You might notice that this is duplicate work, so we extract the score for the substring partway through computing the score for the whole name.

These simple changes, which as usual amount to “not doing the dumb thing”, make a big difference. The time for searching all the tiles went from 3ms, to 0.5ms, and searching all the creatures takes 0.05ms.

There is definitely more we can do, but this plenty good enough for a first version.

On Monday I’ll get back to what I was meant to be doing and add the language support :P

Hope you have a great weekend,

Ciao.

Disclaimer: This DevLog is from the perspective of one developer. So it doesn’t reflect everything going on with the team

[0] This is a very informal dev-log. We aren’t aiming to be a robust education resource here, and so the timings are adhoc, and only from my specific pc. I’m including them mainly so we can get a feel for the speedup from the changes.

[1] Actually, I split the names into chunks at specific characters, but that doesn’t affect the implementation of this bit.

TaleSpire Dev Log 478

2025-08-28 10:41:00 +0000

Hi folks,

Yesterday, I wrote the code that performs fuzzy search over the names of assets.

I’m now taking another quick look at tag search, as I need to be able to filter the tags by what kind of asset is currently of interest (e.g. creatures, tiles, or props).

This should be straightforward, and so by the end of today, I hope to have the behind-the-scenes of the tag search finished.

However. I do need to spend some time considering how language plays into search. For example:

  • How do we handle translations of the asset’s name?
  • When we do, what do we search for? If the name isn’t available in your language, which language/s do we fall back to?

This will be fine. I just need a good mug of coffee and a chat with @Chairmander, and we’ll work it out.

That’s all for now. Hope you have a great day.

Ciao

Disclaimer: This DevLog is from the perspective of one developer. So it doesn’t reflect everything going on with the team

TaleSpire Dev Log 475

2025-05-27 19:52:50 +0000

Howdy all,

Lot’s in flight right now.

Chairmander has been working on the tags and part of that has been upgrading the creature format to support those. Yesterday I helped a little by updating the pack loading code in TaleSpire to work with the latest version of the format. I got to spend a little time helping get the vision limit feature closer to merging, and testing some backend fixes which will (when complete) allow some more features to progress.

However the main thing I’ve been spending my time on the last couple of days has been the particle system. Like many other particle systems the behaviour is scripted via a noodle graph[0]. We’ve had issues in the past with libraries for making these graphs so over a year ago, Ree made one for us. I’ve finally been able to get stuck in and it’s been ace.

I’ve just finished making the serialization code and hooking it into Unity’s save prompting system.

Next up I’ll be working out how I want the type and error checking to work, and then I’ll sketch out the basics of the compiler. From there I can hand all this over to Alex so he can add it to his work on the particle system.

If all goes well I should be back on the dice networking rewrite late next week. Early in the week I may be involved in a little hackaton, but I’m not sure what on yet.

All fun stuff, looking forward to telling you more.

Peace

Disclaimer: This DevLog is from the perspective of one developer. So it doesn’t reflect everything going on with the team

[0] Or node graph, whichever you prefer

TaleSpire Dev Log 474

2025-05-21 20:04:51 +0000

Heya folks.

Here’s a smattering of stuff I’ve been up to recently.

I’m getting ready to take this fix to slab placement out of Beta. It’s had good testing from folks in the community, so I’m happy we’ll finally be shipping it. I’ve got the build on our pre-production branch, and I’ll do the final release testing tomorrow.

I’ve been helping out a bit with the WIP particle system. My role is writing the spec, stubbing out the API, and then setting Alex loose on it! Things are taking shape well there. Alex has been refactoring his particle experiments into more reusable code. He’s also been researching what core operations are needed for us to build the rest of the standard library. We are slowly cornering the design, and it’s a lot of fun.

Yesterday afternoon, however, I simply couldn’t get my brain to focus on particles, so I read about the network sync of physics objects. This meant I was in the perfect place to start a VERY overdue task: rewriting how our dice are synchronized.

The code that manages the dice has been around since before TaleSpire was called TaleSpire, and has been frankensteined over the years as we have added more features on top of it. Due to this, it has some very long-standing bugs. It is way past time it got some love. Until now, every die was its own synchronized entity in Photon, so it was often tricky to treat them as a group. In the new version, the “roll” is the synchronized object, and we handle the data packing ourselves. The result should be greater stability and hopefully less traffic used.

Until now, we have limited the number of dice in a single roll to 40. There have, however, been mods that hack around this. In the new version, the protocol will have a fixed limit of 64 dice per roll[0]. It will not be possible to change this without replacing the sync code.

You can still have many hundreds of dice on the board, but each roll will have that hard limit. This limit also won’t affect multi-part rolls (which will come with the improved dice macro system later).

We are aware that it’s possible, in games like 40K, to have some utterly mad rolls, but we think we can tackle mega rolls as their own feature in the future when it becomes an issue.

We do not foresee this being an issue for general play, but we didn’t want it to seem like we were sneaking this change past you. So now you know!

I’ll definitely write more about this as it gets closer to shipping. With the roll code rewrite, it’s going to be even easier to add the dice automation later this year.

That’s all from me today.

Disclaimer: This DevLog is from the perspective of one developer. It doesn’t reflect everything going on with the team

[0] The UI may limit to less (e.g. 60) as a round number and will feel more natural to most folks.

TaleSpire Dev Log 474

2025-05-14 09:54:31 +0000

Morning all,

Amongst the vision limiting and bug fixes, I’ve been working on a feature that lets you store dice rolls in your inventory.

dice in inventory

The visuals are all 100% work in progress, but it feels good to get something working on this. The feature has been on my mind for a long time.

This feature is one that starts small, but as we make this behavior more universal, it will become more important. Early on the list is being able to drag things to chat messages to send them to other players, and to be able to drop them into symbiotes so others can build upon it. In time this also will include per-creature inventories and gm-containers (chests maybe) that have inventories that can store goodies.

This has been on my wishlist for a long time, so I’m glad to see some movement. It’s also got me working on the dice rewrite again, which has been parked for ages (for dumb reasons I’ll go into another day :/)

Peace.

Disclaimer: This DevLog is from the perspective of one developer. So it doesn’t reflect everything going on with the team

Mastodon