From the Burrow
TaleSpire Dev Log 200
Heya folks,
On Thursday, I continued work on the batching code. I got a first approximation written[0], but upon trying to hook it into the existing setup, I noticed that disabling the current system is not trivial. In fact, I had a choice between working a bunch for a test that wouldn’t teach me much[1] or just plowing into the real work of replacing the current system. I chose the latter.
This means that the goal I set for myself of “something rendering by the weekend” was not feasible, and I shouldn’t push myself unnecessarily. The task of replacing the system touches a lot of code and requires a different mental approach.
So instead of fretting Friday, I decided I’d take it off and just work Saturday instead. One of the blessings of working for yourself :)
Because of that, I have no news for today. I also expect that the updates from me for the next week will be variations of “Replacing part X of the old tile system”. However I will try to keep the posts coming in case anything interesting crops up.
Until then, Bye!
[0] Approximation as it just positions all the parts of the tile at the tile’s origin. So it’ll be a mess but will show if things are working. I did this as the math requires a focus to make sure I don’t screw it up and should be taken slowly.
[1] I have already made experiments to learn how the BatchRendererGroup behaves, and the process of writing the batching code had given me a good deal of the context I had hoped to get from the exercise.
TaleSpire Dev Log 199
It’s the summer holidays over here, so we’ll see a little less of Ree this week as he takes some well-earned breaks. However, you still have to put up with me :)
Today I’ve been looking at writing the batching for the rendering as we move away from Unity’s GameObjects. It’s slow going, but I should have something running before the weekend. This version won’t have GPU-culling, but it will let me progress on the rest of the systems that need rewriting. Once this is working, Ree and I can work out the bare essentials we need for the animation system the tiles will use.
I also had another brief look into Unity’s new physics engine, and I’m reasonably confident we’ll be able to drive that efficiently. More on that another time.
Back tomorrow with more very incremental news :)
Seeya
TaleSpire Dev Log 198
Just signing off for the night, so not gonna write much.
I got the server patch tested and deployed. It will have no effect on the current TaleSpire release, but the next patch will start using it.
Right. Sleep is in order. Bye!
TaleSpire Dev Log 197
Hey folks, I hope your week has started well.
Ree has been busy taking care of business and working on rulers, and I’ve turned my attention to the backend.
I really want to get TS streaming zones rather than downloading the whole board, but before I do that, I want to look into any issues in the current system.
First orders of business are finishing the changes to session management and removing a bunch of old code. We have had quite a few updates to the server code since launch, and the old code has a mental cost when working on the system.
Most of this is relatively straightforward. However, it requires a lot of care and double-checking to make sure the updates never interrupt service.
I’ll probably push the server update tomorrow with is the safest part (adding new code). I can then update TaleSpire to use these new entry-points, and then soon we’ll be in a good position to remove the old ones.
Until next time.
Peace.
TaleSpire Dev Log 196
Today we got another patch out, which felt good. Since then, work has continued of visuals for the rulers, and I’ve made a couple of tweaks I can show.
First, creatures have their own panel now. A little while back, we made placing creatures not transition to building mode, and this continues on that path of changes we want to the building experience.
I’ve also patched the backend and thrown in test UI for units. This will let you set the default units for the campaign. In time we will likely add ways to add multiple units (for larger distances), and we’ve also thought about per board settings so your overworld could be measured in a more appropriate scale. That is all still up in the air, though, and the UI is just so we can make progress with the rulers.
That’s all for now.
Peace.
TaleSpire Dev Log 195
Hi all. Work has gone well today.
Ree’s been working across a few tasks include starting on the proper ruler UX.
I spent the first half the day working through the list of feature requests categorizing them. I’m hoping to put out a more organized list by the end of play tomorrow so that you can have a peek at it before the Dev Stream this Friday.
That work is super tedious, though, so I took a break and added support for customizing the names of the four stats used by all creatures. It looks like this now:
This hasn’t yet been merged into master, but the backend has already been patched to support it. While I was doing that, I added the flag that indicates flying to all creatures. So we can now persist this info once we ship that feature.
That’s the lot for today.
Seeya next time
TaleSpire Dev Log 194
WARNING: The visuals for, and even the kinds of, rulers in this log are 100% temporary. The point is to work out a possible structure for the code and network sync. Drawing any data or conclusions from the clips presented in this update is meaningless.
Heya folks, today Ree has been prototyping props, and I’m going to ramble below about what I’ve been noodling with.
After seeing a conversation in the discord about area-of-effect, I got a strong desire to hack on rulers again. My goal was to make a prototype of one possible mechanism which could give us fairly a simple way to define rulers.
I wanted the ability to support simple point-to-point or volume rulers, but also ones with some additional adjustable parameter (like a cone area-of-effect)
The approach is as follows:
- A ruler is a container which holds some different visuals for rulers (which I’ll call presentations in this update)
- The ruler is a simple state machine with four states
- Placing the first point
- Placing the second point
- Adjusting the ‘parameter’ (optional step)
- Done
- The ruler might be visible to other players. In which case it handles the sync
- A presentation does not have to support a parameter
- Presentations can be cycled at any point before the ‘Done’ state
The ‘parameter’ is one part that might seem a bit vague right now. We should talk about it, but first, have a peek at this clip.
Unlike the sphere and line rulers, the circle area-of-effect presentation had an additional step after placing the center and defining the radius. It allowed the user to show a slice of the circle. To make this, I needed the third point to be on a plane defined by the first and second points. From the volume selection tool, I had already seen that it was handy to define a plane to raycast against, so I decided to add that to the parameter. The optional parameter is either a point on the board (just like the first two), or it can define a plane to constrain the point. Simple stuff but might allow some useful tools.
So this prototype is done we can kick the tires and see if it’s in the right ballpark. It’s totally fine if we throw it all away, or gut it and do something similar. The main thing is that it’s something tactile in-game that we can play around with.
With this itch scratched, I’ve jumped branch to look at the session/chat panel prototype again.
That’s all for now. Seeya
p.s. Here is a little clip showing sync working between two copies of TaleSpire.
TaleSpire Dev Log 193
Hi folks.
I’ve been poking a little at the occlusion culling, so I thought I’d show something I found handy.
We are not moving to Unity’s scriptable rendering pipeline yet. This means much of the work I’m doing right now is finding out how we should hook into Unity’s traditional rendering stack.
I really like BatchRendererGroup as it lets us set up batches and not have to update them per frame[0]. We can then map the batch-id to a specific zone and kind of asset. This now means that any active camera (or one that is told to render) will render the things we have submitted in those batches.
We really want to use lower-poly meshes for the shadows and occlusion-culling, so what we should put in those batches is actually the low poly-meshes (which we are going to call occlusion-meshes from now on). However, we don’t want to render the mesh itself to the final scene, we just want it to cast shadows in the main view and populate a depth buffer for us to use later.
Now those used to Unity might think of layers. You can tag objects with a specific layer and then tell a camera to only render particular layers. The issue with this is that if you filter out an object, you also can’t see it’s shadows, so that won’t do. Next, we could see that when adding batches to the BatchRendererGroup we can set the ShadowCastingMode
to ShadowsOnly
. Awesome, now we only get shadows in the main view… however, we then don’t get any depth information in the depth buffer. Damn. What ended up working was the following:
- Make a shader with only a
ShadowCaster
pass [1]. - Make a material using this, and use that in
AddBatch
. - Render the scene from the same orientation using a camera with a replacement shader and with a depth RenderTexture as the target.
What’s nice about this is that lights will now use our occlusion-meshes, but those meshes won’t show up in the final render.
With the depth buffer available, we now generate the depth-chain, as mentioned in a previous dev-log. We then have everything we need to get into the meat bit of the occlusion culling. Once we know what to draw, we will use DrawMeshInstancedIndirect to submit the high-poly meshes for rendering. At this point, we make sure to set receiveShadows
to false and the ShadowCastingMode
to Off
. This lets us receive the shadows we computed earlier without asking Unity to compute more from these more detailed meshes.
Right now, all the tests I’m doing are just with randomly placed spheres, so screenshots are a little meaningless, however, once we get into the using real assets, I’ll start showing more.
Next, I need to work out a little mistake I’ve created in the depth-chain, refactor the tests to be a little easier to handle, and then get into the culling compute shader. Once I have this first test working, I’ll need to do a lot of planning to work out how we want to handle the data in the TaleSpire. The goal is to find a balance where we do as little per-frame work and as small per-frame GPU uploads as possible.
Until next time, Peace.
[0] and handle culling ourselves which is handy too [1] here is the shader we used in our recent tests
// Very minimal
Shader "OccluderShadowCaster"
{
SubShader
{
Pass
{
Tags {"LightMode"="ShadowCaster"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#pragma multi_compile_instancing
#include "UnityCG.cginc"
struct appdata
{
UNITY_VERTEX_INPUT_INSTANCE_ID
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
V2F_SHADOW_CASTER;
};
v2f vert(appdata v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
return o;
}
float4 frag(v2f i) : SV_Target
{
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
}
}
TaleSpire Dev Log 192
A small ‘still working’ update for the last couple of days. Ree has continued with terrain experiments and business work. I’ve been playing around with Unity’s BatchRendererGroup
type to learn what we have in our toolbox as we start to rewrite how we handle the rendering of tiles and props.
More coming soon.
Ciao
TaleSpire Dev Log 191
Hi folks.
Today, some of the things Ree and I have been working on don’t make for great writeups. He was on business tasks, which included working on our GDPR documentation, and I was finishing a feature we’ll be shipping in a few days if all goes well.
I’m not ready to say what it is as, although it’s tiny, we want to ship it alongside an upcoming asset update. You’ll just have to wait :p
After I finished off that feature, I started work on the in-game chat system. For messages to players within the same board, it’s easiest to use the RPC calls of the networking library we use. However, for campaign-wide messages, we will use our server to relay the message to all connections which are subscribed to that campaign. This is likely to get changed up depending on what we can do with WebRTC down the line.
I wrote the code to handle this on the backend, and while I was at it, I added some code to handle the upcoming bookmarks feature.
With that done, I started mocking up the UI for the chat panel. I’m no designer, so please excuse the ugliness, but a rough shape is forming at least.
The little boxes underneath the message text box are attachment slots. I think we will allow you to drop references to creatures, locations in the board, dice rolls, and other stuff and send them along with your message.
By the time this is ready, it will replace the session history, the messages you had there will now be in this log, which will support tag-based filtering.
You will be able to target your messages at any of the following:
- Everyone in the board
- Everyone in the campaign
- Everyone in a specific party
- A specific player
My current thinking is that you’ll usually use the drop-down to pick the target of the message, but if your message starts with @<someone>
, it will as if you switched the target to that player, sent your message, and switch the target back. This is handy in cases when you need to send something very quickly, like if you are co-ordinating a mutiny with another player.
In time we also will want to support language proficiency in the chat. This would mean you can read messages that arrive in languages your creature understands (e.g. elvish), but the text will be garbled if it doesn’t support that. Obviously, this needs more information to be attached to each creature, so this is more likely to happen closer to when we add rule-system support. It doesn’t feel like something that should be prioritized over other features, though.
Time to call it a night.
Seeya!