Daggerfall Unity 0.13 Rendering Update – Part 3

In this third and final instalment, Daggerfall Unity’s rendering review wraps up by fixing more bugs and giving Retro Mode some overdue love. Preview release 0.13.3 is now available on Releases page.

To quickly recap, this review set out to resolve problem of specular “shine” from Unity’s default Standard shader, switch to more accurate and flexible linear lighting space, and upgrade postprocessing stack to PPv2. Along the way, we fixed many small problems with loose texture mods and reviewed lighting. Almost every part of the game involved with drawing something to screen was inspected and tuned up if tuning was needed.

Thanks to community feedback, we were able to address several issues created by initial 0.13 preview release. Our new shaders were extended to support more PBR capabilities. The game received an extensible “Effect Settings” UI to configure postprocessing and other effects at runtime. We helped several mod authors overcome compatibility issues so their mod works with 0.13 and beyond.

With all the large changes now settling down, we could start refining a few things. Here’s what’s new in 0.13.3.

Remove Nature Shadows

Projecting shadows from 2D billboards comes with downsides. These are just 2D cutouts rotating to face camera, so their shadow either twists and turns with billboard or stays fixed in place. Fixed shadows look better overall, but results in any asymmetry becoming disconnected from cutout when seen from the wrong angle.

Nature shadows had other tradeoffs too. In deferred rendering, screen objects always receive shadows, which means trees received self-shadow artifacts while rotating. To workaround this problem, it was necessary to render nature objects in transparent queue which doesn’t write to depth buffer. This in turn created other problems with rendering elements relying on depth information.

After trialling more solutions and workarounds, it became obvious these shadows were causing too many issues for a minor aesthetic hack that only looked good some of the time. Considering classic didn’t have tree shadows either, the best solution was to simply remove them.

If you prefer these nature shadows despite their limitations, you can switch them back on by opening settings.ini and changing “NatureBillboardShadows=False” into True.

Please keep in mind that enabling nature shadows will revert them to transparent rendering queue, so trees and other nature billboards will not operate fully with effects requiring depth information – Ambient Occlusion, Retro Mode Postprocess, ColorBoost, to name a few.

Retro Mode Enhancements

Retro Mode is a feature in Daggerfall Unity where camera renders to a 320×200 or 640×400 resolution target before scaling output into your display area. The feature also comes with postprocess settings for palettization or posterization to crush palette down to fewer colours with neat side-effects like colour banding from nearby light sources.

From 0.13.3, Retro Mode is now in the Game Effects UI. You can access these settings from drop-down arrow at top-left of screen when game is on pause menu.

In addition to previous settings for retro mode and postprocess, you now have the option to adjust render scale into 4:3 or 16:10. Enabling either of these settings will scale output to selected aspect ratio inside your actual screen area. If you have a wider screen, e.g. 16:9, then vertical pillarbox bars are added.

Previously this aspect correction was only available as a hacky workaround by fiddling with resolution and UI scaling settings, which was error prone and didn’t work under all platforms. Now with this in Game Effects UI, you can switch around these settings at runtime without restarting game.

If you’re coming from an older version of Daggerfall Unity and have already setup Retro Mode based on the old hacky method, please reset your game resolution back to something with correct aspect ratio for your monitor. For example, if you have a 1920×1080 monitor and set your game resolution to 1280×960 to force the aspect change, please set your game resolution back to 1920×1080 or some other 16:9 resolution. You also no longer need to enable “FreeScaling” option, which has been removed from 0.13.3. This is now all handled automatically in-game from checkboxes shown above, along with fixes for problems created by the old FreeScaling option.

One final note about Retro Mode – now that you can switch settings at runtime and change aspect ratio, not all mods will support runtime switching of resolution or aspect. Any mods rendering to a stacked camera (e.g. Enhanced Sky, Distant Terrain) will need added support for runtime resolution switching (update: Enhanced Sky has this support from v3.0.2). Also custom UI mods might need to add aspect handling based on how they calculate screen position. If you have problems with a mod in Retro Mode, try restarting game, switching off aspect correction, or switching off Retro Mode entirely.

ColorBoost Effect

The best way to introduce ColorBoost is by talking about darkness in dungeons. Daggerfall dungeons aren’t dark, exactly. They’re actually quite bright near player then ramp down sharply into darkness after 30 metres or so. This is technically a requirement of lower draw distance in classic, but it creates a uniquely claustrophobic feeling. In classic, even light sources fade into darkness at range. To put it another way, there’s a high contrast between brightness levels depending on distance from player.

See below classic screenshots for example. Here our player is standing near throne lift in Privateer’s Hold. Note how environment around player is rather bright then ramps down into blackness at farthest point.

If you walk down toward that farthest point and turn around, now the brightly lit area near throne is plunged into darkness and world near player is bright instead. Step back a few more metres and area above stairs becomes totally black. Even those bright torches will fade away.

Daggerfall Unity uses a modern naturalistic lighting system where this kind of thing doesn’t happen. Lights have radius and intensity, and geometry is either touched by some amount light or not. In a naturalistic environment, torches don’t stop casting light behind themselves just because player walked a few dozen metres away.

It’s not quite feasible to capture classic’s rendering and lighting perfectly here (totally different engines and lighting systems after all) but it is possible to create more contrast between near and far brightness to capture this same atmosphere.

Let’s start with a screenshot of Daggerfall Unity, once again at top of stairs in Privateer’s Hold looking down. Note how distant torches still affect the wall behind them, and scene overall is rather uniform in brightness. A ramp down into darkness isn’t present at all.

Now ColorBoost comes into play. This postprocessing effect can both increase brightness near player and produce ramp down into darkness inside dungeons. Compare above screen with one below, and note difference in contrast between near and far points. Even the torches start to fade into darkness at range.

In addition to atmosphere, this gives you another way to tune brightness to your preference. Some ColorBoost will brighten things up without completely flattening or over-brightening whole scene. The dungeon falloff effect has adjustable strength down to 0 (disabled).

Here’s a another shot of stairs in Daggerfall Unity at 320×200 16:10 Retro Mode with adjusted ColorBoost settings. This is finally approaching reasonable parity with classic Daggerfall’s dungeon atmosphere despite underlying engine differences.

ColorBoost was originally intended to help in Retro Mode with posterization / palettization enabled, and it’s recommend to use a good amount of ColorBoost in combination with those effects. But you can enable ColorBoost at any time, with or without Retro Mode, and it will work alongside your mods, lighting setup, and other settings.

Speaking of mods and settings, you’ll likely need to dial-in ColorBoost to suit your environment and preferences. Everyone can have a unique setup and world can light very differently as a result. For this reason, ColorBoost config page has several sliders to help dial-in Radius of effect, global Intensity, strength of effect in Dungeons, Exteriors, Interiors, and control Dungeon Falloff. Like all effects, ColorBoost is disabled by default.

General Improvements & Fixes

This release also brings several minor fixes and refinements:

  • Don’t use transparent queue for standalone cutout billboards so they operate with AO and other depth effects
  • Fix volume collider blocking spells and other missiles (fixed in 0.13.2b)
  • Flag window textures in archives 171-173 to support emissive from replacements
  • Allow changing retro mode settings at runtime
  • Remove global UI FreeScaling method, this is now part of retro mode aspect correction
  • Fix overlapping text in popup message boxes with FreeScaling enabled
  • Change protections on MaterialReader Uniforms to public
  • Fix StreamingWorld.TrackLooseObject “mapPixelX” and “mapPixelY” (KABoissonneault)
  • Fix retro mode colour accuracy with higher precision render textures
  • Hide spell icons when pause options dropdown is open
  • Refine automap panel sizing with custom screen rect

Conclusion

We have now reached the end of rendering review in 0.13. Unless a blocking issue is found, the “preview” tag will be dropped from next release. Moving forward, there are no more large changes scheduled to engine or rendering, only bug fixes and minor refinements. This is to ensure best possible stability and mod compatibility moving towards 1.0.

If you are a mod author, please ensure your mod is rebuilt and tested compatible for 0.13.3. This release is very close to next full Beta release without “preview” tag.

Thank you for reading, and for playing Daggerfall Unity!

Daggerfall Unity 0.13 Rendering Update – Part 2

Our rendering update and review continues with 0.13.2 now available on Releases page. This release fixes bugs, expands capabilities of new shaders, and helps mods reach compatibility with 0.13. Let’s unpack everything new in this release.

Expanded Default Shaders

0.13 introduced new default shaders, the small programs which tell your GPU how to render objects and materials. These new shaders better reproduce classic’s colours and flat albedo look without all the unwanted specular shine that comes with Unity’s Standard shader, but did not support a PBR workflow by design. While this was suitable for classic textures, and mod authors could still use custom PBR materials in their .dfmod, any loose texture mods had less support than before.

From 0.13.2, default shaders now support albedo+normal+parallax+metallic maps, allowing loose texture mods to have an optional PBR workflow just by dropping the right textures into a folder. We also fixed several problems loading these optional maps in asset pipeline and extended this PBR support to terrain tilemap shader.

A good example of this kind of mod is Vanilla Normal Mapped which adds normal+parallax+metallic maps to complement classic colour textures. Screenshots below compare standard DFU textures and boosted by Vanilla Normal Mapped mod in 0.13.2.

Before Image After Image

Before Image After Image

These new capabilities in default shaders allow mods to intentionally reintroduce specular based on their materials, while still avoiding unwanted specular when using classic textures only. The big advantage of rolling our own shaders is more control over the rendering process.

Dungeon Water

Without proper alpha blending at the time, DOS Daggerfall used a stippling effect for water surface (a kind of black pixely noise) and a bright blue fog effect when submerged.

Daggerfall Unity improves water surface with a dark water plane and slime highlights, invoking murky and stagnant water suitable for dungeons. But when you submerge, we used the same bright blue fog effect underwater. After listening to feedback, we’ve changed the submerged effect to use a dark blue-green slime colour to better match water surface.

Before Image After Image

In case you want something different, we’ve also exposed the underwater fog to modders. See this topic for details on how to set underwater fog colour/density and some tips on updating surface plane as well.

Shout-out to King of Worms for his persistence around tweaking dungeon water and driving this change.

Increased Torch Brightness

On the subject of feedback, we heard several times the brightness of default and item-based torch were retuned improperly and looked too dark. We’ve now increased brightness of both default and item-based torch, and decoupled how these are handled so they can be tuned independently in future. Screenshot below compares local torch brightness when using a lantern with item-based torch in 0.13.0 vs. 0.13.2. You’ll note that 0.13.2 is brighter and more comparable to lantern in 0.12.

Before Image After Image

In addition to torch brightness, we also heard that retro rendering mode is too dark and tends to crush colours towards black. This kicked off a review into better matching classic’s brightness, particularly in retro mode rendering. During this review, we noted classic dungeons are very bright near player then ramp down to near black based on distance from camera. Because Daggerfall Unity’s retro mode uses naturalistic lighting and selects palette colours in a post-process, it does not properly capture this effect.

The solution was to introduce a new effect called ColorBoost to default shaders which juices up colours local to player and ramps down over a short distance. This better matches brightness contrast seen in classic, and will help players tune dungeons and nights to properly select brighter colours in retro mode local to player. ColorBoost is not a lighting effect, rather it scales albedo near camera so that brighter colours will be selected in post-process. ColorBoost will be available from 0.13.3 with or without retro mode enabled, but its primary purpose will be to select better colours in retro mode. You can see a preview of it in this tweet.

Terrain Mod Compatibility

We’ve worked with authors of popular terrain mods to help overcome compatibility problems and get their mods working in 0.13. This required updates to both mods and core. We’re pleased to announce that Enhanced Sky, Distant Terrain, and Eroded and Enhanced Terrain are now compatible with 0.13.2+. Mod authors should have compatible mods released soon now 0.13.2 is available.

General Improvements & Fixes

We’ve made several minor performance improvements and fixes under the hood. To summarise these quickly:

  • Retro-sized textures are no longer compressed automatically, as this destroyed appearance of small-sized texture replacements. The threshold for retro-sized textures is < 256 pixels wide and high. (Interkarma/TheLacus)
  • Fixed internal crash when loading compressed normal maps.
  • Fixed loading non-colour maps as linear.
  • Refactored loose texture asset loading to fix some minor bugs and clean up code.
  • Fixed errors in terrain tilemap shader and cleaned up shader code.
  • Fixed excess draw calls when rotating interior automap, a large performance improvement to automap (spotted by King of Worms).
  • Fix out-of-range error in FormulaHelper.CalculateCastingCost (KABoissonneault)

Effect Settings / Post Processing Tuning

There’s a new in-game UI under the pause menu chevron called Effect Settings.

This UI allows you to customise post processing effects while game is running. As Daggerfall Unity now embeds PostProcessing v2 (PPv2) stack, the mod which previously customized these settings is no longer compatible. Rather than update mod, we’ve integrated these settings straight into the core game!

All post processing effects are disabled by default. Once you access the above menu, you’ll be able to enable and tune Antialiasing, Ambient Occlusion, Bloom, Motion Blur, Vignette, Depth of Field, and toggle Dither while seeing your changes at runtime. Screenshots below of first three settings pages.

These settings have been expanded to include new settings available in PPv2 that were not available in older releases.

The Effect Settings window is also expandable, so mods can introduce new post processing or other effects, then plug their config page into this UI. This will be where ColorBoost is homed once that feature goes live in 0.13.3.

Post processing is very much a matter of personal taste and you should be able to dial in an effect to your liking. You might use these effects in your game or just to take screenshots. With effects like Vignette and Depth of Field, you can create more stylized screenshots like below.

The choice is yours how you want to use these effects. You can leave them disabled, enhance game by degrees, or pile on a bit of everything for photography purposes.

Conclusion

With all the tweaks and fixes in this release, along with increasing mod compatibility, Daggerfall Unity 0.13 is almost ready to lose the Preview tag and go back to stable beta releases.

As of now, 0.13.2 represents a close-to-final state for rendering in Daggerfall Unity. All the challenging and breaking changes are now behind us. Modders can release compatibility updates for 0.13.2+ and be confident their mods will remain compatible with 1.0 as no further rendering changes are scheduled.

Looking at a timeframe for 1.0, this will now most likely be early 2022. End of year is fast approaching and we still have lots to do. Once rendering is closed out, we’ll move on to Localization improvements and general bugfix. We’ll call 1.0 when happy with overall state and stability of game.

Thank you for reading, and for playing Daggerfall Unity!

Daggerfall Unity 0.13 Rendering Update

There are some long-standing items on Daggerfall Unity’s Roadmap that have at last found their way into the game. These changes relate to visual rendering of classic textures in Unity engine and how they interact with lighting. There’s also a long-overdue update to the postprocessing stack. To summarise everything before getting into details, these changes are:

  • New default shaders for classic textures
  • Switch rendering from Gamma to Linear colour space
  • Lighting review
  • Update postprocessing stack

New Default Shaders

You might have noticed the visuals in DFU have a kind of silvery “shine” on top, and some textures tend to wash out easily under certain lighting conditions. Examples are objects that emit light, such as lanterns, and naturally bright textures like snowy terrain at midday. Even when using retro rendering with palletization, deep blacks will tend to shift value towards lighter greys.

The reason for this is somewhat technical. A concise version is that modern engines like Unity use something called Physically Based Rendering (PBR) which attempts to simulate the physical properties of a material and how it interacts with light. However, old games like Daggerfall predate physical material properties such as normal maps, smoothness maps, etc. and instead have only basic colour information in a single texture. When attempting to render these simple textures in a PBR engine without any other material properties, they are perfectly smooth and will reflect light in unsatisfying ways. This can give objects a shiny kind of look, as if made from plastic or dull metal.

In fixing this, the goal was to correct lighting incongruity while using classic textures and still allow mods like DREAM to use PBR materials. It was also necessary for these different materials to work together in the same scene with any combination of classic and modded materials. This presented some challenges that were eventually overcome with the help of new shaders and several updates to material pipeline.

The best way to see the difference is to compare a scene in 0.12 and 0.13. Pay close attention to the dark areas of the rat while adjusting slider. You’ll notice in 0.12 screenshot the rat has a uniform specular shine that is removed in 0.13. You’ll see the same across the entire scene, although most obvious in darker textures.

Before Image After Image

To fix this specular shine required new shaders better suited to Daggerfall’s classic textures. These new shaders lean fully into the retro textures and use simple Lambertian reflectance like older games of the time. This leads to better colour sampling under most lighting conditions and fixes brighter areas from becoming overbright. For example, the lantern and Fire Daedra wash out to bright yellows in 0.12 using PBR shaders but show their true colours in 0.13.

Before Image After Image
Before Image After Image

While relatively basic, the new shaders still support Normal maps and Emission maps, and conditional compilation. They are more lightweight than Unity’s Standard shader and will perform slightly better on lower-end computers running without mods.

Gamma to Linear Colour Space

The next change was switching from Gamma to Linear colour space. This is another technical subject, but in short it relates to how colours are added and multiplied. Linear colour space leads to more accurate results with improved lighting falloff and softer shadows. The results can be subtle in unmodded DFU, but the combination of new materials and linear lighting uplifts every scene with deeper colours and improved contrast while eliminating bloom and flat specular shine.

Before Image After Image
Before Image After Image
Before Image After Image

With the change to Linear colour space, modded materials now have a chance to look their best at all times with more accurate colours and no unwanted bright spots near lights. Of course, all these changes also require lighting to be reviewed and materials tweaked so they still look good. This leads into the next item on the list.

Lighting Review

Linear colour space blends and lights differently than Gamma. Lights appear to have a larger radius and is more defined on edges. This is more accurate overall, but also different if you’ve become accustomed to Gamma lighting. As a result, all the light sources in the game need to be tuned so they aren’t too bright and still resemble the game as it was.

In general, dungeons will appear a bit darker from 0.13. The combination of new shaders, Linear colour space, and lighting review result in darker colours becoming more prominent. You can really see the flat silvery shine over everything in below screenshot when comparing 0.12 to 0.13. The dark parts of brick textures stay dark rather than shifting value towards lighter greys.

Before Image After Image

Towns are still nicely lit oases, with Linear’s different light falloff visible against sides of buildings in below screenshot. But the removal of flat specular shine means night-time scenes have better overall contrast between light and dark areas.

Before Image After Image

Daytime scenes will light much the same as there’s only a single directional light source (the sun). The change to Linear with new shaders also resolves the problem of terrain textures looking over-bright under a midday sun. Finally, the daytime light curve was adjusted to provide a longer plateau of sunlight around 10am-3pm.

Before Image After Image

Update Postprocessing Stack

For some years now, Daggerfall Unity has continued to use an older embedded postprocessing stack. This has now been removed and replaced with current Post Processing 3.1.1 via Unity’s package manager. This updates deferred fog and postprocess capabilities to be in line with current engine. It also required some minor code changes and retuning fog as some parts of the old Post Processing library have been deprecated.

Fog is roughly the same, other than being a bit thicker towards limits of view distance. Compare the distant trees and buildings in below winter scene.

Before Image After Image

Preview Release and Mods

Daggerfall Unity 0.13 will be available as a Preview release soon. Due to all the changes across asset pipeline, colour space, default materials, and postprocess stack, you should expect some mods that work under 0.12 not to work in 0.13. Mods that include new materials and shaders will be most affected. Any non-graphical mods, or those which only change game settings, should be unaffected or only need minor tuning.

It could take several weeks for mod authors to update their mods to be compatible. If you don’t want to help test 0.13 and provide feedback to developers and modders, you can happily stay on 0.12 until 0.13 release is out of preview. You can also run 0.12 and 0.13 side-by-side by unzipping releases to different folders and running different mod loadouts. Other than changes outlined above, the 0.13 release is identical in terms of gameplay and patch level to 0.12.

Looking to the future, this represents the last major change to Daggerfall Unity leading up to 1.0. Bug fix and general refinement will resume once 0.13 is considered stable.

Thank you for reading! I hope you decide to try out Daggerfall Unity 0.13 preview to help test mods and provide feedback.

Retiring Live Builds Page

Future Releases

For the last few versions, patch notes and downloads have been mirrored to our GitHub Releases page. Starting from upcoming July builds, our Releases page will be the official site to find new builds of Daggerfall Unity. Live Builds will be retired and redirect to Releases.

This comes with a few advantages. Patch notes, source, and downloads for each release now all live together in one place, and a longer release history can be maintained. Whereas Live Builds would only keep last two or three builds, Releases can retain all new versions going forwards. It also means new releases can be curated by other developers as future stewardship of Daggerfall Unity broadens beyond myself.

This is part of a strategy to make GitHub the primary Daggerfall Unity site in time for 1.0 release. As a project that has now been worked on by over 50 people across 5+ years, it doesn’t make sense for a personal blog site to be the centre of such an endeavour. I’ll have more to share about this as 1.0 approaches later in 2021.

Development History

Daggerfall Workshop started as a personal blog site outlining my journey creating exploring tools for Daggerfall. Since Daggerfall Unity reached classic parity in 2019, most of the posts here have been patch notes in bullet format. But if you look back over posts from a few years ago, there were more interesting and technical updates as the energy of development was in full swing.

My sentiment is the basic patch notes are starting to bury more interesting posts from DFU’s long development history. Rather than continue this trend, I’d like Daggerfall Workshop to stand as a journal of one person’s mad obsession gradually leading into a rather astounding fan remake that has since outgrown the person who started it.

Back to Its Roots

I’ll still post major news and events here on the Workshop, and I might even use it as a personal devblog again someday. There’s a future coming for Daggerfall Unity that doesn’t need me to manage every release and review every line of code. In that future, I’m just one more person who loves this game. I might at last have some time just to play for fun and build mods of my own on the side.

And someday after 1.0, once I’ve had time to decompress and organise my thoughts, I’d love write a detailed postmortem of Daggerfall Unity’s development. This would be a fitting capstone to the Workshop after more than 20 years of tinkering on this unique game.

Daggerfall Unity Beta 0.11.4

Daggerfall Unity Beta 0.11.4 is now available for download on Live Builds and Releases page. This is a heavy bug-fix build with some new mod support.

As always, a big thank you to everyone adding new code, fixing bugs, and helping test. You all help make each release the best it can be.

General Fixes & Improvements

KABoissonneault

  • Added the ability for mods to specify an item type as “noRepairs”
  • Modding the character sheet’s Skills dialog UI mod system
  • Fix: Show biography skill bonuses during character creation
  • Added two event handlers for loot spawning
  • Added “weather”, “season”, and “climate” quest trigger conditions
  • Added new time-related text macros
  • Expose the SpellMaker and its subwindows to mods UI
  • Added “resistance” formula overrides.

Ferital

  • Cache RMB blocks
  • Add %mn and %fn macros support to TalkManagerMCP
  • Change NPC knowledge in Talk Manager to match classic
  • Fix automap update not triggering on some occasions
  • Add a runtime method to fix invalid RDB blocks
  • Use classic hack to fix Orsinium overlapping blocks

Pango

  • Resynchronize vital indicators after toggling large HUD bug
  • Quest and enchanted items exclusions wip
  • Fix Castle Wayrest backroom door messages not showing up (issue #1974)
  • Stack identical books together (enhancement)
  • Immediately interrupt resting if you die
  • Prevent levitating and swimming diagonally from being 40% faster bug
  • Don’t reset lastSpell when using magic missile items bug
  • Use monotonic screenshot filenames
  • Preserve rumors line breaks on bulletin boards

Jefetienne

  • Add Large HUD offset logic to FPSSpellCasting like in FPSWeapon

l3lessed

  • SpeedChanger Updates

Hazelnut

  • Allow water tile conversion to be handled by terrain texture mods
  • fix warning on trade window
  • Add new promptmulti action for 2-4 button message boxes in quests
  • Add OnItemHover to inventory window for mods
  • Open up spell book for mods
  • Fix typo in DFU macro %pg1 bug
  • Reset ship ownership on new game start bug
  • Enable player torch shadows based on spell shadows setting
  • Re-fix riding sprint in mods bug
  • Refactor guild service window UI mod system
  • Add formula for bank loans

XJDHDR

  • Fixed ArgumentOutOfRangeException on loading game with new dungeon models
  • Extra features for the CustomDoor script

Jay_H

  • U0C00Y00 Fix

TheLacus

  • Create ITerrainMaterialProvider and allow overriding by mods
  • Add “Create > C# Mod Script” menu for quickly adding new mod script

Interkarma

  • Add back Rigidbody to PlayerAdvanced
  • Refill player vitals after banishment
  • Prevent Seducer stunlock during transformation
  • Fix out of work exception
  • Use questor billboard when moved by their own quests
  • Handle removal of magic items broken via combat hits
  • Visibly show effect of Drain Speed on enemies
  • Fix equipped “item used do” quest action handling and more
  • Fix multiple “teleport pc” into dungeon desync from world
  • Change Sx977 PlaySound usage
  • PlaySound now counts times sound is played
  • Fix ending condition for Lysandus’ Revenge
  • Add “print_quests” console command
  • Fix exiting non ground-level doors at higher terrain altitudes
  • Unlock Castle Daggerfall doors after teleporting inside
  • Console font fixes
  • Exclude Mantellan Crux “BOX” as crushing hazard
  • Fix custom region overlay on travel map
  • Do not process exhaustion event if player already dead
  • Store lastKeyCode during EventType.KeyDown handling
  • Force weather update after teleporting to different climate
  • Don’t import classis rumours in Save Explorer

Localizing Strings in Daggerfall Unity – Part 6

Series
Localizing Strings in Daggerfall Unity – Part 1
Localizing Strings in Daggerfall Unity – Part 2
Localizing Strings in Daggerfall Unity – Part 3
Localizing Strings in Daggerfall Unity – Part 4
Localizing Strings in Daggerfall Unity – Part 5
Localizing Strings in Daggerfall Unity – Part 6

Custom Fonts

Note: Before progressing to this tutorial, please update source project to Daggerfall Unity 0.11.3 or later. This version has fixes required to complete this part in series.

In Part 3 of this series, we noted the Korean (ko) locale would print out question mark characters (?? ???) instead of proper glyphs.

This happens because Daggerfall Unity does not yet have an appropriate font asset to render these characters. The default fonts have a full complement of Latin characters but non-Latin languages require a new font to display their unique alphabet.

This tutorial will demonstrate how to add a custom Korean font with a Hangul alphabet to Daggerfall Unity, but the same process can be used to add Cyrillic fonts, Kanji fonts, or even just a custom default font.

The font we’ll be using is Noto Serif KR from Google Fonts. Click Download family on that page to download the font used in this tutorial, or substitute with another TTF/OTF font for your language.

Once downloaded, unzip the whole font family and locate NotoSerifKR-Regular.otf. This is the specific font we’ll be using. To start with, we’ll add this font to our Unity project.

  1. In Project view, navigate to our DemoTranslationMod/Resources folder.
  2. Drag and drop the NotoSerifKR-Regular.otf font into this folder with other resources. Unity will import this like below.

Create TextMeshPro Font

Daggerfall Unity uses TextMeshPro (TMP) fonts. Before we can see this font in game, we need to create a TMP font asset.

  1. Click Window menu > TextMeshPro > Font Asset Creator
  2. Set NotoSerifKR-Regular in Source Font File by clicking the circle selector on right-hand side then selecting font

Now we need to determine which character codes our TMP font will support. This will vary based on many factors unique to the target language, but the core concept is that we want to inform Font Asset Creator which character codes from your alphabet to compile into your TMP font. Any characters not added to TMP font asset will continue to display as question marks in game.

There are multiple ways to describe which characters to use. You can select from a basic list of settings, use decimal/hex ranges, import from another TMP font, import from a file, etc. Whatever method you use, keep track of the settings so you can add to it later if any characters are found missing.

In this example, we’re going to use a subset of Hangul alphabet by directly entering the characters required. It’s better to start with a subset of characters for the region/dialect you’re targeting rather than just trying to include everything. Some languages have thousands of characters which can result in an unusable TMP atlas without enough fidelity.

  1. In Font Asset Creator, drop down Character Set selector and choose Custom Characters
  2. Copy and paste the following custom characters into the Custom Character List text box. Note the very first character is a space character.
 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz가개갸거게겨고괴괘교구귀궤규그긔기나내냐너네녀노뇌놰뇨누뉘눼뉴느늬니다대댜더데뎌도되돼됴두뒤뒈류드듸디라래랴러레려로뢰뢔료루뤼뤠류르릐리마매먀머메며모뫼뫠묘무뮈뭬뮤므믜미바배뱌버베벼보뵈봬뵤부뷔붸뷰브븨비사새샤서세셔소쇠쇄쇼수쉬쉐슈브븨비아애야어에여오외왜요우위웨유으의이자재쟈저제져조죄좨죠주쥐줴쥬즈즤지차채챠처체쳐초최쵀쵸추취췌츄츠츼치카캐캬커케켜코쾨쾌쿄쿠퀴퀘큐크킈키타태탸터테텨토퇴퇘툐투튀퉤튜트틔티파패퍄퍼페펴포푀퐤표푸퓌풰퓨프픠피하해햐허헤혀호회홰효후휘훼휴흐희히역을선택십시1234567890‘?’“!”(%)[#]{@}/&\<-+÷×=>®©$€£¥¢:;,.*…

The above characters are enough for this tutorial, but will need to be expanded for full language support. This is how it looks in Font Asset Creator. We’re also adding the basic English alphabet to have a well-rounded font that can still display any untranslated English text.

Click Generate Font Atlas to render all the specified characters into a TMP atlas. Once you’ve created the atlas, you’ll see all the characters packed like below. Click for full size.

TextMeshPro renders glyphs using signed distance fields (SDF). How this works is outside the scope of this tutorial, but to summarise it’s a way of representing fonts using mathematical values that can maintain smooth shapes at any resolution.

In the output field, take note of the Missing characters, Excluded characters, and “characters missing from font file”. This will display any character codes you requested but could not be found in the provided TTF/OTF font. If your source font is missing any important characters, then it’s necessary to locate another TTF/OTF font containing those characters.

Depending on your font requirements, you might want to increase Atlas Resolution, e.g. to 4096×4096 or higher to support more characters with good fidelity. You can also adjust packing method, sample size, etc. for your specific font needs.

For this tutorial, the atlas generated above is good enough. Click the Save button and save your new TMP font to DemoTranslationMod/Resources. We’ll use the default name in a moment, please don’t change it. This creates a new TMP font asset like below with the name “NotoSerifKR-Regular SDF”.

This new SDF asset contains the atlas and other information required to render the TMP font in Daggerfall Unity. You can come back and recreate the font later with different properties or more characters if needed.

Associate Font With Locale

There’s one more step before can see this font in game. We need to associate our custom font with the correct locale so that Daggerfall Unity knows to use it. This is done using the StartupScript.cs code we created previously.

Open StartupScript.cs in your code editor and replace the entire contents with below. Don’t forget to save your changes!

using UnityEngine;
using UnityEngine.Localization;
using UnityEngine.Localization.Settings;
using DaggerfallWorkshop.Game;
using DaggerfallWorkshop.Game.Utility.ModSupport;
using DaggerfallWorkshop.Game.UserInterface;

namespace DemoTranslationMod
{
    public class StartupScript : MonoBehaviour
    {
        // Define the names of translated string table collections
        const string runtimeInternalStrings = "Demo_Strings";
        const string runtimeRSCStrings = "Demo_RSC";

        public static Mod mod;

        [Invoke(StateManager.StateTypes.Start, 0)]
        public static void Init(InitParams initParams)
        {
            mod = initParams.Mod;
            var go = new GameObject(mod.Title);
            go.AddComponent<StartupScript>();
        }

        private void Awake()
        {
            // Set TextManager properties to use translated string table collections
            TextManager.Instance.RuntimeInternalStrings = runtimeInternalStrings;
            TextManager.Instance.RuntimeRSCStrings = runtimeRSCStrings;

            // Load KO font
            DaggerfallFont font_ko = new DaggerfallFont(DaggerfallFont.FontName.FONT0003);
            font_ko.LoadSDFFontAsset("NotoSerifKR-Regular SDF");

            // Assign KO font
            Locale ko = LocalizationSettings.AvailableLocales.GetLocale("ko");
            if (ko)
            {
                TextManager.Instance.RegisterLocalizedFont(ko, DaggerfallFont.FontName.FONT0003, font_ko);
            }

            Debug.Log("StartScript has completed.");
        }
    }
}

Let’s take a look at what changed. To start with, we added some new using statements. These import some extra functionality to the script.

using UnityEngine.Localization;
using UnityEngine.Localization.Settings;
using DaggerfallWorkshop.Game.UserInterface;

Then we added the following code to associate our custom font with the KO locale to Daggerfall’s FONT003. This is the default font used in most parts of the game.

// Load KO font
DaggerfallFont font_ko = new DaggerfallFont(DaggerfallFont.FontName.FONT0003);
font_ko.LoadSDFFontAsset("NotoSerifKR-Regular SDF");

// Assign KO font
Locale ko = LocalizationSettings.AvailableLocales.GetLocale("ko");
if (ko)
{
    TextManager.Instance.RegisterLocalizedFont(ko, DaggerfallFont.FontName.FONT0003, font_ko);
}

First, we create a custom DaggerfallFont called font_ko. By default we’re loading FONT003, but we’ll replace this in a moment with our custom font.

Second, we tell font_ko to load our custom font asset using LoadSDFFontAsset(). Any font created using the TextMeshPro Font Asset Creator should load OK. Reminder: you need to be on Daggerfall Unity 0.11.3 or later.

Finally, we try to get the “ko” locale and only continue if this locale is found. If the locale is found, we associate our custom DaggerfallFont with the “ko” locale using RegisterLocalizedFont().

When this code executes at startup, Daggerfall Unity now knows it should use a different font when rendering FONT003 within the Korean (ko) locale. You can associate the same SDF font with FONT001, FONT002, etc. but you might want to use different styles of typefaces to better match the desired look and feel in your translation.

Make sure your changes are saved, then we can try this font in game.

  1. Click Play to start the game and click through to title menu.
  2. Use the locale drop-down to select Korean (ko) in Game view.
  3. Click Start New Game in title menu. If everything works as expected, our custom font will be selected and used with our translated text example.

Click Play again to stop game.

To summarise, creating a custom font requires the following steps:

  1. Locate appropriate TTF/OTF source fonts for your language. These fonts must contain all the alphabet characters you need for your translation.
  2. Import the TTF/OTF font into Unity project.
  3. Use the Font Asset Creator to generate a custom TMP font asset with the required characters and resolution.
  4. Associate new font with your custom locale and related Daggerfall font in startup C# script.

You might need to recreate font several times when creating your translation mod, either to add new characters, change resolution, or just finetune the look and feel. If you change the asset name, don’t forget to update this in your startup script.

Now that we have a custom font, we can move on to packaging our localisation to standalone files. This will be covered in Localizing Strings in Daggerfall Unity – Part 7.