<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title>AssetHoard blog</title>
		<link>https://assethoard.com/blog</link>
		<atom:link href="https://assethoard.com/rss.xml" rel="self" type="application/rss+xml" />
		<description>Guides, artist spotlights, indie life and engineering deep dives from the team behind AssetHoard, the local-first asset manager for indie game developers.</description>
		<language>en-au</language>
		<lastBuildDate>Tue, 13 Oct 2026 00:00:00 GMT</lastBuildDate>
		<item>
			<title>How we built the AssetHoard MCP server</title>
			<link>https://assethoard.com/blog/how-we-built-the-assethoard-mcp-server</link>
			<guid isPermaLink="true">https://assethoard.com/blog/how-we-built-the-assethoard-mcp-server</guid>
			<pubDate>Tue, 13 Oct 2026 00:00:00 GMT</pubDate>
			<dc:creator>Mark Gandolfo</dc:creator>
			<category>AssetHoard news</category>
			<description>AssetHoard&apos;s built-in MCP server lets Claude Code, Cursor, VS Code and Windsurf search your asset library and export into your game project. How we built it.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/2026-10-how-we-built-the-assethoard-mcp-server.jpg" alt="Diagram showing AI assistants (Claude Code, Cursor, VS Code, Windsurf) searching an AssetHoard library through its MCP server and exporting assets into Godot, Unity and Unreal Engine projects" /></p>
<p>You&#39;re three hours into building a level. You need a barrel. You know you own at least four barrel packs, because you bought them in three different bundle sales and one of them was &quot;a steal&quot;. Finding them means leaving the editor, opening a file browser, and digging through folders called <code>Downloads (2)</code>.</p>
<p>Meanwhile there&#39;s an AI assistant sitting in your editor that can write a state machine in eight seconds but has no idea what&#39;s on your hard drive.</p>
<p>AssetHoard is a local-first desktop asset manager for indie game developers and digital artists, and version 0.2.3 fixes that with a built-in <a href="https://assethoard.com/mcp-server">MCP server</a>. This post covers how we built it, why it&#39;s locked down the way it is, and the things we&#39;ve found it genuinely useful for.</p>
<h2 id="what-mcp-is-briefly">What MCP is, briefly</h2><p>The Model Context Protocol is an open standard for letting AI tools call other programs. A program exposes a set of named tools with typed arguments (&quot;search&quot;, &quot;export&quot;, &quot;create_bundle&quot;), and any MCP client (Claude Code, Cursor, VS Code, Windsurf, Claude Desktop) can discover and call them.</p>
<p>For an asset manager that&#39;s a natural fit. AssetHoard already knows every model, texture, sprite and sound you own, what&#39;s in which bundle, what it&#39;s tagged, and what each file depends on. MCP lets your assistant ask it.</p>
<h2 id="the-decisions-that-shaped-it">The decisions that shaped it</h2><h3 id="built-into-the-app-not-a-separate-program">Built into the app, not a separate program</h3><p>The obvious shortcut would have been a little standalone server that opens AssetHoard&#39;s SQLite database and reads it directly. We didn&#39;t do that, for two reasons.</p>
<p>First, two programs writing to one SQLite file is how you end up with a corrupted library and a very bad afternoon. Second, the app would never find out about changes. You&#39;d ask your assistant to tag forty rocks and the open window would keep showing them untagged until you restarted.</p>
<p>So the server runs inside AssetHoard itself, and the app has to be open for it to answer. That turned out to be a feature: every change the assistant makes shows up in the window straight away.</p>
<p>Living inside the app also means you stay in charge of it from the app:</p>
<ul>
<li><strong>Turn it on and off.</strong> One switch in Settings &gt; MCP Server. It&#39;s off until you flip it, and a plug icon sits in the toolbar whenever it&#39;s running, so you&#39;re never guessing.</li>
<li><strong>See what changed.</strong> When an assistant exports files or edits your library, AssetHoard shows a notification in the app saying what it did, and the settings page keeps a list of recent calls.</li>
<li><strong>Decide how much the assistant can do.</strong> Out of the box it can only search, look and export. Changing your library needs &quot;Allow write tools&quot; switched on, and importing files pops up a prompt you have to approve. If you&#39;d rather keep it read-only forever, just leave the write switch off.</li>
</ul>
<h3 id="one-rule-mcp-never-touches-the-database-directly">One rule: MCP never touches the database directly</h3><p>The MCP code lives in its own module, and it isn&#39;t allowed to call app commands or SQL. Everything goes through a small internal library API that sits underneath both the UI and the MCP server.</p>
<p>That sounds like bureaucracy, but it&#39;s what makes the write tools trustworthy. When an assistant moves an asset into a bundle, it runs exactly the same function as when you drag it there yourself. Same validation, same audit log, same undo entry. There&#39;s no second, slightly different code path quietly drifting out of sync with the real one.</p>
<p>It also makes adding a tool cheap. A new tool is a typed argument struct (whose doc comments become the descriptions the model reads) and a thin method that calls the library API. The interesting logic stays in one place and gets tested once.</p>
<h3 id="rust-rmcp-and-streamable-http">Rust, rmcp and streamable HTTP</h3><p>AssetHoard&#39;s backend is Rust, so we used <a href="https://github.com/modelcontextprotocol/rust-sdk" target="_blank" rel="noopener noreferrer">rmcp</a>, the official Rust SDK for MCP, with its streamable HTTP transport mounted on axum. Database work runs on blocking worker threads so a big search never stalls the app&#39;s async runtime, and each call is recorded in a recent-activity list you can watch in Settings.</p>
<p>We picked HTTP over stdio because the server lives inside a desktop app that&#39;s already running. Claude Code, Cursor, VS Code and Windsurf all connect to a local HTTP endpoint with a header, which is a one-line setup. Claude Desktop is the odd one out: it only launches stdio servers, so for now it connects through the <code>mcp-remote</code> bridge.</p>
<h3 id="a-fixed-port-on-purpose">A fixed port, on purpose</h3><p>The server listens on port <code>47823</code> by default. You can change it, but AssetHoard will never pick a different one on its own if that port is busy. Auto-switching sounds helpful until every client config you&#39;ve written silently stops matching. Instead, a taken port shows up as an error with a readable message, and you choose what to do.</p>
<h2 id="making-it-safe-to-leave-on">Making it safe to leave on</h2><p>A local server that can read your files and write to your library deserves some paranoia. Here&#39;s what&#39;s in place:</p>
<ul>
<li><strong>Off by default.</strong> You turn it on in Settings &gt; MCP Server.</li>
<li><strong>Local only.</strong> It binds to <code>127.0.0.1</code>, so nothing on your network or the internet can reach it.</li>
<li><strong>Token required.</strong> Every request needs a bearer token: 48 random hex characters, compared in constant time. Regenerating it disconnects every client.</li>
<li><strong>Browsers are refused.</strong> Any request with an <code>Origin</code> header is rejected, and the <code>Host</code> header must be a loopback address. Browsers always send <code>Origin</code>; CLI and IDE clients don&#39;t. This blocks DNS rebinding, where a malicious web page tries to talk to a server on your machine, and it&#39;s what the MCP spec asks local servers to do.</li>
<li><strong>Write tools are a second opt-in.</strong> &quot;Allow write tools&quot; is a separate toggle, and it&#39;s checked on every call, so switching it off takes effect immediately, even for clients that are already connected.</li>
<li><strong>No deleting your stuff.</strong> There are no tools for deleting assets or bundles. The only deletes are for categories nothing uses and projects that are already empty.</li>
<li><strong>Exports never overwrite.</strong> If a file already exists at the destination, it&#39;s skipped and reported.</li>
<li><strong>Imports ask first.</strong> When an assistant wants to import a folder, AssetHoard pops up a prompt with the path, file count, size and target bundle, and flashes the window. No answer within 60 seconds counts as no. If you trust your setup, &quot;Import without asking&quot; turns this off.</li>
<li><strong>Everything is undoable.</strong> Writes go on the normal undo stack with an <code>MCP:</code> label, like <code>MCP: Moved 1 asset into &#39;Rocks&#39;</code>, and a toast tells you what changed. Ctrl+Z (Cmd+Z on a Mac) works exactly as it does for your own edits.</li>
</ul>
<p>A plug icon appears in the toolbar whenever the server is running, so you always know it&#39;s on.</p>
<p><a href="https://assethoard.com/pages/mcp-server/assethoard-mcp-settings.png" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/pages/mcp-server/assethoard-mcp-settings.png" alt="The MCP Server page in AssetHoard settings, with the server toggle, connection token and client setup commands" title="Settings > MCP Server" width="1920" height="1080" loading="eager" decoding="async"></a></p>
<h2 id="small-things-that-made-a-big-difference">Small things that made a big difference</h2><p><strong>Search returns text, thumbnails are separate.</strong> Search results are ids, names, types, paths and tags, which keeps them small. If the assistant wants to actually look at something, it calls <code>get_thumbnail</code> and gets a preview image of at most 256 pixels. That means it can check that the &quot;mossy rock&quot; really is mossy before suggesting it, without flooding its context with every result&#39;s picture.</p>
<p><strong>Dependencies come along.</strong> Exporting a model brings its textures. Exporting a Godot <code>.tres</code> brings the files it references, and Unreal assets bring theirs. Exporting a whole bundle keeps its folder layout. Assets inside zip archives or <code>.unitypackage</code> files are pulled out first.</p>
<p><strong>Clickable links.</strong> Every asset, bundle and project the server returns includes an <code>assethoard://</code> link. The assistant can hand you a link, you click it, and AssetHoard jumps to that item. We added the link scheme to the app specifically for this.</p>
<p><strong>Errors the model can read.</strong> An unknown id, a bundle inside a package, or write tools being switched off all come back as plain error messages rather than protocol failures, so the assistant can explain what happened or try something else.</p>
<h2 id="what-you-can-do-with-it">What you can do with it</h2><p>Here&#39;s what this looks like in practice. These are the kinds of things you&#39;d type into Claude Code, Cursor or similar with AssetHoard running.</p>
<h3 id="set-dressing-without-leaving-the-editor">Set dressing without leaving the editor</h3><blockquote>
<p>&quot;Find three different barrel models and a wood texture that matches, and copy them into <code>Assets/Props</code>.&quot;</p>
</blockquote>
<p>The assistant searches your library, looks at the thumbnails of the best few, picks a set and exports them, textures included. You keep building the level. This was the main use case we designed for, and it&#39;s the one in the <a href="https://assethoard.com/mcp-server">demo video</a>.</p>
<h3 id="search-by-what-it-looks-like-not-what-its-called">Search by what it looks like, not what it&#39;s called</h3><blockquote>
<p>&quot;Do I have any mossy stone wall textures?&quot;</p>
</blockquote>
<p>Search works the same way as AssetHoard&#39;s search bar: by name with typo tolerance, and by meaning when semantic search is turned on. Since 0.2.3 that includes embedded audio metadata too, so &quot;glass shatter&quot; can find <code>SFX_0472_FINAL.wav</code> if that&#39;s what its description says.</p>
<h3 id="narrow-it-down-like-you-would-in-the-app">Narrow it down like you would in the app</h3><blockquote>
<p>&quot;Show me Godot UI sprites from my Kenney bundle.&quot;</p>
</blockquote>
<p>Results can be filtered by file type, asset class, engine, tag, category or bundle. The assistant works out the bundle id itself and filters inside it.</p>
<h3 id="drop-a-whole-tileset-into-a-project">Drop a whole tileset into a project</h3><blockquote>
<p>&quot;Copy my &#39;Dungeon Tileset&#39; bundle into the Godot project at <code>C:/dev/crawler</code>.&quot;</p>
</blockquote>
<p>The bundle&#39;s sub-bundles become folders in the destination, so the structure you set up in AssetHoard carries over.</p>
<h3 id="tidy-up-the-library-write-tools-on">Tidy up the library (write tools on)</h3><blockquote>
<p>&quot;Make a bundle called &#39;Rocks&#39; under &#39;Environment&#39;, move every rock model into it and tag them &#39;nature&#39;.&quot;</p>
</blockquote>
<p>The assistant creates the bundle, searches, moves and tags. Each step appears live in the app and is its own undo entry. If it gets carried away and moves a boulder that was actually a potato, Ctrl+Z.</p>
<p>A slower but satisfying variation: &quot;Find the untagged textures in my Downloads bundle, look at each one and suggest tags.&quot; Review the suggestions, say yes, and let it apply them.</p>
<h3 id="keep-track-of-what-a-game-uses">Keep track of what a game uses</h3><blockquote>
<p>&quot;Start a project called &#39;Crawler&#39; and add the dungeon tileset and the footstep sounds to it.&quot;</p>
</blockquote>
<p>Projects in AssetHoard only record references. Nothing moves, and an item can belong to several projects. Once a project is set up, you can ask questions like &quot;list everything in Crawler and tell me which assets have no licence recorded&quot;, which is a much nicer way to find out before release than after.</p>
<h3 id="onboard-a-new-pack">Onboard a new pack</h3><blockquote>
<p>&quot;Import <code>C:/Users/me/Downloads/kenney_platformer-pack</code> into my Kenney bundle, then categorise the new assets by type.&quot;</p>
</blockquote>
<p>AssetHoard asks you to allow the import, runs it through the normal import queue with the usual progress notification, then the assistant categorises what came in. The whole import is one undo entry.</p>
<h2 id="whats-next">What&#39;s next</h2><p>The main gap right now is Claude Desktop needing the <code>mcp-remote</code> bridge. A small native shim that lets it connect directly is on the list. We&#39;d also like to hear what you end up using the server for, because the tool list was shaped by our own workflow and yours is probably weirder.</p>
<h2 id="try-it">Try it</h2><p>The MCP server is in <a href="https://assethoard.com/releases/0.2.3">AssetHoard 0.2.3</a> and later. Open Settings &gt; MCP Server, switch it on, and paste the setup command into your client. The <a href="https://assethoard.com/docs/mcp">MCP docs</a> cover each client, and the <a href="https://assethoard.com/docs/mcp-tools">tool reference</a> lists every tool and its arguments. AssetHoard is free to download during the open beta, so the only thing it&#39;ll cost you is finally finding out how many barrel packs you own.</p>
<hr>
<p><em>The AssetHoard Team</em></p>
]]></content:encoded>
		</item>
		<item>
			<title>How to stay motivated as a solo indie developer</title>
			<link>https://assethoard.com/blog/staying-motivated-solo-indie-developer</link>
			<guid isPermaLink="true">https://assethoard.com/blog/staying-motivated-solo-indie-developer</guid>
			<pubDate>Sun, 11 Oct 2026 00:00:00 GMT</pubDate>
			<dc:creator>Mark Gandolfo</dc:creator>
			<category>Indie life</category>
			<description>Motivation runs out on every long project. Solo indie developers who finish rely on habits, visible progress and real rest to get through the slow middle.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/2026-10-staying-motivated-solo-indie-developer.jpg" alt="An empty desk lit by a single lamp at night, with city lights through the window" /></p>
<p>Every solo dev I know has hit the same wall. The first few weeks of a project are electric. You can see the whole thing in your head, the ideas won&#39;t stop coming, and you&#39;d happily skip meals to keep building. Then, somewhere around week six or month three, the electricity goes out. The work is still there. The excitement isn&#39;t.</p>
<p>This isn&#39;t a character flaw and it isn&#39;t a sign you picked the wrong project. It&#39;s the shape of every long piece of solo work. You will not feel motivated all the time, because nobody does. What you can do is build something that keeps you moving when the motivation is gone.</p>
<h2 id="the-short-version">The short version</h2><p>If you only take a few things away, take these. The rest of the post unpacks each one.</p>
<ul>
<li>Stop waiting to feel motivated. Build habits that still produce something on a flat day.</li>
<li>Shrink the next task until it&#39;s almost embarrassingly small, then start there.</li>
<li>Set a daily minimum you can hit even on your worst day, and protect the streak.</li>
<li>Keep a visible record of what you&#39;ve finished, on screen or on paper.</li>
<li>Beat isolation on purpose: find other devs, post devlogs, get one person to hold you to it.</li>
<li>Compare yourself to last month&#39;s you, never to someone else&#39;s finished game.</li>
<li>Treat rest, food, exercise and people as part of the schedule, not a reward you earn.</li>
</ul>
<h2 id="motivation-is-a-bad-thing-to-depend-on">Motivation is a bad thing to depend on</h2><p>Motivation is a feeling, and feelings come and go for reasons you don&#39;t control. You slept badly. The bug you spent all day on wasn&#39;t the real bug. Someone posted a screenshot of their game that made yours look like a student project. Any of those can flatten your drive for a day, and if your ability to work depends on feeling driven, you&#39;ve just lost a day.</p>
<p>The developers who finish things have arranged their work so that a flat day still produces something. They&#39;ve quietly stopped asking &quot;do I feel like working&quot; and started asking &quot;what&#39;s the next small thing I said I&#39;d do&quot;.</p>
<h2 id="shrink-the-task-until-its-stupidly-small">Shrink the task until it&#39;s stupidly small</h2><p>When you can&#39;t face the work, the task in your head is almost always too big. &quot;Build the inventory system&quot; is not a task, it&#39;s a project, and staring at it does nothing but make you tired.</p>
<p>The fix is to shrink the next step until it&#39;s almost embarrassingly small. Not &quot;build the inventory system&quot; but &quot;add one slot to the inventory grid&quot;. Not &quot;do the audio pass&quot; but &quot;wire up the sound for the door opening&quot;. A task you can picture finishing in twenty minutes is a task you can start, and starting is the whole problem. Momentum almost always shows up once you&#39;re moving, it just refuses to show up beforehand.</p>
<p>On genuinely bad days, shrink it further. Open the project. Read the code you wrote yesterday. That&#39;s allowed to be the whole session. More often than not, once the file is open you&#39;ll fix one small thing, and one small thing is infinitely more than zero.</p>
<h2 id="set-a-daily-minimum-you-can-hit-on-your-worst-day">Set a daily minimum you can hit on your worst day</h2><p>Pick a floor. Something so small that you&#39;d feel silly not doing it even when you&#39;re exhausted or fed up. Fifteen minutes. One commit. One asset placed. One line of design doc.</p>
<p>The output barely matters. What the minimum protects is the streak. A chain of tiny days keeps the project alive in your head and stops the restart cost from piling up. If you skip a project for a fortnight, coming back costs you an afternoon just remembering where you were. If you touched it yesterday, you&#39;re already warm.</p>
<p>Some days you&#39;ll hit the minimum and stop, and that&#39;s fine. Plenty of days you&#39;ll hit the minimum and then keep going for two hours because you were never really tired, you were just staring at something too big. The minimum only has to get you to the desk. Most of the time, once you&#39;re there, you keep going.</p>
<h2 id="make-progress-visible-because-your-brain-wont-do-it-for-you">Make progress visible, because your brain won&#39;t do it for you</h2><p>The cruel thing about the middle of a project is that progress stops feeling like progress. The exciting, visible milestones are behind you and ahead of you, and the middle is a thousand small tasks that don&#39;t individually look like much. Left alone, your brain will happily conclude you&#39;ve done nothing for a month.</p>
<p>So don&#39;t leave it alone. Keep a record it can&#39;t argue with. A &quot;done&quot; list you actually add to, a devlog you post every week whether or not anyone reads it, a folder of dated screenshots you can scroll back through. When the doubt shows up, you want evidence sitting right there. The version of your game from three months ago is the proof, and if you never captured it, the doubt wins by default.</p>
<p>None of this has to happen in front of a computer either. Grab a notebook and sketch the inventory system you&#39;ve been putting off. Scribble down a world-building idea before it evaporates. Draw the level on graph paper. A page of notes from a walk is still a record of a day you moved the project forward, and some days it&#39;s the easiest kind to make.</p>
<p>This is one place a bit of tooling earns its keep. Being able to scroll back through what you&#39;ve built, the sprites you&#39;ve drawn, the models you&#39;ve made, the packs you&#39;ve assembled, is a quiet antidote to the feeling that you&#39;re standing still. Half the time you&#39;re much further along than it feels. (It&#39;s a big part of why <a href="https://assethoard.com/blog/how-i-manage-100000-game-assets" title="How I manage 100,000 game assets">I organise my asset library</a> so I can actually see it.)</p>
<h2 id="isolation-is-the-real-enemy-not-the-work">Isolation is the real enemy, not the work</h2><p>The work is rarely what breaks people. Working entirely alone for months is what breaks people. No colleague to tell you the idea&#39;s good. Nobody to notice you shipped the thing. No standup where you say out loud what you did yesterday and quietly realise it was quite a lot.</p>
<p>You have to manufacture what a team gives you for free. Find a Discord of other solo devs (<a href="https://assethoard.com/discord" title="Join the AssetHoard Discord">the AssetHoard Discord</a> is one) and actually turn up in it. Post your devlog even to an audience of nine. Tell one friend what you&#39;re shipping this week so there&#39;s a human who&#39;ll ask how it went. Pair up with another dev and trade weekly check-ins. None of this is marketing. It keeps the work real to someone other than you. Externalising your progress to even one other person changes how the work feels, because suddenly you&#39;re not the only one who knows it exists.</p>
<p>If in-person is an option, take it. A monthly indie meetup or a game jam can reset your whole outlook in an afternoon, mostly by reminding you that everyone else is also stuck on something and doubting themselves too.</p>
<h2 id="stop-comparing-your-middle-to-someone-elses-end">Stop comparing your middle to someone else&#39;s end</h2><p>The screenshot that ruined your afternoon was a finished, polished, cherry-picked frame of someone else&#39;s months of unglamorous work. You compared it to your actual Tuesday, bugs and placeholder art and all. Of course you lost.</p>
<p>Everything you see online is a highlight. The trailer, the launch post, the &quot;we hit a thousand wishlists&quot; thread. You don&#39;t see the fortnight they spent fighting the same engine bug you&#39;re fighting, or the three redesigns they binned, or the week they didn&#39;t open the project at all. Comparison isn&#39;t just unkind to yourself, it&#39;s inaccurate, because you&#39;re missing most of the data.</p>
<p>The only honest comparison is you against you. Are you further along than last month? Then it&#39;s working.</p>
<h2 id="protect-your-life-not-just-your-rest">Protect your life, not just your rest</h2><p>A lot of solo devs treat rest as a reward they have to unlock by working hard enough, which means they never quite unlock it, which means they run flat out until they crash. Then they lose two weeks to burnout and call themselves lazy for it.</p>
<p>Rest isn&#39;t earned, it&#39;s part of the schedule. So is eating well, exercising, and spending time with friends and family. None of that is what you do once the real work is finished, it&#39;s the space that lets you recharge between sessions of the real work. Build it in on purpose. Take one full day off a week and don&#39;t touch the project. Stop at a set time most evenings. Go outside. The ideas that untangle your worst problems almost never arrive while you&#39;re grinding at the desk, they turn up in the shower, on a walk, doing the washing up. A rested brain is a faster brain, and a burned-out one ships nothing at all.</p>
<p>Burnout is not a badge. It&#39;s a project risk, and it&#39;s your job to manage it like any other.</p>
<h2 id="what-it-actually-takes">What it actually takes</h2><p>Staying motivated as a solo dev is mostly a matter of not needing to be motivated. You build small habits, you make your progress visible, you find a few humans to be accountable to, you rest before you&#39;re wrecked, and you keep comparing yourself only to yesterday&#39;s version of yourself.</p>
<p>Do that, and the flat days stop being a threat. They become just another Tuesday where you hit your minimum, close the laptop, and come back tomorrow. The people who finish games aren&#39;t superhuman. They just kept turning up through the boring middle, one small task at a time, until the finish line quietly showed up.</p>
<p>Keep turning up.</p>
<hr>
<p><em>The AssetHoard Team</em></p>
<p class="photo-credit">Hero photo by <a href="https://unsplash.com/@jcgellidon" title="JC Gellidon on Unsplash">JC Gellidon</a> on <a href="https://unsplash.com/photos/EH9f0TI5wco" title="Desk lamp photo on Unsplash">Unsplash</a>.</p>
]]></content:encoded>
		</item>
		<item>
			<title>Artist spotlight: James Rommel Lobaton, Spine 2D animator</title>
			<link>https://assethoard.com/blog/artist-spotlight-james-rommel-lobaton</link>
			<guid isPermaLink="true">https://assethoard.com/blog/artist-spotlight-james-rommel-lobaton</guid>
			<pubDate>Sat, 03 Oct 2026 00:00:00 GMT</pubDate>
			<dc:creator>The AssetHoard Team</dc:creator>
			<category>Artist spotlight</category>
			<description>2D/3D game animator James Rommel Lobaton on rigging other artists&apos; work in Spine, his commission process, and what indie devs should know before hiring one.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/artist-spotlight/james-lobaton-hero.jpg" alt="Isometric Dota 2 battle dioramas lit by lightning and fire, by James Rommel Lobaton" /></p>
<p>Welcome back to our <a href="https://assethoard.com/blog/artist-spotlight-tesseract-assets">Artist Spotlight series</a>, where we chat with creators in the game dev space about their work, their process, and what they&#39;ve learned along the way.</p>
<p>This time we&#39;re talking to James Rommel G. Lobaton, a 2D and 3D game animator from the Philippines with ten years in the industry, a Unity Asset Store shop, and a portfolio that swings happily between Dota 2, fighting games, horror icons and anime.</p>
<p><a href="https://assethoard.com/blog/2026/artist-spotlight/james-lobaton-jason.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/artist-spotlight/james-lobaton-jason.jpg" alt="Jason Voorhees in his hockey mask lunging through streaks of green and red, fan art by James Rommel Lobaton" width="1600" height="844" loading="eager" decoding="async"></a></p>
<h2 id="for-readers-who-havent-come-across-your-work-yet-what-do-you-do">For readers who haven&#39;t come across your work yet, what do you do?</h2><div style="margin-bottom: -1rem; display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem;">
<div>

<p>I&#39;m a 2D/3D game animator, and I&#39;ve been in the animation industry for ten years now. I create animation for games, and on the side I take commissions for character designs and creatures.</p>
<p>During the day I work at a local game dev studio in the Philippines. After work I go home and work again on freelance jobs.</p>
<p>We also have a Unity Asset Store shop, where my friends and I make 2D chibi assets for games. Some are PNGs, and some are bundles with animations ready to drop into a game.</p>
</div>
<div>

<p><a href="https://assethoard.com/blog/2026/artist-spotlight/james-lobaton-six-fanarts.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/artist-spotlight/james-lobaton-six-fanarts.jpg" alt="Six Fan Arts Challenge 2026: six characters in comic panels drawn in heavy black line art, by James Rommel Lobaton" width="1200" height="1492" loading="lazy" decoding="async"></a></p>
</div>
</div>

<h2 id="how-did-you-end-up-working-across-both-2d-and-3d-and-was-game-development-always-the-goal">How did you end up working across both 2D and 3D, and was game development always the goal?</h2><p>I started late on this path. Before animation I was a delivery guy, delivering special welding rods to industrial companies. Animation is my second chance.</p>
<p>I studied a vocational 3D animation course, and from there I threw myself into learning everything about 3D, trying to be a one-man army. While I kept studying 3D, I was also learning Photoshop and basic 2D drawing.</p>
<p>Then I got the opportunity to work at a game dev studio as a 3D animator. As the project went on we ran into trouble: they couldn&#39;t integrate 3D characters into a 2D environment. That&#39;s where the switch happened. I needed to learn <a href="https://esotericsoftware.com/?utm_source=assethoard&utm_medium=referral" target="_blank" rel="noopener noreferrer">Spine</a>, and that&#39;s how I became a 2D/3D animator.</p>
<p>My teacher in the industry was into games, so all of my practice was for games. Dota 2 inspired me a lot too. So yes, I love game dev.</p>
<p><a href="https://assethoard.com/blog/2026/artist-spotlight/james-lobaton-dota-team-a.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/artist-spotlight/james-lobaton-dota-team-a.jpg" alt="Dota 2 heroes whose names start with A, lined up in front of a big "Team A" title, fan art by James Rommel Lobaton" width="1600" height="913" loading="lazy" decoding="async"></a></p>
<h2 id="your-portfolio-mixes-dota-2-fighting-games-horror-icons-and-anime-what-shaped-your-style">Your portfolio mixes Dota 2, fighting games, horror icons and anime. What shaped your style?</h2><p>I&#39;ve loved comics since I was a kid. I love the sharp black lines and big buckets of black against vibrant colours. Since starting on this path, I&#39;ve always practised my drawing, starting with chibi characters. The style has stayed the same: black line art and cool, vibrant colours.</p>
<div class="post-flipbook">

<p><a href="https://assethoard.com/blog/2026/artist-spotlight/james-lobaton-dota.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/artist-spotlight/james-lobaton-dota.jpg" alt="Zeus from Dota 2 crackling with lightning, fan art by James Rommel Lobaton" title="Zeus, Dota 2" width="960" height="1200" loading="lazy" decoding="async"></a></p>
<p><a href="https://assethoard.com/blog/2026/artist-spotlight/james-lobaton-fighting.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/artist-spotlight/james-lobaton-fighting.jpg" alt="Cammy and Chun-Li from Street Fighter standing side by side, fan art by James Rommel Lobaton" title="Cammy and Chun-Li, Street Fighter" width="960" height="1200" loading="lazy" decoding="async"></a></p>
<p><a href="https://assethoard.com/blog/2026/artist-spotlight/james-lobaton-horror.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/artist-spotlight/james-lobaton-horror.jpg" alt="Freddy Krueger slashing with his bladed glove, fan art by James Rommel Lobaton" title="Freddy Krueger, A Nightmare on Elm Street" width="960" height="1200" loading="lazy" decoding="async"></a></p>
<p><a href="https://assethoard.com/blog/2026/artist-spotlight/james-lobaton-anime.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/artist-spotlight/james-lobaton-anime.jpg" alt="Kaiju No. 8 in his armoured kaiju form with glowing cyan markings, fan art by James Rommel Lobaton" title="Kaiju No. 8" width="960" height="1200" loading="lazy" decoding="async"></a></p>
</div>

<p>Games that influenced me are Hades, Borderlands, Skullgirls and Darkest Dungeon. For artists, it&#39;s Mike Mignola, Ludo Lullabi and Todd McFarlane. They&#39;re brilliant artists, and I love how unique their work is. There&#39;s so much energy in their drawings. It keeps my fire going.</p>
<h3 id="and-what-are-you-drawn-to-right-now">And what are you drawn to right now?</h3><p>I still practise and develop my style digitally, but right now I&#39;m also doing traditional painting and drawing on the side. I love going back to watercolour, gouache and acrylic, with some oil pastels too. It&#39;s my way of not burning out, because I&#39;m always doing something different.</p>
<!-- TODO: image, e.g. traditional painting -->

<h2 id="on-projects-like-into-the-crypt-you-animated-characters-drawn-by-another-artist-how-do-you-approach-that">On projects like Into the Crypt you animated characters drawn by another artist. How do you approach that?</h2><p>Before I take a commission, I always check whether I can do cutouts in the other artist&#39;s style. I use Spine, so I need to cut the art into parts. That&#39;s why I don&#39;t take on realistic art: it&#39;s hard for me to fill in the missing parts of the drawing.</p>
<div style="margin-bottom: -1rem; display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem;">
<div>

<h3 id="what-makes-a-piece-of-art-easy-or-hard-to-rig">What makes a piece of art easy or hard to rig?</h3><p>The hard part is when a character is complicated, like one with lots of tentacles or heavy clothing. The cutouts take time, and the rigging needs some study or research. If a character is really complicated, I need to know how the client plans for it to move so that I can do the cutouts wisely.</p>
</div>
<div>

<p><a href="https://assethoard.com/blog/2026/artist-spotlight/james-lobaton-lou-carcolh.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/artist-spotlight/james-lobaton-lou-carcolh.jpg" alt="Lou Carcolh, a spiked-shell creature trailing long tentacles, from Creatuanary 2026 by James Rommel Lobaton" width="960" height="1127" loading="lazy" decoding="async"></a></p>
</div>
</div>

<h2 id="take-us-through-a-typical-commission-like-the-bone-dragon-boss-what-happens-between-the-brief-and-the-final-files">Take us through a typical commission, like the Bone Dragon boss. What happens between the brief and the final files?</h2><p>First, the client sends all the details about the boss monster. Then I create different silhouettes, pick the ones I like and add detail. At this stage it&#39;s all sketches.</p>
<p>I send those to the art director so they can choose one and ask for adjustments. Then it comes back to me to polish. When everything is signed off, I start doing the cutouts for the Spine animation. The final files are delivered in a folder at the end.</p>
<!-- TODO: image, e.g. Bone Dragon silhouettes and final -->

<h2 id="what-does-your-toolkit-look-like-for-2d-and-3d-work">What does your toolkit look like for 2D and 3D work?</h2><p>I use Photoshop and Procreate for 2D, and Maya or 3ds Max for 3D, though I&#39;m practising Blender now.</p>
<p><video controls muted loop playsinline preload="metadata" aria-label="Rough animation test by James Rommel Lobaton: a figure at a desk in a sketched room, drawn frame by frame in red line"><source src="https://assethoard.com/blog/2026/artist-spotlight/284100568-963885287637534-8856451239821048219-n.mp4" type="video/mp4"></video></p>
<p><em>A rough animation test: the figure is drawn frame by frame in red line, with the frame numbers pencilled in.</em></p>
<h3 id="why-spine-for-game-animation">Why Spine for game animation?</h3><p>It&#39;s a very strong piece of software for quick 2D animation. It&#39;s built for games, it keeps getting better with every update, and it&#39;s a one-time payment. Spine is probably the tool I couldn&#39;t work without. It&#39;s a big part of my commission work.</p>
<h2 id="between-client-work-fan-art-and-challenges-like-inktober-and-swordtember-how-do-you-keep-your-files-organised">Between client work, fan art and challenges like Inktober and Swordtember, how do you keep your files organised?</h2><p>Staying organised is a pain. You have to name things correctly or you&#39;ll waste time looking for your files. I keep my files on Google Drive and my PC, and I name them after the game or the customer.</p>
<p>My biggest pain point is not having enough space on my PC&#39;s drive.</p>
<p><em>(We may know a thing or two about that one. Here&#39;s <a href="https://assethoard.com/blog/how-i-manage-100000-game-assets">how we keep 100,000 game assets findable</a>.)</em></p>
<h2 id="what-do-you-wish-indie-developers-knew-before-commissioning-an-animator">What do you wish indie developers knew before commissioning an animator?</h2><p>Know what you want first: what type of game, what animation style, what art style. Always have references. And always communicate. The faster the reply, the better.</p>
<p><video controls muted playsinline preload="metadata" aria-label="Character design process by James Rommel Lobaton, from silhouettes and colour roughs to the final animated character"><source src="https://assethoard.com/blog/2026/artist-spotlight/flashback-nov-3-2024-11-33-10.mp4" type="video/mp4"></video></p>
<p><em>James&#39;s character process: silhouettes first, then colour roughs, then the final character animated.</em></p>
<hr>
<p>See more of James&#39;s work, or get in touch about new projects:</p>
<ul>
<li><a href="https://www.artstation.com/jamesrommellobaton8" target="_blank" rel="noopener noreferrer">ArtStation</a></li>
<li><a href="https://www.instagram.com/eowhasfa/" target="_blank" rel="noopener noreferrer">Instagram</a></li>
<li><a href="https://www.linkedin.com/in/james-rommel-lobaton-549b3720b/" target="_blank" rel="noopener noreferrer">LinkedIn</a></li>
</ul>
<hr>
<p><em>This is part of our Artist Spotlight series. If you&#39;re a game asset creator and want to be featured, get in touch at <a href="mailto:mark@assethoard.com">mark@assethoard.com</a>.</em></p>
]]></content:encoded>
		</item>
		<item>
			<title>Top Free 2D Game Assets in 2026</title>
			<link>https://assethoard.com/blog/top-free-2d-game-assets-2026</link>
			<guid isPermaLink="true">https://assethoard.com/blog/top-free-2d-game-assets-2026</guid>
			<pubDate>Sun, 13 Sep 2026 00:00:00 GMT</pubDate>
			<dc:creator>The AssetHoard Team</dc:creator>
			<category>Guides</category>
			<description>Our running roundup of the best free 2D asset packs for game developers and creative professionals, kept up to date through 2026.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/top-free-2d-game-assets-2026.png" alt="Top Free 2D Game Assets in 2026" /></p>
<p>Free 2D game assets are everywhere, but the ones you can actually ship are harder to find. Half the packs you come across are free to download and not free to use, and the licence is usually buried three clicks deep or missing entirely. This is our running roundup of the free 2D game asset sources we keep coming back to, updated through 2026 (last refreshed September 2026).</p>
<p>A quick word before the list: free does not mean unrestricted. Most of these allow commercial use, but the exact terms vary by site and sometimes by individual asset, so treat every link below as a starting point and confirm the licence before you put anything in a build you intend to sell.</p>
<p>If you&#39;d rather skip the hunt, we keep a <a href="https://assethoard.com/free-game-assets">curated directory of free CC0 assets</a>, filterable by type, style, and engine, with every licence checked so you can grab something and get back to building.</p>
<h2 id="start-with-the-classics">Start with the classics</h2><p>If you have never gone hunting for free assets before, start with the names every game developer already has bookmarked. These are the obvious, always-recommended ones, and they cover an enormous amount of ground on their own.</p>
<ul>
<li><a href="https://kenney.nl/assets" target="_blank" rel="noopener noreferrer">Kenney</a> - thousands of assets covering 2D sprites, tiles, and UI, plus 3D and audio, all released as CC0. Public domain, no attribution, commercial use fine. If you only ever use one source, make it this one.</li>
<li><a href="https://itch.io/game-assets/free" target="_blank" rel="noopener noreferrer">itch.io game assets</a> - the biggest indie marketplace has a deep free section full of sprite packs, tilesets, and UI kits. Licences are set by each creator, so read the terms on the page before downloading.</li>
<li><a href="https://opengameart.org/" target="_blank" rel="noopener noreferrer">OpenGameArt</a> - a long-running community library of free 2D and 3D art under a mix of open licences. Quality varies, but there are gems, and the licence is always stated on the asset page.</li>
</ul>
<p>The rest of this list covers the more specialist and less obvious sources worth knowing.</p>
<h2 id="what-we-looked-for">What we looked for</h2><ul>
<li>Genuinely free, not a paywalled &quot;free&quot; teaser for a paid pack</li>
<li>A licence you can actually read and live with, ideally allowing commercial use</li>
<li>Quality that holds up next to paid work</li>
<li>Formats you can drop straight into a 2D project (PNG sprites, SVG, tilesets)</li>
</ul>
<h2 id="at-a-glance">At a glance</h2><p>A quick comparison to help you filter. &quot;Commercial&quot; is whether you can use the assets in a paid or ad-supported game, and the licence column is a summary only, so always confirm the terms on the specific asset before you ship.</p>
<div class="table-scroll"><table>
<thead>
<tr>
<th>Source</th>
<th>Best for</th>
<th>Licence</th>
<th>Commercial</th>
</tr>
</thead>
<tbody><tr>
<td><a href="#start-with-the-classics">Kenney</a></td>
<td>Sprites, tiles, UI</td>
<td>CC0</td>
<td>Yes</td>
</tr>
<tr>
<td><a href="#start-with-the-classics">itch.io</a></td>
<td>Everything</td>
<td>Varies by creator</td>
<td>Usually</td>
</tr>
<tr>
<td><a href="#start-with-the-classics">OpenGameArt</a></td>
<td>Community 2D and 3D</td>
<td>CC0, CC BY, GPL</td>
<td>Varies</td>
</tr>
<tr>
<td><a href="#pixabay-2d-games">Pixabay</a></td>
<td>Stock backgrounds, textures</td>
<td>Pixabay Licence</td>
<td>Yes, with limits</td>
</tr>
<tr>
<td><a href="#gamedev-market-free-2d-backgrounds">GameDev Market</a></td>
<td>Backgrounds, scene art</td>
<td>Per asset</td>
<td>Varies</td>
</tr>
<tr>
<td><a href="#super-game-asset-free-assets">Super Game Asset</a></td>
<td>RPG and skill icons</td>
<td>Per asset (samples)</td>
<td>Check terms</td>
</tr>
<tr>
<td><a href="#unlucky-studio-free-game-art">Unlucky Studio</a></td>
<td>Sprites, UI, icons</td>
<td>Per pack</td>
<td>Yes</td>
</tr>
<tr>
<td><a href="#svg-repo">SVG Repo</a></td>
<td>Vector icons</td>
<td>CC0, MIT, CC BY</td>
<td>Varies</td>
</tr>
<tr>
<td><a href="#game-icons-net">Game-icons.net</a></td>
<td>Game and ability icons</td>
<td>CC BY 3.0</td>
<td>Yes, with credit</td>
</tr>
<tr>
<td><a href="#reiners-tilesets">Reiner&#39;s Tilesets</a></td>
<td>Sprites, textures</td>
<td>Site licence</td>
<td>Yes</td>
</tr>
<tr>
<td><a href="#clip-studio-assets">Clip Studio Assets</a></td>
<td>Brushes, tones, props</td>
<td>Per asset</td>
<td>Varies</td>
</tr>
<tr>
<td><a href="#square-assets-free-collection">Square Assets</a></td>
<td>Clean 2D sets</td>
<td>Per item</td>
<td>Varies</td>
</tr>
<tr>
<td><a href="#pngtree-2d-assets">Pngtree</a></td>
<td>Stock PNGs</td>
<td>Free tier</td>
<td>Gated to paid</td>
</tr>
<tr>
<td><a href="#gameart2d-freebies">GameArt2D</a></td>
<td>Sprites, tilesets, GUI</td>
<td>CC0</td>
<td>Yes</td>
</tr>
<tr>
<td><a href="#craftpix-freebies">CraftPix</a></td>
<td>Sprites, GUI, backgrounds</td>
<td>CraftPix free licence</td>
<td>Yes, no file resale</td>
</tr>
</tbody></table></div>
<h2 id="the-picks">The picks</h2><h3 id="pixabay-2d-games"><img class="site-logo" src="https://assethoard.com/blog/2026/top-free-2d-free-game-assets/pixabay.png" alt="" /> Pixabay 2D games</h3><p>A broad stock library that can fill gaps for backgrounds, textures, and reference art. The Pixabay Content Licence is generous: no attribution required and commercial use allowed, though you cannot sell unmodified content on its own, and anything featuring recognisable brands or people is off limits for commercial work. Pixabay has also had issues with copyright and AI-generated content slipping into the library, so double-check the source of anything before you use it.</p>
<p>Link: <a href="https://pixabay.com/images/search/2d%20games/" target="_blank" rel="noopener noreferrer">Pixabay 2D games</a></p>
<h3 id="gamedev-market-free-2d-backgrounds"><img class="site-logo" src="https://assethoard.com/blog/2026/top-free-2d-free-game-assets/gamedev-market.png" alt="" /> GameDev Market free 2D backgrounds</h3><p>GameDev Market is a paid marketplace with a rotating free section, and its background packs are a good source of parallax layers and scene art. Licensing is set per asset rather than site-wide, and some free downloads sit behind a Pro membership, so open the asset page and read its licence panel before you commit to using it in a project.</p>
<p>Link: <a href="https://www.gamedevmarket.net/category/2d/backgrounds?orderby=recent&pricing=free&genre=&min_price=0&max_price=50&pro_seller=" target="_blank" rel="noopener noreferrer">GameDev Market free 2D backgrounds</a></p>
<h3 id="super-game-asset-free-assets"><img class="site-logo" src="https://assethoard.com/blog/2026/top-free-2d-free-game-assets/super-game-asset.png" alt="" /> Super Game Asset free assets</h3><p>Best known for its polished RPG item and skill icons. The free section is mostly sample sets offered as a taste of the paid collections, downloaded through a free account. The art quality is high, but because these are samples, read the site&#39;s licensing FAQ so you are clear on where the free tier ends and a purchase begins.</p>
<p>Link: <a href="https://www.supergameasset.com/free-game-assets" target="_blank" rel="noopener noreferrer">Super Game Asset free assets</a></p>
<h3 id="unlucky-studio-free-game-art"><img class="site-logo" src="https://assethoard.com/blog/2026/top-free-2d-free-game-assets/unlucky-studio.png" alt="" /> Unlucky Studio free game art</h3><p>A well-organised stash of 2D art covering character sprites with animation, UI kits, backgrounds, weapon packs, RPG item icons, fantasy monsters, and vehicles. The studio states its free downloads can be used commercially, though attribution expectations can differ from one pack to the next, so check the individual post you are downloading from.</p>
<p>Link: <a href="https://unluckystudio.com/category/freegameart/" target="_blank" rel="noopener noreferrer">Unlucky Studio free game art</a></p>
<h3 id="svg-repo"><img class="site-logo" src="https://assethoard.com/blog/2026/top-free-2d-free-game-assets/svgrepo.png" alt="" /> SVG Repo</h3><p>A huge searchable library of vector icons and illustrations, useful well beyond games for menus, tools, and marketing. The catch worth knowing is that assets come under a mix of licences (CC0, MIT, CC BY, and others), and each entry is tagged individually. Filter by licence and check the one on the asset you want, because &quot;free to download&quot; here does not automatically mean attribution-free.</p>
<p>Link: <a href="https://www.svgrepo.com/" target="_blank" rel="noopener noreferrer">SVG Repo</a></p>
<h3 id="game-icons-net"><img class="site-logo" src="https://assethoard.com/blog/2026/top-free-2d-free-game-assets/game-icons.png" alt="" /> Game-icons.net</h3><p>The first place to look for UI and ability icons. It hosts over 4,000 game icons covering weapons, creatures, buildings, status effects, and abstract symbols, all available as both SVG and PNG with colour variations bundled in. The whole collection is CC BY 3.0, so commercial use is fine as long as you credit the authors. The vector format means you can recolour and scale everything to match your HUD without quality loss.</p>
<p>Link: <a href="https://game-icons.net/" target="_blank" rel="noopener noreferrer">Game-icons.net</a></p>
<h3 id="reiners-tilesets"><img class="site-logo" src="https://assethoard.com/blog/2026/top-free-2d-free-game-assets/reiners-tilesets.png" alt="" /> Reiner&#39;s Tilesets</h3><p>A veteran resource that has been giving away game art for decades. You will find 2D sprites (animals, monsters, buildings, vehicles), a large set of 3D models, and close to 300 tiling textures for walls, ground, wood, and stone. Reiner has long offered these on generous free-to-use terms including commercial projects, but the exact conditions live on the site&#39;s licence page, so read them before shipping.</p>
<p>Link: <a href="https://www.reinerstilesets.de/" target="_blank" rel="noopener noreferrer">Reiner&#39;s Tilesets</a></p>
<h3 id="clip-studio-assets"><img class="site-logo" src="https://assethoard.com/blog/2026/top-free-2d-free-game-assets/clip-studio.png" alt="" /> Clip Studio Assets</h3><p>The asset marketplace built into Clip Studio Paint, full of brushes, textures, tones, 3D props, and pose references. It is the right place to look if you create your art in Clip Studio, since much of it is designed to be used inside the app. If you plan to use assets elsewhere, check the individual asset&#39;s terms, as usability outside Clip Studio Paint is not guaranteed.</p>
<p>Link: <a href="https://assets.clip-studio.com/en-us" target="_blank" rel="noopener noreferrer">Clip Studio Assets</a></p>
<h3 id="square-assets-free-collection"><img class="site-logo" src="https://assethoard.com/blog/2026/top-free-2d-free-game-assets/square-assets.png" alt="" /> Square Assets free collection</h3><p>A small game-art store with a free collection sitting alongside its paid packs. Worth a look for clean, consistent 2D sets, but because it is a storefront, the free items each carry their own terms. Read the licence on the item page before downloading.</p>
<p>Link: <a href="https://square-assets.com/collection/free" target="_blank" rel="noopener noreferrer">Square Assets free collection</a></p>
<h3 id="pngtree-2d-assets"><img class="site-logo" src="https://assethoard.com/blog/2026/top-free-2d-free-game-assets/pngtree.png" alt="" /> Pngtree 2D assets</h3><p>An enormous general-purpose library of PNGs and graphics with a deep 2D search. Treat it with caution: the free tier typically requires attribution and has daily download limits, full commercial rights are often gated behind a paid plan, and like any large stock site, the occasional mislabelled or AI-generated item slips through. Verify the source and licence of anything you pull from here.</p>
<p>Link: <a href="https://pngtree.com/so/2d-assets" target="_blank" rel="noopener noreferrer">Pngtree 2D assets</a></p>
<h3 id="gameart2d-freebies"><img class="site-logo" src="https://assethoard.com/blog/2026/top-free-2d-free-game-assets/gameart2d.png" alt="" /> GameArt2D freebies</h3><p>A tidy set of ready-to-use 2D game art: character sprites (a platformer plumber, ninjas, zombies, a knight, and more), themed tilesets covering platformer, winter, desert, sci-fi, and graveyard, and a range of GUI packs. The free assets are released as CC0, so there are no restrictions and no attribution, and they are fine for prototyping, game jams, and commercial projects alike.</p>
<p>Link: <a href="https://www.gameart2d.com/freebies.html" target="_blank" rel="noopener noreferrer">GameArt2D freebies</a></p>
<h3 id="craftpix-freebies"><img class="site-logo" src="https://assethoard.com/blog/2026/top-free-2d-free-game-assets/craftpix.png" alt="" /> CraftPix freebies</h3><p>One of the largest free 2D libraries around, with sprites, tilesets, GUI, icons, backgrounds, and full game kits added regularly. A free account is needed to download. Commercial use is allowed with no attribution required, but you cannot redistribute or resell the raw art files, and the licence forbids using the assets to train AI or machine-learning systems.</p>
<p>Link: <a href="https://craftpix.net/freebies/" target="_blank" rel="noopener noreferrer">CraftPix freebies</a></p>
<h2 id="a-note-on-licences">A note on licences</h2><p>This is the part that trips people up. Free does not always mean unrestricted, and the difference between &quot;CC BY&quot; and &quot;free for personal use only&quot; is the difference between a safe launch and a takedown notice. Before you ship, confirm three things for every asset: is commercial use allowed, is attribution required, and can you modify it. Write the answer down somewhere that stays attached to the file, not in a browser tab you will lose by next week.</p>
<p>This is exactly the problem AssetHoard is built to solve. Every asset carries its own licence field, and when you import, AssetHoard will try to detect a bundled licence file and fill it in for you, with a manual override when it gets it wrong. The terms travel with the asset instead of living in your memory, so six months from now you still know whether that icon pack needs a credit line.</p>
<h2 id="wrapping-up">Wrapping up</h2><p>That is the current list. We keep this page updated as sources come and go, so bookmark it and check back. When you have pulled a few packs together, <a href="https://assethoard.com/downloads">download AssetHoard</a> to keep them organised and their licences on record before the collection gets away from you.</p>
]]></content:encoded>
		</item>
		<item>
			<title>You bought the bundle. Now find one tree.</title>
			<link>https://assethoard.com/blog/you-bought-the-bundle</link>
			<guid isPermaLink="true">https://assethoard.com/blog/you-bought-the-bundle</guid>
			<pubDate>Mon, 31 Aug 2026 00:00:00 GMT</pubDate>
			<dc:creator>Mark Gandolfo</dc:creator>
			<category>Guides</category>
			<description>Humble, itch.io and Fanatical asset bundles are the cheapest way to build a game asset library and the fastest way to lose one. Here is how to keep yours findable.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/2026-08-you-bought-the-bundle.png" alt="You bought the bundle. Now find one tree." /></p>
<p><a href="https://assethoard.com/blog/2026/2026-08-you-bought-the-bundle.png" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/2026-08-you-bought-the-bundle.png" alt="A stack of plain cardboard boxes piled against a warm brown wall, illustrating an asset bundle you can't see inside" title="You bought the bundle. Now find one tree." width="1600" height="1474" loading="eager" decoding="async"></a></p>
<p>A bundle turns up on Humble for twelve dollars: forty asset packs, a couple of hundred thousand files between them. You buy it without thinking twice, because a single character pack at full price would cost more than the whole thing. That maths holds up. I&#39;ve never met anyone who regretted the purchase.</p>
<p>What people regret is the Tuesday six weeks later, when they need one stylised tree for a forest scene and know for a fact they own about nine hundred of them, somewhere.</p>
<h2 id="what-actually-lands-on-your-drive">What actually lands on your drive</h2><p>When the bundle unlocks you get forty or fifty zip files, named however each creator felt like naming them. <code>LowPolyNature_v2_FINAL.zip</code>. <code>pack3.zip</code>. <code>Kenney_Assets.zip</code>, which is 140,000 files on its own. One has a <code>.unitypackage</code> in it and nothing else. Another is raw <code>.fbx</code> and <code>.png</code>. A third has a Godot addon folder, a set of <code>.uasset</code> files, and a readme explaining which is which. Two of them are the same assets from the same artist, uploaded twice under different version numbers.</p>
<p>Nothing shares a structure. One creator sorts by biome, another by polygon count, a third tips everything into an <code>Assets/</code> folder and leaves it there. Forty packs, forty ideas about how a library should be laid out, and none of them match yours.</p>
<h2 id="why-folders-dont-cut-it-here">Why folders don&#39;t cut it here</h2><p>For your own project files, a folder structure works fine. For a bundle haul it doesn&#39;t, and the reason is simple: you can&#39;t see into a zip without opening it.</p>
<p>To find out whether <code>pack3.zip</code> has the tree you want, you unzip it and look. Do that fifty times and you&#39;ve lost an afternoon. So most people open two or three, take whatever is close enough, and leave the rest sealed. The bundle becomes a folder you feel slightly guilty about every time you scroll past it.</p>
<p>The packs you do unzip cause the opposite problem. Now there are 200,000 loose files, your file explorer stalls trying to draw thumbnails, and searching by name only helps if you already remember what the artist called the thing. <code>tree_04_var_b.fbx</code> isn&#39;t much of a search term.</p>
<p>A better default is to <a href="https://assethoard.com/blog/look-inside-archives-without-unzipping">index the archives without extracting them</a>: read the manifest, pull out the previews, leave the zip where it is. The haul stays compressed on disk and still becomes searchable.</p>
<h2 id="the-engine-problem">The engine problem</h2><p>This is the bit that trips people up, and most advice skips it because most advice assumes you only work in Unity.</p>
<p>Plenty of us don&#39;t. You might prototype in Godot, take a contract in Unreal, still have a GameMaker project from last year, and get Blender files from an artist friend. So the same tree can sit in your library as a bare <code>.fbx</code> in one pack, wrapped in a <code>.unitypackage</code> in another, as a <code>.tres</code> resource in a Godot addon, and as a <code>.uasset</code> you can&#39;t open outside the editor that made it.</p>
<p>Four formats, one tree, and most search tools understand none of them. Unity-only tools read the <code>.unitypackage</code> and ignore the rest. Generic file browsers treat the four as unrelated blobs. So you end up buying assets you already own, because you had no way to tell you owned them.</p>
<p>What helps is a catalogue that reads the formats properly: it opens a <code>.unitypackage</code>, walks a Godot <code>.tres</code> <a href="https://assethoard.com/blog/parsing-godot-tres-files">resource graph</a>, handles <code>.yymps</code> and <code>.uasset</code>, and files all of them as the same kind of thing. The engine that wrapped the tree stops mattering.</p>
<h2 id="what-findable-actually-means">What &quot;findable&quot; actually means</h2><p>Once you&#39;re a few thousand assets in, &quot;organised&quot; isn&#39;t really the goal any more. Findable is, and it comes down to four things.</p>
<p>Seeing it. A cached thumbnail, generated once. Most asset hunting is visual anyway; you rarely remember the name, but you remember what it looked like.</p>
<p>Describing it. Name search fails because you&#39;re searching your memory of the asset, not the artist&#39;s naming scheme. <a href="https://assethoard.com/semantic-search">Semantic search over the previews</a> lets you type &quot;gnarled dead tree&quot; and find it even when the file is called <code>T_04b</code>.</p>
<p>Narrowing it. Tags you picked, rather than the folder someone else picked. The same asset can sit under &quot;trees&quot;, &quot;stylised&quot;, &quot;mobile-safe&quot; and &quot;that Humble bundle&quot; at once.</p>
<p>Shipping it. The <a href="https://assethoard.com/blog/game-asset-licences-explained">licence</a> travelling with the asset, instead of sitting in a readme inside a zip you&#39;ve since deleted. CC0, CC-BY with attribution, the Asset Store standard licence. It&#39;s easy to ignore until the day you ship commercially, and then it matters a great deal.</p>
<h2 id="a-quick-pass-for-a-new-bundle">A quick pass for a new bundle</h2><p>Before you open a project, try this.</p>
<ol>
<li>Download the lot into one folder. Don&#39;t unzip, don&#39;t sort.</li>
<li>Point your catalogue at the folder and let it index, overnight if it needs to. Fifty opaque zips become a set of previews you can actually look through.</li>
<li>Skim the results once, quickly. You&#39;re not organising, just getting a rough sense of what came in.</li>
<li>Tag the standouts and nothing else. Twenty minutes, maybe thirty assets. The rest stay findable by search, which is enough.</li>
<li>Flag anything with an unusual licence. It&#39;s the one step that gets expensive if you skip it.</li>
</ol>
<p>No folder hierarchy, no naming convention, no promise to sort it properly at the weekend. A bundle is cheap and broad, and that only pays off if you can search it.</p>
<h2 id="the-real-cost">The real cost</h2><p>The bundle cost twelve dollars, so it feels like it cost twelve dollars. It didn&#39;t. It also cost the twenty minutes at the start of a session spent hunting for something you own, the asset you bought a second time at full price because you&#39;d forgotten, and the scene you built with a placeholder cube because finding the real prop was more hassle than shipping the cube.</p>
<p>An asset you can&#39;t find isn&#39;t doing much for you. It&#39;s just disk space.</p>
<hr>
<p><a href="https://assethoard.com/downloads">AssetHoard</a> is a local-first desktop asset manager built for exactly this pile. It <a href="https://assethoard.com/archive">indexes archives without unpacking them</a>, reads <a href="https://assethoard.com/unity-asset-manager">Unity</a>, <a href="https://assethoard.com/godot-asset-manager">Godot</a>, Unreal and <a href="https://assethoard.com/gamemaker-asset-manager">GameMaker</a> formats as first-class citizens, generates previews, and lets you <a href="https://assethoard.com/semantic-search">search by what things look like</a> rather than what they were named. It runs <a href="https://assethoard.com/local-first">entirely on your machine</a>, and it&#39;s a one-time purchase, not a subscription.</p>
<p>The next bundle you buy is only cheap if you can find what&#39;s in it. <a href="https://assethoard.com/downloads">Download AssetHoard</a> and point it at the pile.</p>
<p class="photo-credit">Hero photo by <a href="https://unsplash.com/@kseegars">Kadarius Seegars</a> on <a href="https://unsplash.com/photos/cardboard-boxes-against-brown-background-DevJkLB3hWE">Unsplash</a>.</p>
]]></content:encoded>
		</item>
		<item>
			<title>Unreal vs Unity: which engine fits your game?</title>
			<link>https://assethoard.com/blog/unreal-vs-unity</link>
			<guid isPermaLink="true">https://assethoard.com/blog/unreal-vs-unity</guid>
			<pubDate>Wed, 19 Aug 2026 07:23:36 GMT</pubDate>
			<dc:creator>Mark Gandolfo</dc:creator>
			<category>Guides</category>
			<description>Unreal vs Unity, compared for indie developers in 2026. Visual fidelity, 2D and mobile, iteration speed, pricing and royalties, plus who each engine suits.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/2026-08-unreal-vs-unity.jpg" alt="Unreal vs Unity: which engine fits your game?" /></p>
<p><a href="https://assethoard.com/blog/2026/2026-08-unreal-vs-unity.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/2026-08-unreal-vs-unity.jpg" alt="A silhouetted signpost pointing different ways against a sunset sky, illustrating the choice between two game engines" title="Unreal vs Unity" width="1200" height="800" loading="eager" decoding="async"></a></p>
<p>Where <a href="https://assethoard.com/blog/godot-vs-unity">Godot vs Unity</a> is a fight about lightness and ownership, Unreal vs Unity is a fight about ambition and scale. These are the two engines most likely to power something with a big 3D world, and they pull in noticeably different directions.</p>
<p>If you are still deciding whether either belongs on your list at all, the <a href="https://assethoard.com/blog/what-game-engine-should-i-start-with">first-engine guide</a> is the better starting point. If it&#39;s these two on the table, here is how they actually compare.</p>
<h2 id="the-short-version">The short version</h2><p><strong>Unreal</strong> is the fidelity powerhouse, the engine studios reach for when they want photoreal lighting, vast detailed worlds, and visuals that make players ask whether they are watching a game or a film. <strong>Unity</strong> is the versatile all-rounder, lighter to run, faster to iterate in, and dominant on mobile and in 2D.</p>
<p>Pick Unreal for cutting-edge 3D and cinematic ambition. Pick Unity for mobile, 2D, rapid iteration, and a gentler road in. Now the detail.</p>
<h2 id="visual-fidelity">Visual fidelity</h2><p>This is Unreal&#39;s headline act. Its modern rendering feature set, including its dynamic global illumination and virtualised geometry systems, lets small teams produce visuals that used to require a large studio. Out of the box, for high-end 3D, it looks stunning.</p>
<p>Unity is very capable in 3D and its render pipelines have matured a great deal, but matching Unreal&#39;s top-end fidelity takes more manual effort. For photoreal or graphically ambitious work, Unreal starts you closer to the finish line.</p>
<p><strong>Edge:</strong> Unreal.</p>
<h2 id="iteration-speed-and-footprint">Iteration speed and footprint</h2><p>Unity is lighter. It installs smaller, opens faster, and its edit-play loop tends to feel snappier, which matters enormously when you are testing an idea for the hundredth time in an afternoon. That responsiveness is a real, daily productivity advantage, especially on modest hardware.</p>
<p>Unreal is a large engine with a heavier footprint, and its power comes with weight. On a capable machine it&#39;s fine; on an older laptop it can feel sluggish.</p>
<p><strong>Edge:</strong> Unity.</p>
<h2 id="scripting">Scripting</h2><p>Unreal offers two routes: Blueprints, a powerful visual scripting system you can build entire games in without writing code, and C++ for performance-critical or lower-level work. Blueprints are a real strength and lower the barrier for non-programmers, though C++ is a demanding language once you drop into it.</p>
<p>Unity uses C#, which sits in a comfortable middle ground: more approachable than C++, more transferable than a visual system, and backed by a huge body of learning material. For most solo developers, C# is the more forgiving day-to-day language.</p>
<p><strong>Edge:</strong> Unity for approachability, Unreal for the visual-scripting on-ramp and raw ceiling. Depends on how you like to work.</p>
<h2 id="2d-and-mobile">2D and mobile</h2><p>Unity is the clear choice here. It has mature 2D packages, the deepest mobile toolchain of any major engine, and by far the widest third-party support for the ads, analytics and monetisation that mobile games live on.</p>
<p>Unreal can do 2D and mobile, but it is swimming against its own current. Its whole design centre of gravity is high-fidelity 3D, and smaller or mobile projects usually ship leaner in Unity.</p>
<p><strong>Edge:</strong> Unity, decisively.</p>
<h2 id="ecosystem-and-assets">Ecosystem and assets</h2><p>Both have substantial marketplaces and large communities. Unity&#39;s Asset Store is broader and especially strong for 2D, mobile and mid-scale 3D. Unreal&#39;s marketplace skews toward high-end 3D content, and Epic has a history of giving away large quantities of professional assets to Unreal developers.</p>
<p>Call this one close, weighted by what you are making: Unity for breadth, Unreal for high-fidelity 3D content.</p>
<p><strong>Edge:</strong> Draw, project-dependent.</p>
<h2 id="pricing-and-royalties">Pricing and royalties</h2><p>The models differ in shape. Unreal is free to use and takes a royalty on gross game revenue above a threshold. Unity is free on its Personal tier and moves to paid subscriptions above revenue and funding limits.</p>
<p>Neither model is strictly cheaper; it depends on your revenue profile. And both companies have adjusted terms in recent years, so treat any specific figure you read, including here, as a prompt to check the current terms yourself before you commit.</p>
<p><strong>Edge:</strong> Depends on your numbers. Read the current terms.</p>
<h2 id="so-which-one">So which one?</h2><ul>
<li><strong>Choose Unreal if:</strong> you are building ambitious 3D, you want the best-looking visuals with the least manual effort, you like Blueprints, or you are aiming at the kind of fidelity studios ship.</li>
<li><strong>Choose Unity if:</strong> you are targeting mobile, you are doing 2D, you want faster iteration on lighter hardware, or you want a gentler entry into 3D.</li>
</ul>
<p>For a first project, be honest about scope. Unreal&#39;s ceiling is glorious, but a small game rarely needs it, and the weight can slow you down more than the fidelity helps. Many developers are better served starting lighter and reaching for Unreal when a project truly demands it.</p>
<h2 id="what-both-engines-have-in-common">What both engines have in common</h2><p>Whichever way you lean, the project will fill up with assets: models, textures, materials, audio, the professional packs both marketplaces hand out. That library is the part of your work that outlives the engine decision, because art and audio are just files while your Blueprints and C# are not.</p>
<p><a href="https://assethoard.com/downloads">AssetHoard</a> is a local-first asset manager that keeps that library previewable and organised in one place, sitting beside whichever engine you choose. It handles the models, materials and textures these 3D-heavy workflows generate, and reads native project formats from engines like <a href="https://assethoard.com/unity-asset-manager">Unity</a>, so your collection stays tidy no matter which tool you build in.</p>
<p>More in this series: <a href="https://assethoard.com/blog/godot-vs-unity">Godot vs Unity</a> and <a href="https://assethoard.com/blog/gamemaker-vs-godot">GameMaker vs Godot</a>.</p>
<hr>
<p><em>Mark</em></p>
<p class="photo-credit">Hero photo by <a href="https://unsplash.com/@soymeraki">Javier Allegue Barros</a> on <a href="https://unsplash.com/photos/silhouette-of-road-signage-during-golden-hour-C7B-ExXpOIE">Unsplash</a>.</p>
]]></content:encoded>
		</item>
		<item>
			<title>GameMaker vs Godot: the best engine for 2D?</title>
			<link>https://assethoard.com/blog/gamemaker-vs-godot</link>
			<guid isPermaLink="true">https://assethoard.com/blog/gamemaker-vs-godot</guid>
			<pubDate>Wed, 19 Aug 2026 07:02:34 GMT</pubDate>
			<dc:creator>Mark Gandolfo</dc:creator>
			<category>Guides</category>
			<description>GameMaker vs Godot, compared for 2D game development in 2026. Licensing, scripting, workflow, 3D and track record, plus which 2D engine you should pick.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/2026-08-gamemaker-vs-godot.jpg" alt="GameMaker vs Godot: the best engine for 2D?" /></p>
<p><a href="https://assethoard.com/blog/2026/2026-08-gamemaker-vs-godot.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/2026-08-gamemaker-vs-godot.jpg" alt="A black door and a wooden door side by side under twin arches, illustrating the choice between two 2D game engines" title="GameMaker vs Godot" width="1200" height="800" loading="eager" decoding="async"></a></p>
<p>The other comparisons in this series are 3D heavyweight bouts. This one is different. GameMaker and Godot are both superb 2D engines, and choosing between them is less about raw power and more about philosophy: pure specialism versus free-and-flexible.</p>
<p>If you are not yet sure a 2D-focused engine is what you want, the <a href="https://assethoard.com/blog/what-game-engine-should-i-start-with">first-engine guide</a> zooms out. If you have narrowed it to these two, let&#39;s settle it.</p>
<h2 id="the-short-version">The short version</h2><p><strong>GameMaker</strong> has spent decades doing one thing extremely well: 2D games. Its track record is absurd for its size, with Undertale, Hyper Light Drifter, Katana ZERO, Nuclear Throne and Hotline Miami all built in it. <strong>Godot</strong> is the free, open-source all-rounder with a first-class 2D pipeline that also happens to do 3D.</p>
<p>Pick GameMaker for focused 2D with the smoothest no-code-to-code ramp. Pick Godot for a free, open tool that won&#39;t box you into 2D forever. Now the detail.</p>
<h2 id="licensing-and-cost">Licensing and cost</h2><p>Godot is free and open source under the MIT licence. No tiers, no fees, no revenue share, no catch. You own it outright.</p>
<p>GameMaker offers a free tier to learn and build with, and paid options for commercial release and console export. Its pricing model has shifted more than once over the years, moving between subscription and other structures, so check the current terms before you plan a commercial launch.</p>
<p><strong>Edge:</strong> Godot for simplicity and permanence.</p>
<h2 id="2d-workflow">2D workflow</h2><p>This is the heart of the matchup, and it&#39;s a close one.</p>
<p>GameMaker&#39;s entire being is 2D. Its room editor, sprite tools and 2D-specific conveniences are refined by decades of focus, and the result is a workflow that just feels made for the job. For a lot of 2D developers, that specialism is exactly the appeal.</p>
<p>Godot&#39;s 2D is also first-class, built on a dedicated 2D renderer and node system rather than a 3D engine wearing a flat hat. It is flexible, clean, and extremely capable. There is no 2D game GameMaker can make that Godot cannot.</p>
<p><strong>Edge:</strong> Too close to call. GameMaker for refined 2D-specific polish, Godot for flexible 2D power.</p>
<h2 id="scripting">Scripting</h2><p>GameMaker gives you a drag-and-drop action system and its own language, GML. The pairing is one of the best beginner ramps anywhere: build logic visually to get moving, then graduate into GML when you want more control, all without switching tools.</p>
<p>Godot uses GDScript, a game-focused language that reads almost like plain English and is tightly woven into the engine. It skips the visual layer but is itself a very gentle first language, and Godot also supports C#.</p>
<p><strong>Edge:</strong> GameMaker for the visual-to-code ramp, Godot for a clean scripting-first experience. Your preference decides it.</p>
<h2 id="3d">3D</h2><p>Not really a contest, because they are aimed at different things. GameMaker is 2D by design; it has some limited 3D capability, but nobody chooses it to make a 3D game.</p>
<p>Godot is a full 3D engine as well, and its 3D took a major leap in the 4.x releases. If there is any chance your ambitions drift into three dimensions, Godot means you will not have to change tools to follow them.</p>
<p><strong>Edge:</strong> Godot, if 3D is ever on your horizon.</p>
<h2 id="track-record-and-community">Track record and community</h2><p>GameMaker&#39;s hall of fame is remarkable, and it is proof that a focused 2D tool can produce genre-defining hits in the hands of small teams. Its community and learning resources are mature and 2D-centric.</p>
<p>Godot&#39;s community is large, fast-growing and famously welcoming, its documentation is strong, and being open source it has an unusually engaged contributor base. Both are well supported; they simply attract slightly different crowds.</p>
<p><strong>Edge:</strong> Draw.</p>
<h2 id="so-which-one">So which one?</h2><ul>
<li><strong>Choose GameMaker if:</strong> you are certain you want 2D, you like the idea of starting with visual actions and easing into code, or you want a tool with a proven hit-making pedigree in your exact genre.</li>
<li><strong>Choose Godot if:</strong> you want a free and open toolchain, you might one day want 3D, or you prefer a clean scripting-first workflow with no licensing tiers to track.</li>
</ul>
<p>You can&#39;t go far wrong with either. Both are beginner-friendly, both ship real commercial games, and both respect a solo developer&#39;s time. If you want to hedge toward flexibility, lean Godot. If you want to commit fully to 2D craft, lean GameMaker.</p>
<h2 id="the-library-outlives-the-engine">The library outlives the engine</h2><p>Whichever you choose, you will gather a pile of assets: sprites, tilesets, sound effects, fonts, the packs you download and mean to use one day. That collection is the part of your work that survives any future engine change, because your art and audio are just files while your GML or GDScript is not.</p>
<p><a href="https://assethoard.com/downloads">AssetHoard</a> keeps that library previewable, searchable and organised in one place, sitting beside whichever engine you pick. It reads native project formats from both <a href="https://assethoard.com/gamemaker-asset-manager">GameMaker</a> and <a href="https://assethoard.com/godot-asset-manager">Godot</a>, previewing sprites, tilesets, sounds and fonts straight from your projects, so the same tidy library follows you whichever way this decision goes.</p>
<p>The rest of the series: <a href="https://assethoard.com/blog/godot-vs-unity">Godot vs Unity</a> and <a href="https://assethoard.com/blog/unreal-vs-unity">Unreal vs Unity</a>.</p>
<hr>
<p><em>Mark</em></p>
<p class="photo-credit">Hero photo by <a href="https://unsplash.com/@jakeculp">Jacob Culp</a> on <a href="https://unsplash.com/photos/black-and-brown-wooden-doors-F_hQqE6uN30">Unsplash</a>.</p>
]]></content:encoded>
		</item>
		<item>
			<title>Godot vs Unity: which should you actually pick?</title>
			<link>https://assethoard.com/blog/godot-vs-unity</link>
			<guid isPermaLink="true">https://assethoard.com/blog/godot-vs-unity</guid>
			<pubDate>Wed, 19 Aug 2026 06:03:04 GMT</pubDate>
			<dc:creator>Mark Gandolfo</dc:creator>
			<category>Guides</category>
			<description>Godot vs Unity, compared for indie developers in 2026. Licensing, 2D and 3D, scripting, the asset ecosystem and mobile, plus who each engine is really for.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/2026-08-godot-vs-unity.jpg" alt="Godot vs Unity: which should you actually pick?" /></p>
<p><a href="https://assethoard.com/blog/2026/2026-08-godot-vs-unity.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/2026-08-godot-vs-unity.jpg" alt="A dirt path forking into two through a green forest, illustrating the choice between two game engines" title="Godot vs Unity" width="1200" height="803" loading="eager" decoding="async"></a></p>
<p>This is the matchup that launches a thousand forum threads, and most of them generate more heat than light. So let&#39;s do it properly: no tribalism, no &quot;Unity bad&quot; or &quot;Godot cope&quot;, just a clear look at where each engine actually earns its place.</p>
<p>If you haven&#39;t yet decided whether you even want these two on the shortlist, start with the broader <a href="https://assethoard.com/blog/what-game-engine-should-i-start-with">guide to picking a first engine</a>. If Godot and Unity are already your two finalists, read on.</p>
<h2 id="the-short-version">The short version</h2><p><strong>Godot</strong> is the lightweight, free, open-source challenger that has spent the last few years turning from &quot;promising&quot; into &quot;actually good&quot;. <strong>Unity</strong> is the established heavyweight with the biggest ecosystem in the business and a decade of industry adoption behind it.</p>
<p>Pick Godot if you value owning your tools, you want the simplest 2D workflow, or you want the friendliest possible on-ramp. Pick Unity if you need its enormous asset and tutorial ecosystem, you are building anything ambitious in 3D, you are targeting mobile at scale, or you want skills for a studio job. Now the detail.</p>
<h2 id="licensing-and-cost">Licensing and cost</h2><p>This is the cleanest difference, so we&#39;ll get it out of the way first.</p>
<p>Godot is free and open source under the MIT licence. There is no revenue share, no per-seat fee, no runtime charge, and no threshold at which it starts costing you money. You own your copy of the engine outright, source included.</p>
<p>Unity has a free Personal tier for developers under a revenue and funding threshold, and paid subscription tiers above it. The technology is excellent, but it is worth remembering that Unity spent 2023 announcing a per-install runtime fee that it later walked back after significant backlash. The fee is gone, but the episode is a fair reminder that a company-owned engine can change its terms in ways an open-source one cannot.</p>
<p><strong>Edge:</strong> Godot, comfortably, if predictable licensing matters to you.</p>
<h2 id="2d">2D</h2><p>Godot&#39;s 2D is not a 3D engine with a flat camera bolted on. It has a dedicated 2D renderer and node system, pixel-perfect tooling, and a workflow that feels purpose-built, so you can be productive on a straightforward 2D game very quickly.</p>
<p>Unity&#39;s 2D is stronger than its old reputation suggests. It has a mature 2D toolset, a real 2D lighting system with normal maps and shadows, and it can bring lit 3D meshes into a 2D scene for depth and dynamic lighting that flat sprites cannot easily fake. That opens up looks Godot makes you work harder for.</p>
<p><strong>Edge:</strong> Narrow, and it depends on the game. Godot for the simplest, most direct 2D workflow; Unity if you want advanced 2D lighting or to blend 2D and 3D. You make a call on what you&#39;re after.</p>
<h2 id="3d">3D</h2><p>Unity wins 3D outright, and it&#39;s not close. It has built-in terrain sculpting, mature mesh handling and in-editor modelling with ProBuilder, a deep animation stack with Timeline and Cinemachine for cinematics, face and motion capture through Live Capture, and high-fidelity rendering with HDRP. On top of all that sits the largest library of ready-made 3D assets and tutorials of any engine. For anything ambitious in three dimensions, that toolset is a real head start.</p>
<p>Godot&#39;s 3D took a big step forward in the 4.x releases, with a rebuilt renderer, global illumination and better tooling, and it can comfortably ship a commercial 3D game, especially a stylised or smaller-scope one. But the depth is not there yet: several of those Unity systems are plugins, manual work, or simply absent in Godot.</p>
<p><strong>Edge:</strong> Unity, decisively.</p>
<h2 id="lighting-post-processing-and-shaders">Lighting, post-processing and shaders</h2><p>If visual polish matters to you, this is worth a closer look, and it mostly favours Unity.</p>
<p>On lighting and post-processing Unity is well ahead, especially through its High Definition Render Pipeline. You get volumetric lighting and fog, screen-space reflections, ray-traced options, and a Volume-based post-processing stack (bloom, colour grading, depth of field, motion blur, ambient occlusion and more) that artists can tune without touching code. Godot 4 is no slouch, with real-time global illumination through SDFGI, baked lightmaps, volumetric fog, glow and tonemapping in its Environment settings, but the range of effects and the polish of the controls do not match Unity&#39;s.</p>
<p>Shaders are the closer contest. Both engines let you hand-write shaders, and both ship a visual, node-based shader editor, so the core capability is comparable. Godot&#39;s shading language is clean and well documented, and plenty of people prefer it. Unity pulls ahead on the maturity of its Shader Graph and, again, the sheer volume of ready-made shaders and effects on the Asset Store.</p>
<p><strong>Edge:</strong> Unity for lighting and post-processing, clearly. Shaders are closer to a draw, with Unity ahead on tooling and the asset library.</p>
<h2 id="scripting">Scripting</h2><p>Godot&#39;s built-in language, GDScript, is designed for game development and reads almost like plain English. It&#39;s a forgiving first language, and its tight integration with the engine makes iteration fast. You can also use C# in Godot if you prefer, with one notable catch: C# projects cannot export to the web yet, whereas GDScript can.</p>
<p>Unity uses C#, a mainstream, general-purpose language that looks good on a CV and transfers directly to other software work. It is more verbose than GDScript and has a slightly steeper learning curve, but the payoff is broader applicability.</p>
<p><strong>Edge:</strong> Godot for approachability, Unity for transferable career skills. Call it a draw that depends on your goals.</p>
<h2 id="editor-extensibility">Editor extensibility</h2><p>Both engines let you script the editor itself, not just the game, and this is one of Unity&#39;s quieter strengths. Its editor scripting API is deep: you can build custom windows, inspectors, property drawers and full in-editor tools, with two UI frameworks to build them in, the older IMGUI and the newer UI Toolkit. The Asset Store is then full of editor extensions built exactly this way, so a lot of the tooling you might want already exists off the shelf.</p>
<p>Godot has a proper plugin system too, and it is often underrated. Scripts marked with <code>@tool</code> run inside the editor, and <code>EditorPlugin</code> lets you add custom docks, bottom panels, inspectors and gizmos. Because the whole editor is open source, you can even fork and recompile it, which is a kind of editability Unity does not offer at all. What Godot lacks is the sheer API surface and the marketplace of ready-made editor tools that Unity has spent a decade building.</p>
<p><strong>Edge:</strong> Unity, for the depth of its editor API and the ecosystem of existing extensions. Godot&#39;s plugin system is capable and its open editor is uniquely moddable, but the tooling ecosystem is far smaller.</p>
<h2 id="the-ecosystem">The ecosystem</h2><p>Here Unity wins decisively, and it is the single strongest reason to choose it. The Unity Asset Store is deep and battle-tested, almost any &quot;how do I do X&quot; already has a YouTube answer, and studios list Unity by name in job adverts more than any other engine. When you hit a wall, the odds that someone has already documented the way through it are simply higher.</p>
<p>Godot&#39;s community is smaller but famously friendly, its documentation is solid, and its asset library grows every year. For a beginner it rarely bites, but on a complex project the ecosystem gap is real.</p>
<p><strong>Edge:</strong> Unity.</p>
<h2 id="mobile">Mobile</h2><p>Both engines export to iOS and Android. Unity has the deeper mobile story: more mature build tooling, better-trodden performance-optimisation paths, and far more third-party support for ads, analytics and monetisation. If mobile at commercial scale is your target, Unity is the safer bet today.</p>
<p><strong>Edge:</strong> Unity.</p>
<h2 id="so-which-one">So which one?</h2><ul>
<li><strong>Choose Godot if:</strong> you want the simplest 2D workflow, you are learning to code, you want a small fast tool, or you want a toolchain nobody can change the price of.</li>
<li><strong>Choose Unity if:</strong> you need its ecosystem, you are targeting mobile seriously, you want job-transferable C# skills, or you are building an ambitious 3D project and want the most assets and tutorials to lean on.</li>
</ul>
<p>And if you truly can&#39;t decide, download Godot this afternoon. It costs nothing, installs in seconds, and you&#39;ll learn more from an hour of building than from a week of comparison tables like this one.</p>
<h2 id="the-part-that-survives-whichever-you-pick">The part that survives whichever you pick</h2><p>Whichever engine wins your shortlist, one thing is identical in both: you will accumulate assets. Sprites, models, audio, fonts, texture packs, the free bundles you grab and mean to use later. That pile grows fast, and it is the one part of your project that carries across unchanged if you ever switch engines, because assets are just files while code is not.</p>
<p><a href="https://assethoard.com/downloads">AssetHoard</a> is a local-first asset manager that sits beside either engine and keeps that library previewable, searchable and organised in one place. It reads native project formats from both <a href="https://assethoard.com/godot-asset-manager">Godot</a> and <a href="https://assethoard.com/unity-asset-manager">Unity</a>, so the same library works no matter which side of this debate you land on, or if you change your mind later.</p>
<p>Next in the series: <a href="https://assethoard.com/blog/unreal-vs-unity">Unreal vs Unity</a> and <a href="https://assethoard.com/blog/gamemaker-vs-godot">GameMaker vs Godot</a>.</p>
<hr>
<p><em>Mark</em></p>
<p class="photo-credit">Hero photo by <a href="https://unsplash.com/@madebyjens">Jens Lelie</a> on <a href="https://unsplash.com/photos/two-roads-between-trees-u0vgcIOQG08">Unsplash</a>.</p>
]]></content:encoded>
		</item>
		<item>
			<title>What game engine should I start with?</title>
			<link>https://assethoard.com/blog/what-game-engine-should-i-start-with</link>
			<guid isPermaLink="true">https://assethoard.com/blog/what-game-engine-should-i-start-with</guid>
			<pubDate>Wed, 19 Aug 2026 02:32:30 GMT</pubDate>
			<dc:creator>Mark Gandolfo</dc:creator>
			<category>Guides</category>
			<description>The best game engine for beginners in 2026, explained simply. How to choose between Godot, Unity, Unreal, GameMaker and the no-code tools for your first game.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/2026-08-what-game-engine-should-i-start-with.jpg" alt="What game engine should I start with?" /></p>
<p><a href="https://assethoard.com/blog/2026/2026-08-what-game-engine-should-i-start-with.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/2026-08-what-game-engine-should-i-start-with.jpg" alt="A pile of classic game controllers, including PlayStation, NES and SNES pads, evoking the choice of a first game engine" title="What game engine should I start with?" width="1600" height="1067" loading="eager" decoding="async"></a></p>
<p>It is the first question almost everyone asks, and it arrives loaded with more anxiety than it deserves. Choosing a game engine feels like choosing a tattoo. Permanent, public, and destined to be judged by strangers on the internet.</p>
<p>But it&#39;s not a tattoo. It&#39;s a pair of boots. You want ones that fit the terrain you&#39;re walking, they&#39;ll wear in over time, and if you truly hate them you can swap them for another pair without starting your life over. Every engine below has shipped games you&#39;ve heard of. None of them will stop you making something good.</p>
<p>So instead of asking &quot;which engine is best&quot;, ask three smaller questions that actually have answers: <strong>what am I making</strong>, <strong>where will it run</strong>, and <strong>how do I like to work</strong>. Everything else follows from those.</p>
<h2 id="the-three-questions-that-matter">The three questions that matter</h2><p><strong>What am I making?</strong> A cosy 2D farming game and a first-person 3D horror game pull toward very different tools. 2D and 3D are the first fork in the road, and picking the engine built for your dimension will save you months of fighting the grain.</p>
<p><strong>Where will it run?</strong> A game aimed at phones, consoles or the browser leans on very different tooling from a desktop-only one. If you already know you want to ship to mobile or the web, weight that heavily, because export support and performance on your target platform vary a lot from one engine to the next.</p>
<p><strong>How do I like to work?</strong> Some people are happy in a code editor and want a real scripting language from day one. Some people think in flowcharts and want to wire up logic visually. Some people want to write as little code as humanly possible and just ship. There&#39;s no wrong answer here. It&#39;s about matching how you think to what the tool asks of you.</p>
<p>Hold those three answers in your head as you read the rundown below.</p>
<h2 id="the-engines-one-by-one">The engines, one by one</h2><h3 id="godot">Godot</h3><p>The one I recommend to most people starting out. <a href="https://godotengine.org" target="_blank" rel="noopener noreferrer">Godot</a> is free and open source, with no account, no revenue share, no runtime fee, no strings. It&#39;s a small download, it opens in seconds, and its scene-and-node model is one of the cleanest mental models in the business.</p>
<p>Its 2D support is first-class rather than an afterthought bolted onto a 3D engine, and its 3D has come on enormously in the 4.x releases. GDScript, its built-in language, reads almost like plain English and is a kind first programming language. You can also use C# if you want something more career-transferable.</p>
<p>The trade-off is ecosystem size. There are fewer paid plugins, fewer ready-made asset packs, and a smaller (though very friendly) tutorial pile than Unity has. For a beginner, that gap rarely bites. If you are weighing the two head to head, my <a href="https://assethoard.com/blog/godot-vs-unity">Godot vs Unity</a> comparison goes deeper.</p>
<p><strong>Best for:</strong> 2D games, first-time coders, anyone who values owning their tools outright</p>
<h3 id="gamemaker">GameMaker</h3><p>If your first game is 2D and you want to ship it quickly, <a href="https://gamemaker.io" target="_blank" rel="noopener noreferrer">GameMaker</a> is a superb choice, and its track record embarrasses engines ten times its size. Undertale, Hyper Light Drifter, Katana ZERO, Nuclear Throne and Hotline Miami all came out of it.</p>
<p>It is built entirely around 2D, which is its whole strength. You can start with drag-and-drop actions and graduate to GML, its scripting language, when you are ready for more control. That gentle ramp from no-code to real-code is exactly what a lot of beginners need.</p>
<p>The catch is that it is 2D only, so the day you want to make a 3D game you will be reaching for something else. For the 2D-versus-2D call against Godot, see <a href="https://assethoard.com/blog/gamemaker-vs-godot">GameMaker vs Godot</a>.</p>
<p><strong>Best for:</strong> 2D-only projects, fast iteration, a smooth path from visual logic into code</p>
<h3 id="unity">Unity</h3><p>The default of the last decade, and still an enormous, capable engine. <a href="https://unity.com" target="_blank" rel="noopener noreferrer">Unity</a> uses C#, a proper mainstream language that looks good on a CV, and it has the largest third-party ecosystem of the lot. If a specific asset pack, tutorial series or plugin exists for exactly your game, there is a strong chance it exists for Unity first.</p>
<p>That ecosystem is the real reason to pick it. The Asset Store is deep, the answer to almost any &quot;how do I&quot; is already on YouTube, and studio job listings ask for it by name more than any other engine.</p>
<p>Two caveats. It&#39;s heavier and more complex to get started with than Godot or GameMaker, so the beginner on-ramp is a little steeper. And Unity spent 2023 torching a lot of goodwill with a since-reversed runtime-fee announcement, which is worth knowing about even though the policy itself is gone. The tech is still excellent; just go in with clear eyes.</p>
<p><strong>Best for:</strong> 3D and 2D alike, building job-ready skills, leaning on a huge asset and tutorial ecosystem</p>
<h3 id="unreal-engine">Unreal Engine</h3><p><a href="https://www.unrealengine.com" target="_blank" rel="noopener noreferrer">Unreal</a> is the powerhouse. If you are chasing high-fidelity 3D, photoreal lighting, or the kind of visuals that make people ask &quot;that is a game?&quot;, this is the tool the biggest studios reach for, and it is free until you are earning serious money.</p>
<p>Its Blueprints visual scripting system is powerful, so you can build a surprising amount without writing C++. But Unreal is a large, heavy, professional-grade engine all the same. For a solo beginner making their first small game, it&#39;s often more engine than the project needs, and the learning curve is the steepest here. It also assumes a fairly modern machine, so on an older or low-spec laptop it will feel sluggish in a way Godot and Unity will not. If you are choosing between the two big 3D engines, my <a href="https://assethoard.com/blog/unreal-vs-unity">Unreal vs Unity</a> breakdown weighs them up.</p>
<p><strong>Best for:</strong> ambitious 3D, cutting-edge visuals, developers who know they want the AAA toolset</p>
<h3 id="the-no-code-tools-construct-and-gdevelop">The no-code tools: Construct and GDevelop</h3><p>If the word &quot;scripting&quot; makes you want to close the tab, start here. <a href="https://www.construct.net" target="_blank" rel="noopener noreferrer">Construct</a> and <a href="https://gdevelop.io" target="_blank" rel="noopener noreferrer">GDevelop</a> let you build complete, shippable games out of visual event sheets, no traditional programming required. They run in the browser, they are quick to learn, and they are brilliant for getting a real, playable thing in front of people fast.</p>
<p>You will eventually hit a ceiling that code-based engines do not have, but &quot;eventually&quot; might be several finished games away, and finishing games is the whole point.</p>
<p><strong>Best for:</strong> absolute beginners, non-programmers, rapid prototyping, small 2D projects</p>
<h2 id="a-quick-cheat-sheet">A quick cheat sheet</h2><ul>
<li><strong>I want 2D and I am new to code:</strong> Godot or GameMaker.</li>
<li><strong>I want 2D and I do not want to code at all:</strong> GDevelop or Construct.</li>
<li><strong>I want 3D and I am new:</strong> Godot first, Unity if you need its ecosystem.</li>
<li><strong>I want the most job-transferable skills:</strong> Unity (C#).</li>
<li><strong>I want the best-looking 3D and I am ambitious:</strong> Unreal.</li>
<li><strong>I can&#39;t decide:</strong> Godot. Download it today, you&#39;ll lose nothing.</li>
</ul>
<h2 id="the-thing-nobody-wants-to-hear">The thing nobody wants to hear</h2><p>The engine isn&#39;t what&#39;s standing between you and a finished game. Scope is.</p>
<p>The most common failure in game development has nothing to do with the engine. It&#39;s starting a sprawling dream project, burning out on it, and quietly shelving it six weeks later with nothing to show. The engine you agonised over for a week barely registers next to that.</p>
<p>So whatever you pick, make something tiny first. A game that fits in one screen. Something you can finish in a weekend and then actually release, warts and all. You will learn more from shipping one embarrassing little game than from a month of comparison videos, and you will find out whether the boots fit by walking in them, not by reading the box.</p>
<h2 id="whatever-you-pick-your-assets-will-pile-up">Whatever you pick, your assets will pile up</h2><p>The moment you start, you begin collecting stuff. Sprite packs, sound effects, models, fonts, that free tileset bundle you grabbed at 2am and will absolutely use one day. It happens in every engine, and it happens fast.</p>
<p>That collection is the one thing that outlives your engine choice. Your art, audio and models are just files, and they carry across unchanged if you ever switch. The code does not, but the assets do. Which is exactly why it pays to keep them organised and engine-agnostic from the very beginning, rather than as a folder called <code>assets_final_v3_USE_THIS_ONE</code>.</p>
<p>That is the job <a href="https://assethoard.com/downloads">AssetHoard</a> does. It sits beside whichever engine you land on, previewing and organising your whole library in one place, and it reads native project formats from <a href="https://assethoard.com/godot-asset-manager">Godot</a>, <a href="https://assethoard.com/unity-asset-manager">Unity</a> and <a href="https://assethoard.com/gamemaker-asset-manager">GameMaker</a> so the same library follows you wherever you go.</p>
<p>Pick an engine. Make something small. Keep your assets tidy. The rest is just practice.</p>
<hr>
<p><em>Mark</em></p>
<p class="photo-credit">Hero photo by <a href="https://unsplash.com/@kike_borland">Enrique Guzmán Egas</a> on <a href="https://unsplash.com/photos/gSstgCAgd3U">Unsplash</a>.</p>
]]></content:encoded>
		</item>
		<item>
			<title>Where to get free sound effects in 2026</title>
			<link>https://assethoard.com/blog/free-sound-effects-2026</link>
			<guid isPermaLink="true">https://assethoard.com/blog/free-sound-effects-2026</guid>
			<pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
			<dc:creator>Mark Gandolfo</dc:creator>
			<category>Guides</category>
			<description>22 places to find free sound effects and audio for your game in 2026. Big CC0 libraries, professional bundles, the BBC archive, and generators for making your own retro bleeps from scratch.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/freesounds.png" alt="Where to get free sound effects in 2026" /></p>
<p><a href="https://assethoard.com/blog/2026/freesounds.png" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/freesounds.png" alt="A collection of free sound effect and audio sources for game developers in 2026" title="Where to get free sound effects in 2026" width="1920" height="1339" loading="eager" decoding="async"></a></p>
<p>Sound is the half of game feel that nobody notices until it is missing. A jump without a jump sound is just a sprite moving up. Add a short, punchy bloop and suddenly the thing has weight.</p>
<p>The good news is that in 2026 you do not need a field recorder, a foley pit, or a subscription to make your game sound good. There are enormous libraries of free, royalty-free, and public-domain audio out there, plus a small clutch of generators that will synthesise a laser or a coin pickup for you in about four seconds.</p>
<p>Here are 22 places worth bookmarking, grouped by what they are best at. A licence note at the end covers the one thing you must check before you ship.</p>
<h2 id="the-big-all-rounder-libraries">The big all-rounder libraries</h2><p>Start here. These cover the widest range of sounds and are where most searches begin.</p>
<h3 id="freesound">Freesound</h3><p><a href="https://freesound.org" target="_blank" rel="noopener noreferrer">Freesound.org</a> is the granddaddy, a collaborative database with well over half a million samples uploaded by people all over the world. The depth is unmatched. If you need the specific sound of a rusty gate, a Geiger counter, or a very particular type of splash, it is probably in here somewhere.</p>
<p>The trade-off is that quality and licensing vary wildly from one upload to the next. Filter by CC0 if you want no-strings usage, and audition before you commit. The search has quietly improved over the years and now handles similarity search, so you can find &quot;more sounds like this one&quot;.</p>
<p><strong>Best for:</strong> Specific and unusual sound effects, foley, ambience, sheer variety</p>
<h3 id="pixabay">Pixabay</h3><p>Yes, the stock photo site. <a href="https://pixabay.com/sound-effects/" target="_blank" rel="noopener noreferrer">Pixabay</a> has grown a genuinely large royalty-free sound effect and music library, all under a permissive Pixabay licence that behaves like CC0 for practical purposes. No attribution, commercial use fine.</p>
<p>The filtering and preview experience is nicer than most dedicated audio sites, which makes it a great first stop for common sounds.</p>
<p><strong>Best for:</strong> Quick searches, common effects, background music, zero attribution</p>
<h3 id="zapsplat">Zapsplat</h3><p><a href="https://www.zapsplat.com" target="_blank" rel="noopener noreferrer">Zapsplat</a> hosts hundreds of thousands of sound effects and production music tracks. The free tier is generous and covers commercial use, on the condition that you credit Zapsplat somewhere (a Gold subscription removes the attribution requirement and the download limits).</p>
<p>The library is well tagged and professionally curated, so you spend less time wading through duds.</p>
<p><strong>Best for:</strong> Well-organised, professional effects when you can accommodate a credit</p>
<h3 id="mixkit">Mixkit</h3><p><a href="https://mixkit.co/free-sound-effects/" target="_blank" rel="noopener noreferrer">Mixkit</a> (part of Envato) gives away a curated set of free sound effects and music under its own licence, free for commercial use with no attribution. The library is smaller and more hand-picked than the giants above, which is a feature rather than a bug when you just want something clean and usable fast.</p>
<p><strong>Best for:</strong> Curated, ready-to-use effects and music, no attribution</p>
<h3 id="uppbeat">Uppbeat</h3><p><a href="https://uppbeat.io/sfx" target="_blank" rel="noopener noreferrer">Uppbeat</a> started as a music platform and now carries a solid sound effect library too. The free tier is clean and modern, aimed squarely at content creators, with a credit required on the free plan.</p>
<p><strong>Best for:</strong> Modern UI sounds, whooshes, transitions, background music</p>
<h3 id="opengameart">OpenGameArt</h3><p><a href="https://opengameart.org/art-search-advanced?field_art_type_tid%5B%5D=13" target="_blank" rel="noopener noreferrer">OpenGameArt.org</a> is best known for sprites and models, but its audio section is a hidden gem for game-specific sounds and chiptune music. Everything is under an open licence (CC0, CC-BY, GPL), it is built by and for game developers, and the search lets you filter by licence up front.</p>
<p><strong>Best for:</strong> Game-specific SFX, chiptune and orchestral music, open licences</p>
<h2 id="sound-effect-specialists">Sound effect specialists</h2><p>When you need higher-end or more specific effects, these dedicated libraries earn their place.</p>
<h3 id="sonniss-gdc-game-audio-bundle">Sonniss GDC Game Audio bundle</h3><p>Every year for GDC, <a href="https://sonniss.com/gameaudiogdc" target="_blank" rel="noopener noreferrer">Sonniss</a> releases a free bundle of professional game audio. The back catalogue now runs to hundreds of gigabytes of royalty-free sound effects, usable commercially with no attribution required. These are not amateur phone recordings, they come from professional sound libraries and they are genuinely excellent. Download a couple of years&#39; worth and you have a career&#39;s supply of foley.</p>
<p><strong>Best for:</strong> Professional-grade effects in bulk, one enormous free download</p>
<h3 id="99sounds">99Sounds</h3><p><a href="https://99sounds.org" target="_blank" rel="noopener noreferrer">99Sounds</a> publishes free, curated sound effect and sample packs put together by working sound designers. Cinematic hits, foley, ambiences, glitch, and the occasional oddball themed pack. Quality is consistently high because each release is a deliberate collection rather than a dumping ground.</p>
<p><strong>Best for:</strong> Themed professional packs, cinematic and impact sounds</p>
<h3 id="a-sound-effect">A Sound Effect</h3><p><a href="https://www.asoundeffect.com/free-sound-effects/" target="_blank" rel="noopener noreferrer">A Sound Effect</a> is primarily a marketplace for boutique commercial libraries, but it runs a regularly updated free section and gives away high-quality packs from independent sound designers. Well worth checking periodically, and a good way to sample the work of pro libraries before buying.</p>
<p><strong>Best for:</strong> Boutique free packs, discovering professional sound designers</p>
<h3 id="bbc-sound-effects">BBC Sound Effects</h3><p>The <a href="https://sound-effects.bbcrewind.co.uk" target="_blank" rel="noopener noreferrer">BBC Sound Effects archive</a> put over 33,000 effects online, drawn from decades of the BBC&#39;s radio and television work. Vintage machinery, wildlife, crowds, historical ambiences, the lot.</p>
<p>The catch is the licence. These are released under the RemArc licence, which covers personal, educational, and research use, not commercial games. Superb for prototyping, reference, and learning, but read the terms carefully before anything ships. Treat it as inspiration, not shipping stock.</p>
<p><strong>Best for:</strong> Reference, prototyping, historical and unusual recordings (non-commercial)</p>
<h3 id="adobe-free-sound-effects">Adobe free sound effects</h3><p>Adobe quietly maintains a <a href="https://www.adobe.com/products/audition/offers/AdobeAuditionDownloadSoundEffects.html" target="_blank" rel="noopener noreferrer">free download of around 10,000 sound effects</a> originally assembled for Audition. Ambiences, foley, sci-fi, cartoon, and more, cleanly organised into themed folders. No Creative Cloud subscription required to grab them, and they are royalty-free.</p>
<p><strong>Best for:</strong> A solid, well-organised starter pack across every category</p>
<h3 id="gamesounds-xyz">GameSounds.xyz</h3><p><a href="https://gamesounds.xyz" target="_blank" rel="noopener noreferrer">GameSounds.xyz</a> is a no-frills aggregator that pulls together public-domain and permissively licensed audio in a directory you can browse straight in the page. Not pretty, but fast, and everything is oriented towards game use.</p>
<p><strong>Best for:</strong> Quick browsing of public-domain game audio</p>
<h3 id="free-sfx-and-orange-free-sounds">Free SFX and Orange Free Sounds</h3><p>Two smaller British libraries worth a mention. <a href="https://www.freesfx.co.uk" target="_blank" rel="noopener noreferrer">Freesfx.co.uk</a> offers a broad catalogue free with attribution, and <a href="https://orangefreesounds.com" target="_blank" rel="noopener noreferrer">Orange Free Sounds</a> mixes SFX, loops, and music under Creative Commons licences. Neither is huge, but both surface things the big sites miss.</p>
<p><strong>Best for:</strong> Filling gaps the majors leave, Creative Commons audio</p>
<h3 id="soundbible-and-fesliyan-studios">SoundBible and Fesliyan Studios</h3><p><a href="https://soundbible.com" target="_blank" rel="noopener noreferrer">SoundBible</a> is an old-school library of individual clips, largely CC0 or attribution, handy for one-off common sounds. <a href="https://www.fesliyanstudios.com/sound-effects-free" target="_blank" rel="noopener noreferrer">Fesliyan Studios</a> leans towards game and cartoon effects plus royalty-free music, free with attribution for most uses.</p>
<p><strong>Best for:</strong> One-off common sounds, cartoon and game effects</p>
<h3 id="findsounds">FindSounds</h3><p><a href="https://www.findsounds.com" target="_blank" rel="noopener noreferrer">FindSounds</a> is not a library but a search engine that crawls audio across the web. When a sound is oddly specific and nowhere obvious has it, this is the tool that turns it up. Verify the licence on wherever it actually lives before you use anything you find.</p>
<p><strong>Best for:</strong> Hunting down a very specific sound that hides from normal search</p>
<h2 id="make-your-own-retro-sound-effect-generators">Make your own: retro sound effect generators</h2><p>Sometimes the fastest route to the exact bleep you want is to generate it. These tools synthesise classic game sounds from a handful of sliders, and because you made the output, there are no licensing questions at all.</p>
<h3 id="bfxr">Bfxr</h3><p><a href="https://www.bfxr.net" target="_blank" rel="noopener noreferrer">Bfxr</a> is the browser-based descendant of the legendary sfxr. Hit &quot;Randomise&quot;, mash the preset buttons (Pickup, Laser, Explosion, Power-up, Jump, Hurt), tweak the waveform and envelope, and export to .wav. It is the single fastest way to fill a whole game with coherent 8-bit sound effects in an afternoon. Runs entirely in the browser, nothing to install.</p>
<p><strong>Best for:</strong> 8-bit and chiptune SFX, rapid prototyping, jam games</p>
<h3 id="chiptone">ChipTone</h3><p><a href="https://sfbgames.itch.io/chiptone" target="_blank" rel="noopener noreferrer">ChipTone</a> by SFB Games is a more powerful free synth in the same spirit. Richer control over the waveform, envelope, arpeggios, and effects than Bfxr, with a friendlier interface. If Bfxr feels too coarse, this is the step up.</p>
<p><strong>Best for:</strong> More detailed retro SFX with finer control</p>
<h3 id="jsfxr-and-rfxgen">jsfxr and rFXGen</h3><p><a href="https://sfxr.me" target="_blank" rel="noopener noreferrer">jsfxr</a> is a clean web port of the original sfxr, minimal and instant. <a href="https://raylibtech.itch.io/rfxgen" target="_blank" rel="noopener noreferrer">rFXGen</a> by the raylib author is a small downloadable tool that does the same job as a native app, with wave visualisation and batch export. Both are free.</p>
<p><strong>Best for:</strong> Purists who want the original sfxr feel, offline generation</p>
<h3 id="labchirp">LabChirp</h3><p><a href="https://labbed.net/software.html" target="_blank" rel="noopener noreferrer">LabChirp</a> is a free Windows tool for building more complex layered sound effects than the sfxr family allows. Multiple channels, more waveform types, and enough depth to make sounds that do not obviously scream &quot;generated&quot;. Free and worth the download.</p>
<p><strong>Best for:</strong> Layered, less obviously synthetic generated effects</p>
<h2 id="bonus-ambience-and-music">Bonus: ambience and music</h2><p>Not strictly sound effects, but you will want these soon enough.</p>
<ul>
<li><strong><a href="https://tabletopaudio.com" target="_blank" rel="noopener noreferrer">Tabletop Audio</a></strong> builds looping ambiences and soundscapes (forests, taverns, spaceships) that make great background beds. Free to stream and download.</li>
<li><strong><a href="https://incompetech.com" target="_blank" rel="noopener noreferrer">Incompetech</a></strong> is Kevin MacLeod&#39;s vast library of royalty-free music, free with attribution under CC-BY.</li>
<li><strong><a href="https://freemusicarchive.org" target="_blank" rel="noopener noreferrer">Free Music Archive</a></strong> and the <strong><a href="https://www.youtube.com/audiolibrary" target="_blank" rel="noopener noreferrer">YouTube Audio Library</a></strong> both offer large collections of free tracks, licences varying per item.</li>
<li><strong><a href="http://ccmixter.org" target="_blank" rel="noopener noreferrer">ccMixter</a></strong> hosts remixable Creative Commons music if you want stems to chop up.</li>
</ul>
<h2 id="a-note-on-licences">A note on licences</h2><p>&quot;Free to download&quot; and &quot;free to ship&quot; are not the same sentence. Before anything goes into a build you sell, check the licence on every individual clip. The main ones you will meet:</p>
<ul>
<li><strong>CC0 / public domain</strong>: use however you like, no attribution, commercial use fine. The gold standard.</li>
<li><strong>CC-BY</strong>: free to use, but you must credit the creator. Keep a running credits list as you go, not the night before launch.</li>
<li><strong>CC-BY-SA</strong>: attribution plus derivatives must carry the same licence. Fine for audio you use as-is, awkward if you build on it.</li>
<li><strong>Site-specific licences</strong> (Pixabay, Mixkit, Zapsplat): usually permissive, but each has its own wording on attribution and redistribution. Read it once.</li>
<li><strong>Non-commercial licences</strong> (the BBC&#39;s RemArc): great for prototyping and learning, not for a game you sell.</li>
</ul>
<p>When in doubt, read the licence. It takes thirty seconds and saves the kind of headache that arrives by email months after launch. Keeping the licence noted against each sound as you download it is the cheapest insurance in game development.</p>
<h2 id="keeping-it-all-organised">Keeping it all organised</h2><p>Here is what happens in practice. You grab a Sonniss bundle &quot;for later&quot;, generate forty variations in Bfxr during a jam, download three themed packs from 99Sounds, and pull one perfect gate creak off Freesound. Within a month you have thousands of .wav and .ogg files scattered across your downloads folder, a couple of unzipped bundles, and an external drive, and you cannot remember which of them holds that footstep you liked.</p>
<p>Finding one sound you downloaded six months ago becomes an archaeological dig.</p>
<p><a href="https://assethoard.com">AssetHoard</a> is a local-first <a href="https://assethoard.com">asset manager for game developers</a> built for exactly this. Point it at your audio folders and it indexes the lot, waveform previews and all, so you can audition a sound in place without opening another app, search across everything at once, and drag the clip straight into Unity or Godot. It reads inside .zip and other archives without unpacking them, so those Sonniss bundles stay exactly as you downloaded them while still being fully searchable. You can even record the licence against each file so future-you knows what is safe to ship.</p>
<p>One-time purchase, offline, no subscription. Your library stays on your machine.</p>
<h2 id="the-bottom-line">The bottom line</h2><p>You can make a game sound professional in 2026 without spending a cent. Between the big libraries, the professional bundles, the BBC&#39;s archive, and a generator or two, the raw material is all there and mostly free to ship.</p>
<p>The hard part was never finding sounds. It is finding the right one, twice, when you need it. Sort that out early and the audio stops being a chore.</p>
<p>Now go make something that goes bloop.</p>
<hr>
<p><em>The AssetHoard Team</em></p>
]]></content:encoded>
		</item>
		<item>
			<title>Look inside any archive, without unzipping it</title>
			<link>https://assethoard.com/blog/look-inside-archives-without-unzipping</link>
			<guid isPermaLink="true">https://assethoard.com/blog/look-inside-archives-without-unzipping</guid>
			<pubDate>Fri, 07 Aug 2026 00:00:00 GMT</pubDate>
			<dc:creator>Mark Gandolfo</dc:creator>
			<category>AssetHoard news</category>
			<description>How AssetHoard indexes and previews the contents of zip, unitypackage, tar.gz and rar archives in place, without extracting a single file to disk.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/pages/archive/assethoard-archive-preview.png" alt="Look inside any archive, without unzipping it" /></p>
<p><a href="https://assethoard.com/pages/archive/assethoard-archive-preview.png" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/pages/archive/assethoard-archive-preview.png" alt="AssetHoard previewing a file from inside an archive, its contents listed in the library as if extracted" title="Previewing a member of an archive in AssetHoard, with nothing extracted to disk" width="1914" height="1074" loading="eager" decoding="async"></a></p>
<p>Every game developer has the same graveyard: a folder full of <code>.zip</code>, <code>.unitypackage</code>, and <code>.tar.gz</code> files you downloaded from a bundle sale two years ago. You know there is a great rock texture in one of them. You have no idea which. So you unzip all forty of them onto your SSD, poke around, and then have two copies of everything forever.</p>
<p>AssetHoard is a local-first asset manager for indie game developers and digital artists, and it takes a different approach to archives. It reads them where they sit, builds a searchable index of what is inside, and shows you previews of the contents, all without extracting a single file. The <a href="https://assethoard.com/blog/browse-inside-archives-without-extracting">feature announcement</a> covered what that looks like day to day; this post is how it works under the hood, and why it is faster than it has any right to be.</p>
<h2 id="nothing-gets-extracted-indexing-archives-in-place">Nothing gets extracted: indexing archives in place</h2><p>There was a single goal, and no obvious way to reach it: <strong>the original archive is referenced in place and never copied.</strong> When AssetHoard imports a <code>.zip</code> or <code>.unitypackage</code>, it does not unpack it into a working directory. It opens the file, walks its table of contents, and records every member (each model, texture, and audio clip inside) as a logical entry in your library. The archive on disk is left exactly as it was.</p>
<p>That means importing a 4 GB asset pack costs you close to zero extra disk space. Your library shows the contents, your searches and filters cover the contents, but the bytes stay compressed inside the one file you already have.</p>
<p>Supported archive formats today:</p>
<ul>
<li><strong><a href="https://assethoard.com/unity-asset-manager">Unity packages</a></strong> (<code>.unitypackage</code>), with a dedicated indexer that understands Unity&#39;s GUID-and-pathname layout</li>
<li><strong>Zip</strong> (<code>.zip</code>)</li>
<li><strong>Tarballs</strong>: <code>.tar</code>, <code>.tar.gz</code>, <code>.tgz</code>, and bare <code>.gz</code></li>
<li><strong>RAR</strong> (<code>.rar</code>)</li>
</ul>
<p>Each format gets its own adapter behind a shared contract, so the rest of the app never has to care whether a preview came out of a zip central directory or a gzip stream.</p>
<h2 id="reaching-one-file-in-the-middle-of-a-compressed-stream">Reaching one file in the middle of a compressed stream</h2><p>Listing an archive&#39;s contents is straightforward. The awkward bit is pulling <strong>one</strong> file out of the middle of a compressed stream when you want to preview it, without decompressing everything before it.</p>
<p>For a zip this is tractable: zip keeps a central directory and each entry is independently compressed, so AssetHoard can seek straight to the member it wants. A tarball is a single walk. But a <code>.tar.gz</code> is one long gzip stream with no seek points at all. Naively, to read the last file you would have to decompress the entire archive first.</p>
<p>AssetHoard solves this with a checkpoint index (the &quot;zran&quot; technique). During indexing it drops an access point roughly every 1 MB of decompressed data and writes those checkpoints into a small sidecar file next to the index. When you later ask to preview a member, it jumps to the nearest checkpoint and decompresses forwards only from there. The sidecar costs about 1.6% of the archive size, and in exchange a file buried deep in a gzip stream opens in a fraction of a second instead of after a full-archive decompress.</p>
<p>When a member does get read, it is <strong>streamed</strong>, never buffered. A single mesh inside a package can be hundreds of megabytes, so AssetHoard opens a reader over the member&#39;s uncompressed bytes and pipes them straight to a cache file on disk. It never holds a whole member in memory.</p>
<h2 id="previewing-files-inside-an-archive">Previewing files inside an archive</h2><p>Browsing a package should feel like browsing a folder. In AssetHoard it does, and the trick is doing the least possible work per item.</p>
<ul>
<li><strong>Images and textures</strong> get thumbnailed and shown in the grid.</li>
<li><strong>3D models</strong> show a poster-frame thumbnail by default. The full interactive viewer only mounts, and only plucks the model&#39;s bytes out of the archive, when you actually click &quot;View in 3D&quot;. You can scroll past a hundred models without decompressing a single one.</li>
<li><strong>Audio</strong> clips play in place.</li>
<li><strong>Engine resources</strong> are understood natively. <a href="https://assethoard.com/godot-asset-manager">Godot packages</a>, for example, surface their embedded <code>preview.png</code> instead of falling back to a generic icon.</li>
</ul>
<p>There is a nice bit of restraint in the indexer here too. For a &quot;solid&quot; archive, where every read has to re-decompress from a block boundary, an eager pass that thumbnailed every member up front would be quadratic. AssetHoard detects that case and skips the eager pass, falling back to generating previews lazily on first view. You get thumbnails either way; the app just refuses to melt your CPU to get them a few seconds sooner.</p>
<p>Thumbnails, once generated, are cached as PNGs and served to the interface over a local asset protocol. Image bytes never cross the boundary between the Rust core and the UI, which keeps browsing snappy even in packages with thousands of members.</p>
<h2 id="keeping-the-index-correct-when-the-archive-changes">Keeping the index correct when the archive changes</h2><p>Referencing files in place instead of copying them raises an obvious question: what happens when the archive changes, or the index and the file drift apart? AssetHoard treats this as a first-class concern.</p>
<ul>
<li><strong>Fingerprinting and a freshness ladder.</strong> Cached previews are stamped with a fingerprint of their source archive. If the cache file is present, it is provably current, so it is served without even touching the database or reopening the archive. If the archive changed underneath, the index is rebuilt.</li>
<li><strong>Drift detection.</strong> Before yielding bytes from a seek into a tarball, the adapter re-checks the 512-byte tar header at the recorded offset against the member it expected. If they do not match, it drops the stale cache, rebuilds the index once, and retries. A corrupted or silently-shifted index can never hand you the wrong file&#39;s bytes.</li>
<li><strong>Per-archive locks.</strong> Two previews of the same archive will not both pay for an expensive rebuild. The costly index build serialises on a per-archive lock while everything else stays concurrent.</li>
<li><strong>A security gate.</strong> Virtual member pointers only resolve to archives AssetHoard actually imported. You cannot smuggle an arbitrary path off disk through a crafted pointer.</li>
<li><strong>Graceful degradation.</strong> If the source archive is moved or deleted, that is an expected outcome (the original was never copied), and the app says so rather than crashing. Password-protected archives are refused cleanly at index time instead of half-importing members that could never preview.</li>
</ul>
<h2 id="why-it-matters">Why it matters</h2><p>Put together, this means you can point AssetHoard at a directory of untouched archives and immediately treat their contents as first-class library items: searchable, filterable, taggable, and previewable, with no extraction step, no duplicated storage, and no waiting for a 4 GB unzip to finish before you can find your rock texture.</p>
<p>The archives stay exactly as you downloaded them. AssetHoard just gives you x-ray vision into them.</p>
<p>Have a browse through the <a href="https://assethoard.com/docs/archives">archives documentation</a> for the full picture, or <a href="https://assethoard.com/downloads">download AssetHoard</a> and point it at that graveyard folder you have been avoiding.</p>
<hr>
<p><em>Mark</em></p>
]]></content:encoded>
		</item>
		<item>
			<title>How to Organise Unity Asset Store Downloads</title>
			<link>https://assethoard.com/blog/how-to-organise-unity-asset-store-downloads</link>
			<guid isPermaLink="true">https://assethoard.com/blog/how-to-organise-unity-asset-store-downloads</guid>
			<pubDate>Sun, 02 Aug 2026 00:00:00 GMT</pubDate>
			<dc:creator>The AssetHoard Team</dc:creator>
			<category>Guides</category>
			<description>A practical guide to managing your growing Unity Asset Store library, from folder structure to dedicated tools.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/pages/unity/assethoard-unity-import-downloaded.png" alt="How to Organise Unity Asset Store Downloads" /></p>
<p><a href="https://assethoard.com/pages/unity/assethoard-unity-import-downloaded.png" target="_blank" rel="noopener noreferrer" title="Open the AssetHoard Unity import panel screenshot in a new tab"><img src="https://assethoard.com/pages/unity/assethoard-unity-import-downloaded.png" alt="AssetHoard's Unity import panel listing 28 newly detected Asset Store packages ready to import, each showing its name, publisher, and file size" title="AssetHoard detecting downloaded Unity Asset Store packages and offering to import them without opening Unity" loading="lazy"></a></p>
<p>You know how it goes. There&#39;s a Humble Bundle with forty Unity assets for $12. You grab it. Then the Asset Store has a 50% off sale and you pick up a few character packs you&#39;ve been eyeing. A forum post recommends a great procedural terrain tool. It&#39;s on sale, why not. Six months later you have 300 .unitypackage files and absolutely no idea what most of them contain.</p>
<p>This is the Unity Asset Store backlog problem, and it affects almost every developer who uses the store seriously.</p>
<h2 id="the-problem-with-the-unity-asset-store">The problem with the Unity Asset Store</h2><p>The Asset Store itself is part of the issue. When you&#39;re browsing it inside Unity, you see nice screenshots and read the description. But once something is in your library, that context mostly disappears. There&#39;s no tagging, no personal notes, no way to filter your own library by style or category. You can see a list of things you&#39;ve purchased, and that&#39;s about it.</p>
<p>Outside of Unity it&#39;s worse. Your downloaded packages sit in a cache folder somewhere on your machine, just a pile of files named things like <code>FantasyRPGCharacterPack_v3.unitypackage</code>. No thumbnails. No way to know if that&#39;s a set of 2D sprites or fully rigged 3D models without importing it.</p>
<p>So what do most developers do? They import packages into a throwaway Unity project just to jog their memory, then delete it and forget again. If they&#39;re lucky, they remember to check the Asset Store listing first. If they&#39;re not, they spend twenty minutes importing and exploring something they bought two years ago and never used.</p>
<p>Multiply that across 200+ purchases and you&#39;ve lost serious time.</p>
<h2 id="where-unity-stores-downloaded-packages">Where Unity stores downloaded packages</h2><p>Before you can organise anything, you need to know where the files actually live.</p>
<p>On Windows, Unity caches downloaded packages here:</p>
<pre><code class="hljs language-plaintext">C:\Users\{username}\AppData\Roaming\Unity\Asset Store-5.x\</code></pre><p>On macOS it&#39;s:</p>
<pre><code class="hljs language-plaintext">~/Library/Unity/Asset Store-5.x/</code></pre><p>And on Linux:</p>
<pre><code class="hljs language-plaintext">~/.local/share/unity3d/Asset Store-5.x/</code></pre><p>Inside that folder, packages are organised by publisher name, then package name. So a Synty Studios package might live at something like <code>Unity\Asset Store-5.x\Synty Studios\POLYGON - Fantasy Kingdom\</code>.</p>
<p>A .unitypackage file is essentially a tar.gz archive. Crack one open and you&#39;ll find the asset files themselves, <code>.meta</code> files, and a folder structure that mirrors how things will be imported into your project. Unity uses this to reconstruct where everything goes. It&#39;s not a mystery format, it&#39;s just not visible in any useful way without tooling.</p>
<p>A lot of developers have no idea this cache folder exists. They assume packages live &quot;in Unity&quot; somehow, and are surprised to discover there are gigabytes of files sitting in AppData.</p>
<h2 id="how-to-set-up-a-sane-folder-structure">How to set up a sane folder structure</h2><p>The first practical step is to stop relying on Unity&#39;s cache folder as your long-term storage. Create a dedicated folder somewhere sensible, outside any individual Unity project, and treat it as your personal asset library.</p>
<p>Something like <code>D:\GameAssets\</code> on Windows, or <code>~/GameAssets/</code> on macOS and Linux. The location matters less than the habit of putting everything there consistently.</p>
<p>From there, pick an organisational scheme and stick with it. Two approaches that work well:</p>
<p><strong>By publisher.</strong> If you buy a lot from the same studios (Synty, Kay Lousberg, Kenney), organise by publisher name: <code>GameAssets/Synty/</code>, <code>GameAssets/Kenney/</code>, etc. This mirrors how the Asset Store cache is already structured, which makes copying files over straightforward.</p>
<p><strong>By category.</strong> If you buy from lots of different publishers, category-first often makes more sense: <code>GameAssets/3D Models/</code>, <code>GameAssets/Audio/</code>, <code>GameAssets/UI/</code>, <code>GameAssets/Shaders/</code>. When you&#39;re hunting for audio assets, you look in one place regardless of who made them.</p>
<p>You can combine the two: publisher folders within categories, or sub-folders by style within publisher folders. Whatever matches how you actually search for things.</p>
<p>Alongside the folder structure, keep a simple reference document. A spreadsheet or even a plain text file. For each package, note:</p>
<ul>
<li>What the package actually contains (a brief description in your own words)</li>
<li>The licence type (some Asset Store licences restrict redistribution or use in certain contexts)</li>
<li>Which projects you&#39;ve used it in</li>
</ul>
<p>That last one is more useful than it sounds. When you&#39;re upgrading a project or changing an asset, knowing exactly what you&#39;ve used and where means you&#39;re not hunting through old project folders.</p>
<p>One more thing: back up your packages. The Asset Store doesn&#39;t guarantee lifetime access to everything. Publishers remove packages, the store has had downtime, and there have been cases where purchased assets became unavailable. Once you&#39;ve downloaded something you paid for, treat it like it might not be there tomorrow, because occasionally it won&#39;t be.</p>
<h2 id="why-folder-structure-alone-isnt-enough">Why folder structure alone isn&#39;t enough</h2><p>Folders get you a long way. They&#39;re better than nothing by a significant margin. But they break down once your library gets serious.</p>
<p>The fundamental limitation is that a folder tells you what something is called and where it lives. It doesn&#39;t tell you what&#39;s inside. You can rename your file to <code>synty_polygon_fantasy_kingdom_v1.2.unitypackage</code> and that&#39;s still just a name. You don&#39;t know whether it has NPCs, whether the textures are 1K or 4K, whether it includes animations or just static meshes.</p>
<div class="figure-inline">
<p class="figure-inline__text">Tags are the thing folders can't do. A package might be "low-poly" and "fantasy" and "Synty" and "characters" all at once. In a folder structure, it lives in exactly one place. If you organise by publisher, you can't find it when you're browsing by style. If you organise by style, you lose the publisher grouping. Any folder scheme is a single taxonomy, and your brain uses multiple taxonomies simultaneously.</p>
<a href="https://assethoard.com/pages/unity/assethoard-unity-categorise.png" target="_blank" rel="noopener noreferrer" class="figure-inline__image" title="Open the AssetHoard category management screenshot in a new tab"><img src="https://assethoard.com/pages/unity/assethoard-unity-categorise.png" alt="AssetHoard's Manage Categories dialog assigning categories such as Props, Sprites, and Textures to a Unity package, shown over a grid of package thumbnails" title="Tagging and categorising a Unity package across multiple categories at once in AssetHoard" loading="lazy"></a>
</div>

<p>Spreadsheets help with this. You can add multiple columns for different attributes. But they don&#39;t scale pleasantly once you&#39;re past about fifty entries, and they&#39;re completely disconnected from the actual files.</p>
<p>The deeper problem is that to even fill in a spreadsheet accurately, you need to know what&#39;s in each package. And the only way to find out what&#39;s in a .unitypackage without tooling is to import it into Unity. Which brings you back to the throwaway project workflow, just with more paperwork involved.</p>
<h2 id="using-assethoard-to-manage-your-unity-library">Using AssetHoard to manage your Unity library</h2><p>This is where a dedicated <a href="https://assethoard.com/">game asset manager</a> earns its keep.</p>
<p><video controls muted playsinline preload="metadata"><source src="https://assethoard.com/pages/unity/assethoard-unity-browse.mp4" type="video/mp4"></video></p>
<p><a href="https://assethoard.com/">AssetHoard</a> is built specifically for this problem. You point it at your Asset Store download folder, or wherever you&#39;ve moved your packages, and it indexes everything. No importing into Unity, no throwaway projects.</p>
<p>From there you get actual previews: thumbnails for textures, sprites, and models pulled directly from inside the .unitypackage archives. You can browse what&#39;s in a package before you&#39;ve touched it in Unity. That alone saves a significant amount of time if you&#39;re regularly evaluating what you own before starting a project.</p>
<p>Tagging is the other big feature. You can tag packages however makes sense to you: by style, category, project, quality level, whatever. A Synty pack can be tagged &quot;low-poly&quot;, &quot;fantasy&quot;, &quot;characters&quot;, and &quot;Synty&quot; simultaneously. When you&#39;re starting a fantasy game and want to see every low-poly character asset you own, you search for those tags and everything shows up regardless of where the files are stored.</p>
<p>When you&#39;ve found what you want, you can drag assets directly into an open Unity project. You&#39;re not manually digging through AppData or remembering which subfolder you put things in.</p>
<p><video controls muted playsinline preload="metadata"><source src="https://assethoard.com/pages/unity/assethoard-unity-draganddrop.mp4" type="video/mp4"></video></p>
<p>AssetHoard is a one-time purchase, local-first, no subscription. There&#39;s no cloud sync, no account required, nothing phoning home. Your files stay on your machine and so does your library data. If you want more detail on the Unity-specific workflow, there&#39;s a dedicated <a href="https://assethoard.com/unity-asset-manager">Unity asset manager</a> page worth reading.</p>
<h2 id="summary">Summary</h2><p>The real cost of your Asset Store library isn&#39;t the money you spent buying things. It&#39;s the time you lose not being able to find them when you need them, or re-discovering the same packages over and over because you have no system.</p>
<p>Any system is better than no system. Folders and a spreadsheet are a perfectly reasonable starting point and will serve you well until your library grows past a point where manual upkeep becomes its own overhead.</p>
<p>But if you&#39;re buying assets regularly, building multiple projects, or just feel like you own a lot of stuff you can&#39;t actually use effectively, a <a href="https://assethoard.com/">game asset manager</a> will return the time investment many times over. The goal is a library you can actually search, not just a pile of files you vaguely remember paying for.</p>
<hr>
<p><em>The Asset Hoard Team</em></p>
]]></content:encoded>
		</item>
		<item>
			<title>What is a digital asset management system for game developers?</title>
			<link>https://assethoard.com/blog/dam-for-game-developers</link>
			<guid isPermaLink="true">https://assethoard.com/blog/dam-for-game-developers</guid>
			<pubDate>Sun, 19 Jul 2026 00:00:00 GMT</pubDate>
			<dc:creator>Mark Gandolfo</dc:creator>
			<category>Guides</category>
			<description>Digital asset management (DAM) keeps every game asset findable in one place. Here&apos;s what that means for game devs, and what to look for in one.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/hero/assethoard-packs.png" alt="What is a digital asset management system for game developers?" /></p>
<p><a href="https://assethoard.com/hero/assethoard-packs.png" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/hero/assethoard-packs.png" alt="AssetHoard managing imported game asset packs" title="Catalogue and browse downloaded game asset packs in AssetHoard" width="1920" height="1032" loading="eager" decoding="async"></a></p>
<h2 id="so-whats-a-dam">So what&#39;s a DAM?</h2><p>Think about all your files. Every sprite, every 3D model, every sound effect you downloaded at 2am and swore you&#39;d use one day. If you&#39;re not totally sure where all of them are right now, that&#39;s the thing a DAM is for.</p>
<p>DAM stands for digital asset management. It&#39;s a system that keeps your files in one place, tags them, shows you previews, and lets you find things by what they are instead of where you saved them. That distinction doesn&#39;t matter much at ten files. At a few thousand it matters a lot.</p>
<p>The whole idea started in marketing. Big teams needed somewhere to keep logos and campaign images so nobody accidentally shipped last year&#39;s brand colours. Handy, but not built with game devs in mind.</p>
<h2 id="why-folders-stop-working">Why folders stop working</h2><p>Folders make you pick one home for each file, and most assets don&#39;t have one home. A single pixel sword might belong in your weapons pile, your player kit, that game jam project, and your medieval stuff, all at the same time. You can only file it once, so you end up copying it around, and then you&#39;ve got four swords and can&#39;t remember which one you actually finished.</p>
<p>You&#39;ve probably also opened a folder called <code>assets_final</code> and found <code>final_v2</code> inside it, and <code>final_ACTUAL_use_this</code> inside that. It happens to everyone eventually.</p>
<p>And folders can&#39;t show you anything. A filename like <code>char_03_b.png</code> tells you nothing on its own, so you end up opening files one at a time just to see what they are.</p>
<h2 id="why-a-regular-dam-wont-fix-it">Why a regular DAM won&#39;t fix it</h2><p>You might figure you can grab an off-the-shelf DAM and call it done. Usually not.</p>
<p>Most of them are built for marketing assets. They&#39;re fine with logos and photos, but hand them a Godot <code>.tres</code> file or an Aseprite animation and they don&#39;t really know what to do with it.</p>
<p>They also tend to be cloud-first and locked behind a login, so your whole library lives on someone else&#39;s server and you&#39;re paying every month to reach your own work. And the pricing usually assumes you&#39;re a team with an approvals process, not one person shipping a game on the side.</p>
<h2 id="what-actually-matters-for-game-devs">What actually matters for game devs</h2><p>If you&#39;re weighing up a DAM for game work, these are the parts worth caring about:</p>
<ul>
<li><strong>Handles your file types.</strong> Not just images. 3D models, sprites, animation, audio, fonts, and engine-specific formats too.</li>
<li><strong>Shows thumbnails.</strong> You think visually, so finding an asset by sight is faster than reading filenames.</li>
<li><strong>Tags things for you.</strong> Manual tagging is a second job. The good ones automate most of it.</li>
<li><strong>Tracks variants.</strong> Three versions of the same character should sit together, not scatter across your drive.</li>
<li><strong>Works offline and stays yours.</strong> Local-first means the library lives on your machine and doesn&#39;t need a connection to open.</li>
<li><strong>Talks to your engine.</strong> Dragging an asset straight into Unity or Godot beats exporting and re-importing.</li>
<li><strong>Holds up at scale.</strong> Ten files is nothing. A hundred thousand is the real test.</li>
</ul>
<p>If you&#39;re weighing actual tools against that list, we&#39;ve done a <a href="https://assethoard.com/blog/best-offline-asset-manager-indie-developers">round-up of offline asset managers for indie developers</a> that covers the main options.</p>
<h2 id="where-assethoard-fits">Where AssetHoard fits</h2><p>AssetHoard is a local-first desktop asset manager for game developers and digital artists. One place for everything, sitting on your own machine.</p>
<p>That list above was more or less the design brief. It reads 80+ file types, so your models, sprites, Aseprite files, audio, fonts, and engine packages all land in one library. It generates thumbnails so you can browse by sight, and <a href="https://assethoard.com/semantic-search">search works semantically and visually</a>, so you can look for what something resembles rather than only what you named it. Variant groups keep the &quot;which one&#39;s the final one&quot; problem contained. You can drag assets straight into <a href="https://assethoard.com/unity-asset-manager">Unity</a> or <a href="https://assethoard.com/godot-asset-manager">Godot</a>. And it&#39;s built in Rust, so it stays responsive when your library gets big.</p>
<p>It runs on Windows, macOS, and Linux. No accounts, no cloud, no monthly bill. It&#39;s a one-time purchase, $29 USD, and the library stays yours.</p>
<p>If your assets are already scattered across half a dozen drives, it&#39;s a decent place to bring them together. And if you want to see how a real library holds up at scale, here&#39;s <a href="https://assethoard.com/blog/how-i-manage-100000-game-assets">how I organise 100,000 game assets</a> with it.</p>
<p><a href="https://assethoard.com/downloads">Download AssetHoard</a></p>
]]></content:encoded>
		</item>
		<item>
			<title>Stop unzipping everything: browse inside archives without extracting</title>
			<link>https://assethoard.com/blog/browse-inside-archives-without-extracting</link>
			<guid isPermaLink="true">https://assethoard.com/blog/browse-inside-archives-without-extracting</guid>
			<pubDate>Sun, 12 Jul 2026 00:00:00 GMT</pubDate>
			<dc:creator>The AssetHoard Team</dc:creator>
			<category>AssetHoard news</category>
			<description>The next release lets you open zip, rar, and tgz files right in your library and preview what&apos;s inside, without unpacking a thing.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/pages/archive/assethoard-archive.png" alt="Stop unzipping everything: browse inside archives without extracting" /></p>
<p><a href="https://assethoard.com/pages/archive/assethoard-archive.png" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/pages/archive/assethoard-archive.png" alt="An archive open in AssetHoard, its files and folders listed in the library as if extracted" title="Browsing the contents of an archive in AssetHoard" width="1914" height="1074" loading="eager" decoding="async"></a></p>
<p>Be honest: how many <code>.zip</code> files are sitting in your Downloads folder right now, unopened, because you&#39;re not sure which one holds the texture you actually want?</p>
<p>Almost everything you grab arrives compressed. Asset packs, sprite sheets, model bundles, the odd font collection. They land as archives, and unpacking each one just to peek inside means loose files scattered across your drive, duplicated copies you forget to delete, and a Downloads folder that slowly turns into a landfill. So you don&#39;t unpack them. You leave them there, promising to sort it out later. Later never comes.</p>
<h2 id="open-the-box-without-unpacking-it">Open the box without unpacking it</h2><p>The next release of AssetHoard fixes the whole ritual. Import a <code>.zip</code>, <code>.rar</code>, or <code>.tgz</code> and it reads the contents on import, then shows the files and folders inside as if they were already sitting in your library. The folder tree is intact, names and sizes are right there, and you can dig through the whole thing like any other asset.</p>
<p>Nothing gets extracted. The archive stays as one tidy item in your library with its contents indexed underneath, so a pack holding hundreds of files doesn&#39;t flood your grid with clutter. Your drive stays clean, and there are no stray copies to chase down.</p>
<h2 id="preview-whats-actually-in-there">Preview what&#39;s actually in there</h2><p>Browsing a file list is useful. Seeing the files is better.</p>
<p>Click any file inside an archive and AssetHoard previews it live, exactly as if you&#39;d pulled it out. Images and sprites at full resolution, audio you can play in place, 3D models you can orbit and spin. Whatever the format, if AssetHoard can preview it loose, it can preview it inside an archive. It only reaches for the one file you clicked, and only when you click it. Everything else stays compressed until you go looking.</p>
<p>That means you can finally answer the question that started all this. Which pack has the texture? Open them, look, done. No unzip, no temp folders, no cleanup.</p>
<h2 id="one-less-chore">One less chore</h2><p>You didn&#39;t get into game development to be a file archaeologist. Archives are one more pile of admin between you and the work, and this quietly removes it. Your downloads stay downloads, your library stays tidy, and the thing you&#39;re hunting for is finally something you can just look at.</p>
<p>Have a browse through the <a href="https://assethoard.com/docs/archives">archives documentation</a> for the full picture.</p>
<p>If your hoard of assets needs taming, <a href="https://assethoard.com/downloads">download AssetHoard</a>.</p>
<hr>
<p><em>The AssetHoard Team</em></p>
]]></content:encoded>
		</item>
		<item>
			<title>How to be a game developer when you can&apos;t draw</title>
			<link>https://assethoard.com/blog/game-developer-without-artistic-skills</link>
			<guid isPermaLink="true">https://assethoard.com/blog/game-developer-without-artistic-skills</guid>
			<pubDate>Mon, 06 Jul 2026 00:00:00 GMT</pubDate>
			<dc:creator>Mark Gandolfo</dc:creator>
			<category>Indie life</category>
			<description>You don&apos;t need to be an artist to ship a good-looking game. Here&apos;s how to build one with asset packs, a few texture swaps, some lighting, and a genre that plays to your strengths.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/hero/assethoard-materials.png" alt="How to be a game developer when you can&apos;t draw" /></p>
<p><a href="https://assethoard.com/hero/assethoard-materials.png" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/hero/assethoard-materials.png" alt="A materials and texture library, the raw ingredients for building a good-looking game without drawing anything yourself" width="1920" height="1032" loading="eager" decoding="async"></a></p>
<p>There&#39;s a myth that sits on top of game development like a wet blanket: that you have to be an artist to make a game worth playing. It stops a lot of people before they start. They can code, or they can design, or they just have a good idea and the patience to build it, but they can&#39;t draw a convincing tree, so they decide the whole thing is off the table.</p>
<p>It isn&#39;t. Some of the best-looking games on your shelf were built by people who never drew a single asset. They didn&#39;t cheat, and they didn&#39;t hire out everything. They did something more useful: they got good at <em>assembling</em> rather than <em>creating</em>, and they picked projects that didn&#39;t need them to be an artist in the first place.</p>
<p>Here&#39;s how you do the same.</p>
<h2 id="separate-making-art-from-having-good-art">Separate &quot;making art&quot; from &quot;having good art&quot;</h2><p>The first thing to untangle is that these are two different skills, and only one of them is optional.</p>
<p>Making art is drawing, sculpting, animating, painting textures by hand. That takes years, and if it&#39;s not where your interest lies, that&#39;s fine. <em>Having</em> good art in your game is a different job. It&#39;s about consistency, mood, and direction. It&#39;s curation. And curation is a skill you can learn in an afternoon and get genuinely good at in a month.</p>
<p>A game that pulls fifty assets from one coherent source and lights them well will look better than a game with brilliant, hand-made assets that don&#39;t agree with each other. Players don&#39;t grade your art on how it was made. They react to whether it feels like one world. That feeling comes from consistency, not craftsmanship, and consistency is something you can engineer without drawing anything.</p>
<h2 id="start-with-a-pile-of-good-assets">Start with a pile of good assets</h2><p>The raw material is out there, most of it free. Sites like <a href="https://assethoard.com/blog/where-to-find-free-game-assets-2026">Kenney, Poly Haven, OpenGameArt and itch.io</a> publish enormous libraries of models, textures, sprites and audio, a lot of it under CC0, which means you can use it, modify it, and ship it commercially with no strings attached.</p>
<p>Before you download half the internet, a word on the thing that trips people up: <a href="https://assethoard.com/blog/game-asset-licences-explained">licences</a>. &quot;Free&quot; covers a range of terms. CC0 is do-what-you-like. CC-BY wants a credit. Some packs are non-commercial only, some marketplace assets can go in a game but not be resold, and a few have oddly specific rules buried in a readme. None of this is hard, but it does need tracking, because the day you decide to sell your game is the wrong day to discover one texture was never cleared for it. Note the licence on every asset as it comes in, not later.</p>
<p>The goal at this stage isn&#39;t to find <em>the</em> asset. It&#39;s to build a working palette: a handful of sources whose style you can live with, that share enough of a look to sit together, or that you&#39;re willing to push into agreement. Which brings us to the actual work.</p>
<h2 id="modify-dont-just-drop-in">Modify, don&#39;t just drop in</h2><p>The reason asset-pack games get a bad reputation is that people use them raw. They grab the popular free pack, drop it in untouched, and ship a game that looks exactly like the other four hundred games built from the same pack. The pack isn&#39;t the problem. Using it unchanged is.</p>
<p>You don&#39;t need to be an artist to modify assets. You need to be willing to change a few knobs:</p>
<ul>
<li><strong>Recolour and re-texture.</strong> A model is just a shape until you decide what it&#39;s made of. Take a plain crate, a rock, a wall, and swap the <a href="https://assethoard.com/blog/pbr-vs-orm-explained">material or texture</a> for a different one, and it becomes a new object. Do this consistently across a scene, pulling everything toward one palette, and a dozen mismatched packs start to look like they were made for each other. This is the single highest-leverage thing a non-artist can do.</li>
<li><strong>Rescale and recombine.</strong> Kitbashing, in the trade. Take parts from different models and assemble them into something that isn&#39;t in any pack. A building from three modular kits. A creature from two. Nobody can point at the source because the source is four sources.</li>
<li><strong>Retone the whole thing.</strong> Even leaving geometry alone, shifting the colour balance of an entire set of assets toward warm, or cold, or desaturated, immediately makes them feel authored rather than borrowed.</li>
</ul>
<p>The point of all this is deniability, in the good sense. You want the finished thing to look like <em>your</em> game, not like a shopping list. A modest amount of modification gets you most of the way there.</p>
<h2 id="let-lighting-and-post-processing-do-the-heavy-lifting">Let lighting and post-processing do the heavy lifting</h2><p>If curation is the cheapest way to look like you have art direction, lighting is the cheapest way to have it.</p>
<p>The same grey untextured scene can look like a horror game, a sunny platformer, or a moody puzzle box depending entirely on how it&#39;s lit. Lighting is not drawing. It&#39;s placing a few lights, choosing a colour temperature, and deciding where the shadows fall. Modern engines hand you global illumination, soft shadows and physically based lighting essentially for free. Spend an afternoon learning your engine&#39;s lighting system and you&#39;ll get more visual return than a week of trying to learn to paint.</p>
<p>Then stack post-processing on top. A colour-grading pass to lock in a mood. A little bloom so lights feel like lights. A vignette to pull the eye inward. A touch of grain or a subtle chromatic aberration if it suits the tone. Individually these are sliders. Together they&#39;re the difference between &quot;some assets in a scene&quot; and &quot;a look&quot;. Most of what people call <em>style</em> in a modern game is a lighting choice and a post-processing stack sitting on top of assets the developer bought.</p>
<p>None of this asks you to draw. It asks you to make decisions and be consistent about them, which is exactly the kind of thing a systems-minded developer is already good at.</p>
<h2 id="choose-a-game-that-doesnt-need-you-to-be-an-artist">Choose a game that doesn&#39;t need you to be an artist</h2><p>The smartest move of all comes before any of this: pick a project whose fun doesn&#39;t live in the visuals.</p>
<p>Some genres are art-hungry. A hand-animated 2D adventure or a character-driven action game will fight you every step of the way if you can&#39;t draw. Others barely care what they look like, as long as they look <em>clean</em>, because the enjoyment is somewhere else entirely:</p>
<ul>
<li><strong>Puzzle games.</strong> The satisfaction is in the mechanic. A clean, minimal look isn&#39;t a compromise, it&#39;s often the correct choice. Tetris didn&#39;t need a concept artist.</li>
<li><strong>Deck-builders and card games.</strong> Systems, numbers, and clever interactions carry these. You need readable cards and a tidy layout, not a portfolio.</li>
<li><strong>Strategy, management and simulation.</strong> Icons, tidy UI, and legible information beat lavish art. Players stare at spreadsheets dressed as cities and love it.</li>
<li><strong>Narrative and text-driven games.</strong> Words do the work. A strong visual frame and good typography go a long way, and neither requires drawing.</li>
<li><strong>Abstract and minimalist games.</strong> Geometric shapes, bold colour, and motion. An entire aesthetic built out of primitives, which happens to be exactly what a non-artist can produce.</li>
</ul>
<p>Picking one of these isn&#39;t settling. It&#39;s playing to your strengths. A great puzzle game built by someone who can&#39;t draw will always beat an ambitious action game abandoned because its creator couldn&#39;t produce the art it demanded.</p>
<h2 id="the-bit-nobody-tells-you-its-a-curation-problem">The bit nobody tells you: it&#39;s a curation problem</h2><p>Once you go down this road, you discover the real bottleneck isn&#39;t making things. It&#39;s <em>finding</em> things. You end up with folders of packs from a dozen sources, hundreds of textures, half of them nearly identical, and no memory of which crate went with which wall or which licence let you ship which rock.</p>
<p>This is the boring, unglamorous work that sits underneath every asset-driven game, and it&#39;s the thing that quietly kills momentum. You didn&#39;t get into this to spend your evenings <a href="https://assethoard.com/blog/how-i-manage-100000-game-assets">archaeologising your own Downloads folder</a>. A game built from assets lives or dies on whether you can actually find the right asset when you need it, see it next to the others to check they agree, and trust that its licence is cleared.</p>
<p>That&#39;s the whole reason <a href="https://assethoard.com/downloads">AssetHoard</a> exists. It&#39;s an <a href="https://assethoard.com/blog/best-offline-asset-manager-indie-developers">offline, local-first</a> library for exactly this: everything you&#39;ve collected in one place, previewable side by side so you can build a consistent palette by eye, tagged so you can find it, with <a href="https://assethoard.com/blog/game-asset-licences-explained">the licence recorded on every single asset</a> so shipping day holds no surprises. The making-a-game part is yours. The keeping-track-of-your-ingredients part is ours.</p>
<h2 id="you-were-never-blocked-by-not-being-able-to-draw">You were never blocked by not being able to draw</h2><p>If you take one thing from this: the barrier you thought was there mostly isn&#39;t. Not being able to draw stops you from being a <em>concept artist</em>. It doesn&#39;t stop you from being a game developer.</p>
<p>Get a good pile of assets. Modify them enough to make them yours. Light them well and grade them into a mood. Pick a game where the fun lives in the design, not the pixels. And keep your ingredients organised enough that building stays fun instead of turning into filing.</p>
<p>The art will be fine. Go make the game.</p>
<hr>
<p><em>The AssetHoard Team</em></p>
]]></content:encoded>
		</item>
		<item>
			<title>Windows protected your PC: fixing the SmartScreen warning on your indie game</title>
			<link>https://assethoard.com/blog/windows-protected-your-pc-indie-game</link>
			<guid isPermaLink="true">https://assethoard.com/blog/windows-protected-your-pc-indie-game</guid>
			<pubDate>Sat, 04 Jul 2026 00:00:00 GMT</pubDate>
			<dc:creator>Mark Gandolfo</dc:creator>
			<category>Indie life</category>
			<description>Ship your game on itch.io or by direct download and players hit the blue &apos;Windows protected your PC&apos; warning. Why it happens, why Steam games avoid it, and how to fix it.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/windows-protected-pc-indie/windows-protected-your-pc.png" alt="Windows protected your PC: fixing the SmartScreen warning on your indie game" /></p>
<p><a href="https://assethoard.com/blog/2026/windows-protected-pc-indie/windows-protected-your-pc.png" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/windows-protected-pc-indie/windows-protected-your-pc.png" alt="The blue "Windows protected your PC" SmartScreen warning shown when a player runs an unsigned indie game downloaded from itch.io or a direct link" title="The Windows protected your PC SmartScreen warning" width="912" height="453" loading="eager" decoding="async"></a></p>
<p>You put your game on itch.io or sell it from your own site. A player downloads the build, double-clicks it, and instead of your title screen gets a full blue panel: &quot;Windows protected your PC&quot;, publisher unknown. A good number stop right there. It is one of the quietest ways a direct-download game bleeds installs: the player never tells you, they just leave. Here is what causes it and how to fix it.</p>
<h2 id="why-does-my-game-show-the-windows-protected-your-pc-warning">Why does my game show the Windows protected your PC warning?</h2><p>It comes from Microsoft Defender SmartScreen, a reputation system in Windows. Before running a downloaded file it checks whether the file is signed by a publisher it recognises and whether that exact file has been downloaded enough to look established. A new build from an unknown developer fails both, so Windows shows the warning. Your game is not flagged as malware, only as unknown, which to a cautious player is much the same thing.</p>
<h2 id="why-steam-games-are-fine-and-yours-is-not">Why Steam games are fine and yours is not</h2><p>The warning only appears on files carrying the Mark of the Web, a tag Windows attaches to anything that arrived through a browser. Steam files never get it: the Steam client downloads, installs and launches the build itself, so nothing comes via a browser and SmartScreen never looks. That is how you can ship a completely unsigned game on Steam and no player sees a warning.</p>
<p>There is an instant fix, and it is not a certificate. It is a distribution channel. Anything that installs your build for the player sidesteps SmartScreen the way Steam does, and the Microsoft Store and the itch.io desktop app both qualify. If one fits your game, that is the fastest way out.</p>
<p>The catch is that most itch buyers just click the download in their browser. That file lands with the Mark of the Web attached and SmartScreen stops to inspect it. Same binary as the Steam version, only the delivery changed. Sell direct and sooner or later you deal with this.</p>
<h2 id="what-actually-clears-it">What actually clears it</h2><p>To sign a build you need a code signing certificate: a file that vouches the download came from you. The standard, affordable tier is an OV (organisation validation) certificate, and that is the one to get. Do not pay extra for the EV (extended validation) tier expecting the warning to vanish, it no longer bypasses SmartScreen, so OV does the same job for far less.</p>
<p>Reputation builds against two things: the file hash of each build, and your signing identity. So the routine is boring and repetitive:</p>
<ul>
<li>Sign every release with the same identity. Unsigned builds start from zero every version.</li>
<li>Timestamp at signing, so the signature stays valid after the certificate expires.</li>
<li>Do not touch the binary after signing. One changed byte breaks the signature.</li>
<li>Keep the same certificate and publisher name. Switching resets the clock.</li>
<li>Then ship clean builds and wait. Microsoft does not publish the threshold; expect several weeks and a few hundred clean installs.</li>
</ul>
<p>Your earliest players see the warning regardless. Put a line on your itch.io page and in your Discord telling people to click &quot;More info&quot; then &quot;Run anyway&quot;. Your first supporters will not mind. The ones worth shielding are the cold visitors on your store page with no reason to trust you yet.</p>
<p>So be clear about what signing buys: your name replaces &quot;Unknown publisher&quot;, and the certificate is what reputation accrues to. An unsigned build banks nothing, starting from zero every release, so without one you never get on the ladder.</p>
<h2 id="which-certificate-should-an-indie-developer-buy">Which certificate should an indie developer buy?</h2><p>Every code signing certificate now keeps its private key in FIPS-compliant hardware to curb theft: either a USB token posted to you, which must stay plugged in when you sign, or a cloud HSM run by the certificate authority, where the key stays on their hardware and you sign over an API.</p>
<div class="table-scroll"><table>
<thead>
<tr>
<th>Option</th>
<th>Who it suits</th>
<th>Rough cost</th>
<th>Physical token</th>
<th>The catch</th>
</tr>
</thead>
<tbody><tr>
<td>Microsoft Artifact Signing</td>
<td>US, Canada, EU, UK developers</td>
<td>about US$10 per month</td>
<td>No</td>
<td>Not available outside those countries</td>
</tr>
<tr>
<td>Certum Open Source</td>
<td>Genuinely free or open-source games only</td>
<td>~US$55 to US$80 set, then ~US$35 per year</td>
<td>Yes (smartcard)</td>
<td>Revoked if used on a commercial release</td>
</tr>
<tr>
<td>SSL.com IV plus eSigner</td>
<td>Solo devs selling a paid game</td>
<td>from ~US$65 per year plus a cloud signing subscription</td>
<td>No (cloud HSM)</td>
<td>Subscription on top of the certificate</td>
</tr>
<tr>
<td>Sectigo or Comodo OV/IV</td>
<td>Mainstream cheapest commercial route</td>
<td>~US$219 per year</td>
<td>Yes by default</td>
<td>Ships a USB token unless you use cloud signing</td>
</tr>
<tr>
<td>DigiCert OV/EV</td>
<td>Buyers whose contracts name DigiCert</td>
<td>~US$400 OV, ~US$685 EV</td>
<td>Yes or cloud</td>
<td>Premium pricing, rarely justified for indies</td>
</tr>
<tr>
<td>EV, any authority</td>
<td>Kernel-mode driver signing</td>
<td>from ~US$287 per year</td>
<td>Yes (HSM)</td>
<td>No longer skips SmartScreen, organisations only</td>
</tr>
</tbody></table></div>
<p>For a solo developer selling a paid game the shortlist is short: a cloud-signed individual certificate from SSL.com, or an individual or organisation certificate with a token from Sectigo or Comodo. Individual validation is the least painful: it verifies you as a person, needs no registered company, and still puts your name on the build. None of them clear the warning on day one, whatever you spend.</p>
<h2 id="what-you-have-to-prove-to-get-one">What you have to prove to get one</h2><p>Individual validation: a government-issued photo ID, sometimes proof of address, and usually a short live check where you scan your ID and record a brief video. Often issued within a day or two.</p>
<p>Organisation validation: proof the business exists (in Australia, your ABN and ASIC registration, or a letter from your accountant or lawyer), a publicly listed phone number for a callback, and an email on a domain you own. Usually one to seven business days.</p>
<p>Australian sole trader: validate as an individual with just your ID, or as a business with your ABN. The one door closed to you is Microsoft&#39;s Artifact Signing, which does not cover Australia.</p>
<h2 id="the-short-version">The short version</h2><p>Move to Steam, the Microsoft Store or the itch.io desktop app and the warning disappears at once. Stay on browser downloads and no certificate removes it on day one. Get one anyway so players see your name instead of &quot;Unknown publisher&quot;, sign every build the same way, timestamp it, and let reputation build as real people install clean copies. It is slow and there is no shortcut. Sign consistently and wait it out.</p>
]]></content:encoded>
		</item>
		<item>
			<title>You don&apos;t own your software anymore</title>
			<link>https://assethoard.com/blog/you-dont-own-anything-anymore</link>
			<guid isPermaLink="true">https://assethoard.com/blog/you-dont-own-anything-anymore</guid>
			<pubDate>Thu, 02 Jul 2026 00:00:00 GMT</pubDate>
			<dc:creator>Mark Gandolfo</dc:creator>
			<category>Indie life</category>
			<description>Every app is now a subscription and your files live on someone else&apos;s server. Here&apos;s the case for local-first, one-time purchase software you actually own.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/hero/assethoard-backgrounds.png" alt="You don&apos;t own your software anymore" /></p>
<p><a href="https://assethoard.com/hero/assethoard-backgrounds.png" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/hero/assethoard-backgrounds.png" alt="Stacks of subscription apps versus a single local-first, one-time purchase tool you own" width="1920" height="1032" loading="eager" decoding="async"></a></p>
<p>Open your subscriptions page. Go on. Add it up.</p>
<p>Most creatives I know are paying for at least a dozen recurring services before they&#39;ve even started their actual work. Design tool, file storage, music streaming, project management, note-taking, email, a couple of streaming services they forgot to cancel, two AI assistants, a font library, a stock asset site, and somewhere in there a &quot;productivity&quot; app that emails them weekly to remind them they&#39;re still being charged.</p>
<p>None of it is really yours. You&#39;re renting the lot.</p>
<h2 id="why-we-swapped-owning-software-for-subscriptions">Why we swapped owning software for subscriptions</h2><p>There used to be a simple deal. You&#39;d hand over some money, get a box (or a download, eventually), and the software was yours. Forever. The company could release a new version next year and you could ignore it. Your files were files. They opened with the program you bought, on the computer you owned, whether or not the company that made it still existed.</p>
<p>That model didn&#39;t disappear because users wanted it gone. It disappeared because the people selling software realised they could make more money the other way. Recurring revenue is more predictable. It&#39;s easier to forecast, easier to value, easier to raise money against. A one-time purchase asks the company to keep earning your business. A subscription assumes you&#39;ll forget to cancel.</p>
<p>So everything became a subscription. Tools that used to cost $50 once now cost $20 a month. Add it up over five years and you&#39;ve paid twenty-four times as much for the same thing, plus whatever features they&#39;ve quietly moved behind the next pricing tier in the meantime.</p>
<h2 id="the-maths-is-bad-the-ownership-maths-is-worse">The maths is bad. The ownership maths is worse.</h2><p>If subscriptions were just expensive, that would be one thing. You could argue the convenience is worth it, or that ongoing updates justify the price. Sometimes that&#39;s even true.</p>
<p>The bigger problem is what happens to your stuff when the relationship ends.</p>
<p>Stop paying and you don&#39;t downgrade to the version you used to own. You lose access entirely. Your files are still technically yours, in the sense that they exist somewhere, but the app you used to open them is locked behind a paywall. Your project files become hostages.</p>
<p>Worse, a lot of &quot;your&quot; data isn&#39;t actually on your machine. It lives on the company&#39;s servers. Your tags, your collections, your project history, your settings, your assets. The day they pivot, get acquired, shut down, or decide your use case isn&#39;t profitable enough to support anymore, all of that work evaporates. You get a courtesy email and a 30-day window to export what you can. The metadata you spent years building, the organisation, the structure: gone.</p>
<p>This isn&#39;t a hypothetical. It&#39;s happened to users of dozens of creative tools in the last decade. The pattern is the same every time. Beloved tool gets acquired. Pricing changes. Features get removed. Eventually the lights go out. The CEO writes a blog post thanking you for the journey. Your data is yours to retrieve, mostly, sort of, with some asterisks.</p>
<h2 id="subscriptions-also-make-every-tool-worse">Subscriptions also make every tool worse</h2><p>There&#39;s a quieter problem with the subscription model that doesn&#39;t get talked about enough: it changes what the software is for.</p>
<p>When you pay once, the software&#39;s job is to be good enough that you&#39;d recommend it. The company makes money by making something people want to buy. The incentive is to ship a great product and move on.</p>
<p>When you pay every month, the software&#39;s job is to keep you paying. The company makes money by making it harder to leave. That changes everything. Features get tied to the latest version, which is tied to the subscription. Export formats get worse, or proprietary. Cloud sync becomes mandatory so you can&#39;t take your data and run. The login screen appears earlier. The &quot;cancel&quot; button gets harder to find.</p>
<p>Some of this is malicious. Most of it isn&#39;t. It&#39;s just what happens when the incentive shifts from &quot;build something good&quot; to &quot;keep them subscribed&quot;. Even good people, building good software, drift in that direction over time.</p>
<h2 id="but-its-just-a-few-dollars-a-month">&quot;But it&#39;s just a few dollars a month&quot;</h2><p>It is. Until it isn&#39;t.</p>
<p>The few dollars become more dollars at the next round of price increases. The features you depend on get moved to the next tier. The plan you signed up for gets renamed and what was included before now costs extra. Free tiers shrink. Trial periods shorten. The yearly plan that was a discount becomes the only way to get the features you used to have on monthly.</p>
<p>And it&#39;s not one subscription. It&#39;s twenty. Each one a &quot;small&quot; recurring fee. Together they&#39;re a second rent.</p>
<p>For indie developers, who are already juggling engine licences, hosting, asset store purchases, music tools, marketplaces, store fees, and tax, another subscription isn&#39;t a small ask. It&#39;s another thing to track, another auto-renewal to forget about, another vendor with a copy of your credit card.</p>
<h2 id="local-first-means-its-yours">Local-first means it&#39;s yours</h2><p>The alternative is straightforward, and it used to be the default. Software that runs on your machine. Files that live on your disk. A licence you bought, not rented. A tool that keeps working whether or not the company is having a good quarter. It is the thinking behind every <a href="https://assethoard.com/blog/best-offline-asset-manager-indie-developers">offline, local-first asset manager</a> worth using.</p>
<p>The difference comes down to a handful of things you feel every day:</p>
<div class="table-scroll"><table>
<thead>
<tr>
<th></th>
<th>Subscription cloud app</th>
<th>Local-first, one-time purchase</th>
</tr>
</thead>
<tbody><tr>
<td>Cost over time</td>
<td>Recurring, and rising with every price increase</td>
<td>Paid once, no ongoing fee</td>
</tr>
<tr>
<td>Where your files live</td>
<td>On the company&#39;s servers</td>
<td>On your own drive</td>
</tr>
<tr>
<td>If the company shuts down</td>
<td>Access ends, with a deadline to export</td>
<td>The app keeps running, your library stays</td>
</tr>
<tr>
<td>Account required</td>
<td>Yes, a login and a profile on their servers</td>
<td>None, nothing to log in to</td>
</tr>
<tr>
<td>Who controls updates</td>
<td>The vendor, tied to your subscription</td>
<td>You decide when, or whether, to update</td>
</tr>
</tbody></table></div>
<p>That&#39;s how AssetHoard works.</p>
<p>You pay once. You <a href="https://assethoard.com/downloads">get the app</a>. It runs on your computer. Your asset library is on your drive, not on our server. Your tags, your collections, your previews, your metadata, <a href="https://assethoard.com/blog/game-asset-licences-explained">right down to the licence on each asset</a>: all local. The catalogue file is yours. You can back it up, copy it to another machine, archive it on an external drive, hand it to your future self in ten years.</p>
<p>If we vanish tomorrow, your library doesn&#39;t. The app keeps running. Your files keep opening. The work you&#39;ve put into organising your assets stays with you, because it&#39;s on your machine, in formats you can read, with no cloud dependency to lose.</p>
<p>We don&#39;t have a recurring billing system because we don&#39;t want one. We don&#39;t have an account system because you don&#39;t need one. There&#39;s no &quot;your plan includes&quot; because everyone&#39;s plan is the same: you bought it, it&#39;s yours.</p>
<h2 id="what-to-expect-from-software-you-actually-own">What to expect from software you actually own</h2><p>You shouldn&#39;t have to think this hard about whether a piece of software will exist next year. You shouldn&#39;t have to read a privacy policy to find out who owns your files. You shouldn&#39;t have to keep a spreadsheet of every recurring charge so you can remember what you&#39;re paying for.</p>
<p>The bar for software ownership used to be lower because the deal was simpler. Buying meant owning. Owning meant keeping. Keeping meant having control over your own work.</p>
<p>It can still be like that. It just takes choosing tools that are built on that assumption, and being willing to walk past the ones that aren&#39;t.</p>
<p><a href="https://assethoard.com/downloads">AssetHoard</a> is one of those tools. There are others. Look for them.</p>
<hr>
<p><em>The AssetHoard Team</em></p>
]]></content:encoded>
		</item>
		<item>
			<title>Reading Paint.NET Files Without Paint.NET</title>
			<link>https://assethoard.com/blog/paint-net-pdn-support</link>
			<guid isPermaLink="true">https://assethoard.com/blog/paint-net-pdn-support</guid>
			<pubDate>Thu, 11 Jun 2026 00:00:00 GMT</pubDate>
			<dc:creator>The AssetHoard Team</dc:creator>
			<category>AssetHoard news</category>
			<description>How we added thumbnails and metadata for .pdn files using a trick the Windows shell extension already relies on, and what we deliberately left on the table.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/paint-net-pdn-support.png" alt="Reading Paint.NET Files Without Paint.NET" /></p>
<h2 id="the-request">The Request</h2><p>A user pinged us on Discord:</p>
<blockquote>
<p>the free program Paint.NET is like super-charged MS paint with layers, been using it for graphic design for years. its .pdn files also have thumbnails in Windows, on account of a Shell extension</p>
</blockquote>
<p>In AssetHoard, <code>.pdn</code> files were landing in the library as generic blank tiles. No thumbnail, no dimensions, no layer count. For a user with a folder full of Paint.NET work, that means the grid view is useless: every asset looks identical. The fix is obvious in principle (support the format) and not so obvious in practice (Paint.NET&#39;s file format is a serialised .NET object graph, and we are not a .NET app).</p>
<p>This is the story of how we shipped real thumbnails for <code>.pdn</code> files in a few hundred lines of Rust, by piggybacking on a trick Paint.NET itself uses for the Windows Explorer preview.</p>
<h2 id="whats-actually-in-a-pdn-file">What&#39;s Actually In A <code>.pdn</code> File</h2><p>Most game-dev file formats are documented. GLTF has a spec. PSD has a spec. Aseprite publishes their format. Paint.NET is closed-source from v4 onwards, and even when v3.x was open-source, the &quot;format&quot; was really just .NET&#39;s <code>BinaryFormatter</code> serialiser dumping the in-memory <code>Document</code> object straight to disk. There&#39;s no neutral binary layout. To read the bitmap data you basically need to reconstruct the .NET runtime&#39;s idea of what a <code>Document</code> looks like.</p>
<p>But there&#39;s a wrinkle. The Paint.NET team needed Windows Explorer to render thumbnails. Spinning up the .NET runtime to deserialise a Document just so Explorer can draw a 96-pixel icon is absurd, so they did something cleverer: they prepend a small XML header to every <code>.pdn</code> file with all the cheap stuff. Dimensions, layer count, and crucially a base64-encoded PNG preview of the image.</p>
<p>The shell extension reads the XML, decodes the PNG, hands it to Explorer. The actual document data sits untouched after the header. We can do the exact same thing.</p>
<h2 id="the-bytes">The Bytes</h2><p>Here are the first eight bytes of a real <code>.pdn</code> file saved from Paint.NET v5.109, dumped as hex:</p>
<pre><code class="hljs language-plaintext">50 44 4e 33 10 04 00 3c
P  D  N  3  └──┬──┘ &lt;
            xml length</code></pre><p>Decoded:</p>
<pre><code class="hljs language-plaintext">Bytes 0-3:   &quot;PDN3&quot;                          magic
Bytes 4-6:   0x10 0x04 0x00 = 1040 (LE u24)  XML preamble length
Byte 7+:     &lt;pdnImage ...                   XML preamble starts here</code></pre><p>The 24-bit little-endian length is unusual. Most formats use 16 or 32 bits. Paint.NET went with 24, which is enough for a roughly 16MB XML header. You will never hit that limit. Our test fixtures have headers in the 1KB to 17KB range.</p>
<p>After reading those 1040 bytes of XML, you get this:</p>
<pre><code class="hljs language-xml"><span class="hljs-tag">&lt;<span class="hljs-name">pdnImage</span>
  <span class="hljs-attr">width</span>=<span class="hljs-string">&quot;980&quot;</span>
  <span class="hljs-attr">height</span>=<span class="hljs-string">&quot;980&quot;</span>
  <span class="hljs-attr">layers</span>=<span class="hljs-string">&quot;1&quot;</span>
  <span class="hljs-attr">savedWithVersion</span>=<span class="hljs-string">&quot;5.109.9343.2610&quot;</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">custom</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">thumb</span> <span class="hljs-attr">png</span>=<span class="hljs-string">&quot;iVBORw0KGgoAAAANSUhEUgAAA...&quot;</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">custom</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">pdnImage</span>&gt;</span></code></pre><p>Everything we want is right there. Width, height, layer count, the Paint.NET version that saved the file, and a base64-encoded PNG thumbnail. The <code>iVBORw0KGgo</code> prefix is what <code>0x89 P N G</code> looks like in base64, so we know the embedded payload is a real PNG.</p>
<p>After the XML, the rest of the file is the .NET BinaryFormatter blob, usually gzip-compressed (you can spot it by the <code>0x1F 0x8B</code> marker right after the XML ends). That blob holds the full-resolution layer pixel data, blend modes, layer names. We don&#39;t touch it. Parsing NRBF (the .NET Remoting Binary Format protocol) from Rust would mean either porting hundreds of lines of deserialisation code from pypdn, or shelling out to a .NET runtime. Both are huge effort for a feature most users will never notice.</p>
<h2 id="the-implementation">The Implementation</h2><p>The whole handler is about 200 lines. The interesting part is the preamble reader:</p>
<pre><code class="hljs language-rust"><span class="hljs-keyword">fn</span> <span class="hljs-title function_">read_xml_preamble</span>(path: &amp;Path) <span class="hljs-punctuation">-&gt;</span> <span class="hljs-type">Result</span>&lt;<span class="hljs-type">String</span>, HandlerError&gt; {
    <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut </span><span class="hljs-variable">file</span> = File::<span class="hljs-title function_ invoke__">open</span>(path)?;
    <span class="hljs-keyword">let</span> <span class="hljs-variable">file_size</span> = file.<span class="hljs-title function_ invoke__">metadata</span>()?.<span class="hljs-title function_ invoke__">len</span>();

    <span class="hljs-keyword">if</span> file_size &lt; <span class="hljs-number">7</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-title function_ invoke__">Err</span>(HandlerError::<span class="hljs-title function_ invoke__">ParseError</span>(
            <span class="hljs-string">&quot;PDN file shorter than 7-byte header&quot;</span>.<span class="hljs-title function_ invoke__">to_string</span>(),
        ));
    }

    <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut </span><span class="hljs-variable">header</span> = [<span class="hljs-number">0u8</span>; <span class="hljs-number">7</span>];
    file.<span class="hljs-title function_ invoke__">read_exact</span>(&amp;<span class="hljs-keyword">mut</span> header)?;

    <span class="hljs-keyword">if</span> &amp;header[<span class="hljs-number">0</span>..<span class="hljs-number">4</span>] != <span class="hljs-string">b&quot;PDN3&quot;</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-title function_ invoke__">Err</span>(HandlerError::<span class="hljs-title function_ invoke__">ParseError</span>(
            <span class="hljs-string">&quot;Not a PDN3 file - missing magic bytes&quot;</span>.<span class="hljs-title function_ invoke__">to_string</span>(),
        ));
    }

    <span class="hljs-keyword">let</span> <span class="hljs-variable">xml_len</span> = <span class="hljs-type">u32</span>::<span class="hljs-title function_ invoke__">from</span>(header[<span class="hljs-number">4</span>])
        | (<span class="hljs-type">u32</span>::<span class="hljs-title function_ invoke__">from</span>(header[<span class="hljs-number">5</span>]) &lt;&lt; <span class="hljs-number">8</span>)
        | (<span class="hljs-type">u32</span>::<span class="hljs-title function_ invoke__">from</span>(header[<span class="hljs-number">6</span>]) &lt;&lt; <span class="hljs-number">16</span>);

    <span class="hljs-keyword">let</span> <span class="hljs-variable">max_xml_len</span> = file_size.<span class="hljs-title function_ invoke__">saturating_sub</span>(<span class="hljs-number">7</span>);
    <span class="hljs-keyword">if</span> <span class="hljs-type">u64</span>::<span class="hljs-title function_ invoke__">from</span>(xml_len) &gt; max_xml_len {
        <span class="hljs-keyword">return</span> <span class="hljs-title function_ invoke__">Err</span>(HandlerError::<span class="hljs-title function_ invoke__">ParseError</span>(<span class="hljs-built_in">format!</span>(
            <span class="hljs-string">&quot;PDN XML preamble length {} exceeds remaining file size {}&quot;</span>,
            xml_len, max_xml_len
        )));
    }

    <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut </span><span class="hljs-variable">xml_buf</span> = <span class="hljs-built_in">vec!</span>[<span class="hljs-number">0u8</span>; xml_len <span class="hljs-keyword">as</span> <span class="hljs-type">usize</span>];
    file.<span class="hljs-title function_ invoke__">read_exact</span>(&amp;<span class="hljs-keyword">mut</span> xml_buf)?;

    <span class="hljs-type">String</span>::<span class="hljs-title function_ invoke__">from_utf8</span>(xml_buf)
        .<span class="hljs-title function_ invoke__">map_err</span>(|e| HandlerError::<span class="hljs-title function_ invoke__">ParseError</span>(<span class="hljs-built_in">format!</span>(<span class="hljs-string">&quot;PDN preamble is not valid UTF-8: {e}&quot;</span>)))
}</code></pre><p>A few defensive details worth calling out:</p>
<p><strong>Stack-allocated header.</strong> <code>let mut header = [0u8; 7]</code> is a fixed-size array on the stack. No heap allocation for the seven bytes we read first. We only allocate the <code>Vec&lt;u8&gt;</code> for the XML body after we&#39;ve validated the length looks sane.</p>
<p><strong>Bounds checking the length.</strong> The 24-bit length field is attacker-controlled in the sense that a malformed file could claim a 16MB preamble even when only a few KB exist on disk. We compare the declared length to the actual remaining file size before allocating. Without this check, a crafted file could trick us into allocating 16MB for what&#39;s actually a 100-byte file.</p>
<p><strong>UTF-8 validation.</strong> <code>String::from_utf8</code> returns a <code>Result</code>. If the preamble isn&#39;t valid UTF-8 (shouldn&#39;t ever happen for a real Paint.NET file, but a corrupt or hostile file might present otherwise), we return a clean error instead of producing garbled output.</p>
<p>Once we have the XML string, the metadata extraction is straightforward:</p>
<pre><code class="hljs language-rust"><span class="hljs-keyword">fn</span> <span class="hljs-title function_">extract_metadata</span>(&amp;<span class="hljs-keyword">self</span>, path: &amp;Path) <span class="hljs-punctuation">-&gt;</span> <span class="hljs-type">Result</span>&lt;serde_json::Value, HandlerError&gt; {
    <span class="hljs-keyword">let</span> <span class="hljs-variable">xml</span> = <span class="hljs-keyword">Self</span>::<span class="hljs-title function_ invoke__">read_xml_preamble</span>(path)?;
    <span class="hljs-keyword">let</span> <span class="hljs-variable">doc</span> = roxmltree::Document::<span class="hljs-title function_ invoke__">parse</span>(&amp;xml)
        .<span class="hljs-title function_ invoke__">map_err</span>(|e| HandlerError::<span class="hljs-title function_ invoke__">ParseError</span>(<span class="hljs-built_in">format!</span>(<span class="hljs-string">&quot;Failed to parse PDN preamble: {e}&quot;</span>)))?;

    <span class="hljs-keyword">let</span> <span class="hljs-variable">pdn_image</span> = doc
        .<span class="hljs-title function_ invoke__">descendants</span>()
        .<span class="hljs-title function_ invoke__">find</span>(|n| n.<span class="hljs-title function_ invoke__">tag_name</span>().<span class="hljs-title function_ invoke__">name</span>() == <span class="hljs-string">&quot;pdnImage&quot;</span>)
        .<span class="hljs-title function_ invoke__">ok_or_else</span>(|| HandlerError::<span class="hljs-title function_ invoke__">ParseError</span>(
            <span class="hljs-string">&quot;PDN preamble missing &lt;pdnImage&gt; root&quot;</span>.<span class="hljs-title function_ invoke__">to_string</span>()
        ))?;

    <span class="hljs-keyword">let</span> <span class="hljs-variable">width</span> = pdn_image.<span class="hljs-title function_ invoke__">attribute</span>(<span class="hljs-string">&quot;width&quot;</span>).<span class="hljs-title function_ invoke__">and_then</span>(|v| v.parse::&lt;<span class="hljs-type">u32</span>&gt;().<span class="hljs-title function_ invoke__">ok</span>());
    <span class="hljs-keyword">let</span> <span class="hljs-variable">height</span> = pdn_image.<span class="hljs-title function_ invoke__">attribute</span>(<span class="hljs-string">&quot;height&quot;</span>).<span class="hljs-title function_ invoke__">and_then</span>(|v| v.parse::&lt;<span class="hljs-type">u32</span>&gt;().<span class="hljs-title function_ invoke__">ok</span>());
    <span class="hljs-keyword">let</span> <span class="hljs-variable">layer_count</span> = pdn_image
        .<span class="hljs-title function_ invoke__">attribute</span>(<span class="hljs-string">&quot;layers&quot;</span>)
        .<span class="hljs-title function_ invoke__">and_then</span>(|v| v.parse::&lt;<span class="hljs-type">u32</span>&gt;().<span class="hljs-title function_ invoke__">ok</span>())
        .<span class="hljs-title function_ invoke__">unwrap_or</span>(<span class="hljs-number">0</span>);
    <span class="hljs-keyword">let</span> <span class="hljs-variable">saved_with_version</span> = pdn_image.<span class="hljs-title function_ invoke__">attribute</span>(<span class="hljs-string">&quot;savedWithVersion&quot;</span>).<span class="hljs-title function_ invoke__">map</span>(<span class="hljs-type">String</span>::from);

    <span class="hljs-comment">// ... package into JSON</span>
}</code></pre><p>We use <code>roxmltree</code>, which was already a dependency for our Krita handler (Krita files have a similar XML manifest tucked inside a zip archive). No new crates needed.</p>
<p>Thumbnail extraction follows the same shape: parse the XML, find the <code>&lt;thumb&gt;</code> element, decode the base64 PNG, hand it to the <code>image</code> crate for resizing. The whole thumbnail path is about 30 lines.</p>
<h2 id="test-fixtures">Test Fixtures</h2><p>A handler is only as trustworthy as the files you test it against. We hit the standard problem here: how do you write tests for a proprietary format without a sample file?</p>
<p>Our first move was the pypdn project on GitHub. It&#39;s an MIT-licensed Python reader and ships with <code>.pdn</code> test fixtures from Paint.NET 3.5.10 and 4.21. Useful, but those are old versions. Paint.NET v5 is a major architectural rewrite (it moved to GPU-accelerated rendering with Direct2D), and we had no proof the file format hadn&#39;t moved with it.</p>
<p>We asked the user who filed the ticket. They sent three v5-saved files: a single-layer drop shadow study, a 14-layer HUD mockup, and a concept-art piece at v5.108. All three opened cleanly with our parser. All three had identical header structure to the v3.5 and v4.21 samples from pypdn. The format has been stable for over a decade.</p>
<p>That was the moment we knew we could ship.</p>
<p>We checked the smaller two files into <code>src-tauri/tests/fixtures/</code> as <code>test.pdn</code> and <code>test_many_layers.pdn</code>. The unit tests assert real numbers from real files: 980x980 single-layer, 969x550 with 14 layers, both saved with Paint.NET versions starting with <code>5.</code>.</p>
<h2 id="what-we-deliberately-didnt-do">What We Deliberately Didn&#39;t Do</h2><p>Three things we left on the floor on purpose.</p>
<p><strong>Layer extraction.</strong> We can report the layer count (because it&#39;s in the XML preamble) but not layer names or blend modes (those are in the BinaryFormatter blob). We could parse the blob, but it&#39;s a huge engineering investment for a feature only power users would notice. The Krita and PSD handlers do surface layer names, and the PDN file details panel will look slightly thinner by comparison. We considered showing an empty layer list panel for PDN files, then realised that looks broken. Better to show nothing than to show a panel with placeholder text.</p>
<p><strong>Export as PNG.</strong> PSD and Krita both expose an &quot;Export as PNG&quot; context action because their handlers can flatten the document. We can&#39;t, because the composite pixels live in the BinaryFormatter blob. The embedded thumbnail is the wrong size and quality for a real export. So we left the action off entirely. Consistent absence is less confusing than a broken or low-quality option.</p>
<p><strong>Render profile auto-classification.</strong> Some image handlers run a heuristic to guess whether an image is pixel art (use nearest-neighbour resizing) or a photo (use bilinear). For PDN we&#39;d be running that heuristic on the embedded preview thumbnail, which is small and downsampled. The verdict would be unreliable, and a wrong verdict makes the preview look worse than no auto-classification at all. We skip it and let users override via the render profile UI if they care.</p>
<h2 id="the-cross-platform-bonus">The Cross-Platform Bonus</h2><p>One side effect of parsing the file ourselves rather than calling out to the Windows shell extension: PDN thumbnails now work even without Paint.NET installed. On macOS or Linux, the <code>.pdn</code> icon in Explorer would just be a generic file. In AssetHoard, you get the real thumbnail because we&#39;re reading the bytes directly. That makes AssetHoard a better PDN viewer than Windows Explorer for anyone who&#39;s been handed a <code>.pdn</code> file by a collaborator and doesn&#39;t have Paint.NET on their machine.</p>
<h2 id="the-takeaway">The Takeaway</h2><p>Sometimes a feature that looks like it needs a major engineering investment (&quot;parse a closed-source .NET serialisation format&quot;) turns out to have a back door that the format&#39;s own designers already built in. The Paint.NET team needed Windows Explorer thumbnails to work without spinning up .NET, so they prepended a small XML manifest with the cheap stuff. That manifest is exactly what we needed.</p>
<p>Total work: about a day, including format research, fixture sourcing, the handler itself, and seven new unit tests. The result is that <code>.pdn</code> files now sit alongside .psd and .kra in the library, with thumbnails, dimensions, and version metadata.</p>
<p>If you&#39;re building something that needs to read a proprietary format, take a hard look at what the format&#39;s official tooling already does cheaply. The hard work might already be done.</p>
]]></content:encoded>
		</item>
		<item>
			<title>CC0, CC-BY, MIT: A Game Developer&apos;s Guide to Asset Licences</title>
			<link>https://assethoard.com/blog/game-asset-licences-explained</link>
			<guid isPermaLink="true">https://assethoard.com/blog/game-asset-licences-explained</guid>
			<pubDate>Wed, 27 May 2026 00:00:00 GMT</pubDate>
			<dc:creator>Mark Gandolfo</dc:creator>
			<category>Guides</category>
			<description>A plain guide to the licences attached to game assets, what each one actually requires, and how to keep track of attribution before it becomes a problem.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/06-licenses/assethoard-licences-explained.jpg" alt="CC0, CC-BY, MIT: A Game Developer&apos;s Guide to Asset Licences" /></p>
<p><a href="https://assethoard.com/blog/2026/06-licenses/assethoard-licences-explained.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/06-licenses/assethoard-licences-explained.jpg" alt="Game asset licences explained: CC0, CC-BY, MIT and the Creative Commons modifiers" width="1620" height="1080" loading="eager" decoding="async"></a></p>
<p><strong>TLDR:</strong> <a href="#licences-at-a-glance">just take me to the table.</a></p>
<h2 id="you-downloaded-the-asset-are-you-allowed-to-ship-it">You downloaded the asset. Are you allowed to ship it?</h2><p>Most developers do not think about asset licences until it is too late to fix cleanly. The texture pack went into the build two years ago, the folder it came from is gone, and no one can say whether attribution was ever required, let alone provided. A typical asset library is assembled over years from dozens of sources, and the licence is the first thing to get separated from the file.</p>
<p>This post is a plain guide to the licences you will actually encounter on game assets and what each one requires of you. It is not legal advice. The goal is to help you recognise what you are looking at, so you know which assets are safe to use without thinking and which ones need a closer read.</p>
<h2 id="two-different-worlds-creative-commons-and-software-licences">Two different worlds: Creative Commons and software licences</h2><p>Game assets tend to arrive under one of two families of licence, and it helps to know which family you are dealing with before anything else.</p>
<p>Creative Commons licences were designed for creative works: images, audio, 3D models, written text. They are the licences you will see most often on art and sound.</p>
<p>Software licences such as MIT, Apache 2.0 and the GPL family were designed for source code. You will see these on shaders, tools, plugins, and occasionally on asset packs distributed through code repositories.</p>
<p>The distinction matters because the two families use different language and were written with different assumptions. A licence written for code does not always map cleanly onto a sprite sheet. When a 3D model arrives under the MIT licence, which happens, you are relying on a reasonable reading of terms that were not written with 3D models in mind. That is usually fine, but it is worth knowing that is what you are doing.</p>
<h2 id="the-creative-commons-licences">The Creative Commons licences</h2><p>Creative Commons is not a single licence. It is a set of licences built from a few interchangeable parts, and once you know the parts, the names stop being cryptic.</p>
<h3 id="cc0">CC0: the closest thing to no strings</h3>

<p>CC0 is a public domain dedication. The creator has waived their rights as far as the law allows. You can use the asset in a commercial project, modify it, and redistribute it, and you are not required to credit anyone.</p>
<p>CC0 is the easiest licence to work with, and it is why <a href="https://assethoard.com/blog/where-to-find-free-game-assets-2026">sites built around CC0 assets</a> are popular with developers who want to avoid licence tracking entirely. Attribution is still a courteous thing to do, and many developers credit CC0 creators anyway, but it is a courtesy and not an obligation.</p>
<p>If an asset is genuinely CC0, you can use it and effectively forget about it. The difficulty is confirming that it genuinely is CC0, which comes back to record keeping, covered further down.</p>
<h3 id="cc-by">CC-BY: free to use, credit required</h3>

<p>CC-BY allows commercial use, modification and redistribution, on one condition: you must give appropriate credit to the creator. That credit normally means naming the creator, linking to the original where practical, and indicating whether you made changes.</p>
<p>CC-BY is one of the most common licences on free game assets, and the attribution requirement is also the most commonly missed obligation in game development. Missing it is not a technicality. If you ship a commercial game using CC-BY assets and provide no credit, you are not complying with the licence.</p>
<p>The practical fix is simple and worth building into your process early. Keep a credits file from the first day of the project. Every time a CC-BY asset goes in, the creator goes into the file. Doing this continuously takes seconds. Reconstructing it the week before launch, from assets whose origins you no longer remember, can take days, and sometimes it cannot be done at all.</p>
<h3 id="the-modifier-letters">The modifier letters</h3><p>The rest of the Creative Commons system is built from modifiers added to BY. Each one adds a restriction.</p>
<p><strong id="sa">SA, ShareAlike.</strong> If you modify the asset, you must release your modified version under the same licence. For a self-contained asset this is usually manageable. The reason to be careful is that ShareAlike can, depending on how the work is combined, create obligations you did not anticipate for the things you build around the asset. If you are considering a CC-BY-SA asset for a commercial project, this is the one modifier worth reading closely rather than skimming.</p>
<p><strong id="nc">NC, NonCommercial.</strong> The asset may not be used for commercial purposes. This is the modifier that catches developers out most painfully, because a free game is not automatically a non-commercial one. If your game is on a paid storefront, carries advertising, or exists to build a commercial studio&#39;s profile, a reasonable reading is that it is commercial. An asset marked NC is not safe for a project with any commercial dimension, and a free demo for a paid game sits in genuinely uncertain territory. The safe assumption is that NC and a commercial release do not mix.</p>
<p><strong id="nd">ND, NoDerivatives.</strong> You may use the asset but you may not distribute a modified version of it. ND is uncommon on game assets and is largely impractical for them, since assets are usually resized, recoloured, recompressed or otherwise altered as a matter of course. Treat an ND asset as difficult to use in a real pipeline.</p>
<h3 id="reading-a-creative-commons-name">Reading a Creative Commons name</h3><p>Put the parts together and the names decode themselves. CC-BY-NC-SA means: credit required, no commercial use, and modifications must carry the same licence. For most commercial game projects, the presence of NC alone is enough to set the asset aside.</p>
<p>One more detail worth knowing: Creative Commons licences are versioned, most commonly 3.0 and 4.0. The differences are mostly minor for game use, but if a project is significant, the version is part of what you should record.</p>
<h2 id="the-software-licences">The software licences</h2><p>These appear on shaders, plugins, tools and code-adjacent asset packs.</p>
<p><strong id="mit">MIT</strong> is short, permissive and common. You can use, modify and distribute MIT-licensed work, including commercially. The main requirement is that you preserve the copyright notice and licence text in your distribution. For a game, that normally means including the notice somewhere in your credits or a licences screen.</p>
<p><strong id="apache">Apache 2.0</strong> is similar to MIT in spirit, permissive and commercially usable, with more explicit wording, including an explicit grant of patent rights. It also asks that you note significant changes you have made. For most game use it behaves much like MIT with a longer licence file.</p>
<p><strong id="gpl">The GPL family</strong> is the one to approach with genuine care. The GPL is a copyleft licence, and depending on how GPL-licensed code is incorporated, it can require that the larger work it becomes part of is also released under the GPL. For proprietary commercial games this is often a serious problem. The LGPL is more permissive about linking and is frequently fine for libraries used in commercial software, but GPL terms reward careful reading rather than assumption. If a tool or plugin you depend on is GPL-licensed, understand the obligation before you build on it, not after.</p>
<p>A note specific to game engines: code licences and asset store terms are separate things. The engine you use has its own licence, and an asset bought from a storefront is governed by that storefront&#39;s terms in addition to any licence the creator attaches. Those storefront terms are part of the picture and worth reading at least once.</p>
<h2 id="licences-at-a-glance">Licences at a glance</h2>

<p>This table is a quick orientation, not a replacement for reading the licence on an asset that matters. &quot;Copyleft&quot; means a modified version must be released under the same licence, and &quot;modifications allowed&quot; refers to distributing a changed version rather than editing privately.</p>
<div class="table-scroll"><table>
<thead>
<tr>
<th>Licence</th>
<th>Commercial use</th>
<th>Attribution required</th>
<th>Modifications allowed</th>
<th>Copyleft</th>
</tr>
</thead>
<tbody><tr>
<td>CC0</td>
<td>Yes</td>
<td>No</td>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<td>CC-BY</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<td>CC-BY-SA</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>CC-BY-NC</td>
<td>No</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<td>CC-BY-ND</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>CC-BY-NC-SA</td>
<td>No</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>CC-BY-NC-ND</td>
<td>No</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>MIT</td>
<td>Yes</td>
<td>Yes (keep notice)</td>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<td>Apache 2.0</td>
<td>Yes</td>
<td>Yes (keep notice)</td>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<td>GPL</td>
<td>Yes</td>
<td>Yes (keep notice)</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>LGPL</td>
<td>Yes</td>
<td>Yes (keep notice)</td>
<td>Yes</td>
<td>Library only</td>
</tr>
</tbody></table></div>
<h2 id="asset-store-and-bespoke-licences">Asset store and bespoke licences</h2><p>Not every asset uses a standard licence at all. Many marketplace assets ship under the storefront&#39;s own end user licence agreement, and some creators write their own terms.</p>
<p>These bespoke licences are where genuine surprises live. Common clauses worth checking for include limits on the number of projects or seats an asset may be used in, a requirement to hold a particular tier of licence for commercial release, restrictions on redistribution that affect whether you can include the asset in a source repository or a downloadable project template, and limits on use in AI training datasets. None of these are unusual, and none of them are visible unless you read the licence. The general rule holds: a non-standard licence is the one that most needs reading, precisely because you cannot predict it from a familiar name.</p>
<h2 id="the-real-problem-is-not-the-licences-it-is-the-record-keeping">The real problem is not the licences. It is the record keeping.</h2><p>Every licence above is straightforward enough to comply with on its own. The difficulty in practice is almost never understanding a single licence. It is that a finished game draws on a library built over years, and the licence information was never attached to the assets in a durable way.</p>
<p>The licence terms tend to live in a forum post, a storefront page, a readme that stayed in the original archive, or an email. The asset gets copied into the project. The terms do not travel with it. Two years later the asset is still in the build and the terms are unrecoverable.</p>
<p>The fix is to treat licence information as part of the asset itself, recorded at the moment the asset enters your library, while you still have the source in front of you. The specific tool matters less than the <a href="https://assethoard.com/blog/how-i-manage-100000-game-assets">habit of organising assets as they arrive</a>. What matters is that for any asset you might ship, you can answer three questions quickly: where did this come from, what licence is it under, and does that licence require attribution.</p>
<div class="figure-inline">
<p class="figure-inline__text">This is a problem <a href="https://assethoard.com">AssetHoard</a> is built to take off your hands. It is a local-first asset manager that keeps your whole library in one place, and licence and source are part of what it tracks alongside each asset, so the terms stay attached to the file instead of being scattered across the places you originally found them. When you reach a release and need a complete, accurate credits list, the information is already where the assets are. If you would like to see the rest of what it does, the <a href="https://assethoard.com">website</a> is the place to start.</p>
<a href="https://assethoard.com/features/assethoard-license.png" target="_blank" rel="noopener noreferrer" class="figure-inline__image"><img src="https://assethoard.com/features/assethoard-license.png" alt="AssetHoard showing the licence and source recorded in an asset's details panel" title="AssetHoard tracks licence and source on every asset" loading="lazy"></a>
</div>

<h2 id="the-short-version">The short version</h2><p>If you remember nothing else: CC0 means use it freely. CC-BY means use it and credit the creator. NC means keep it away from anything commercial. ShareAlike and the GPL family mean read the actual terms before you build on the asset. And whatever the licence, record where the asset came from on the day it enters your library, because the licence is worth nothing to you if you cannot find it again when you ship.</p>
<hr>
<p><em>The AssetHoard Team</em></p>
]]></content:encoded>
		</item>
		<item>
			<title>Parsing Godot .tres files and walking the resource graph</title>
			<link>https://assethoard.com/blog/parsing-godot-tres-files</link>
			<guid isPermaLink="true">https://assethoard.com/blog/parsing-godot-tres-files</guid>
			<pubDate>Sat, 09 May 2026 00:00:00 GMT</pubDate>
			<dc:creator>Mark Gandolfo</dc:creator>
			<category>AssetHoard news</category>
			<description>How AssetHoard parses Godot resource files, resolves cross-references, and reconstructs the res:// folder layout on drag-out so materials work the moment they land in your project.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/releases/v0.1.13/assethoard-v0.1.13.png" alt="Parsing Godot .tres files and walking the resource graph" /></p>
<p><a href="https://assethoard.com/releases/v0.1.13/assethoard-v0.1.13.png" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/releases/v0.1.13/assethoard-v0.1.13.png" alt="AssetHoard library showing Godot .tres assets — material spheres, sprite frames animations and tilesets — with a SpriteFrames preview panel open on the right" title="AssetHoard v0.1.13: Godot .tres support with material, SpriteFrames and TileSet previews" width="1278" height="688" loading="eager" decoding="async"></a></p>
<p>A <code>.tres</code> file looks innocent. Open one in a text editor and you get something close to INI: a header, a few sections, some key-value pairs. Tiny. Readable. Surely a couple of regexes away from being parseable.</p>
<p>This impression survives roughly five minutes.</p>
<p>Godot resource files are a custom format that references other resources by path, by UID, and sometimes both. A <code>StandardMaterial3D.tres</code> is a small text file pointing at textures that live somewhere else. Move just the <code>.tres</code> to a different project and the material is broken on the other end. The textures cannot be found. The material falls back to magenta. Your asset is, for any practical purpose, useless.</p>
<p>This is a problem for an external asset manager. The whole point of AssetHoard is that you find a thing in one place and use it somewhere else. If &quot;use it somewhere else&quot; only works for self-contained files, then half of what comes out of a Godot project is excluded.</p>
<p>So <a href="https://assethoard.com/releases/0.1.13" title="Read the AssetHoard v0.1.13 release notes">v0.1.13</a> ships proper <code>.tres</code> support. Materials, ShaderMaterials, SpriteFrames and TileSets all get real previews instead of generic icons. More importantly, dragging a <code>.tres</code> out of AssetHoard now walks its reference graph and pulls every linked file along with it, reconstructing the <code>res://</code> folder layout at the drop location. Drop the result into a Godot project and it just works.</p>
<p>This post is the long version of how that got built. Lexer, parser, resource resolution, rendering, and the drag-out behaviour. There are sharp edges in every layer.</p>
<h2 id="the-tres-godot-format">The .tres Godot format</h2><p>Before parsing anything you have to understand what you are parsing. The <code>.tres</code> format is text-based, deceptively simple at a glance, and full of corners.</p>
<p>A minimal example:</p>
<pre><code class="hljs language-plaintext">[gd_resource type=&quot;StandardMaterial3D&quot; load_steps=3 format=3 uid=&quot;uid://abc123&quot;]

[ext_resource type=&quot;Texture2D&quot; uid=&quot;uid://def456&quot; path=&quot;res://textures/stone_albedo.png&quot; id=&quot;1_albedo&quot;]
[ext_resource type=&quot;Texture2D&quot; uid=&quot;uid://ghi789&quot; path=&quot;res://textures/stone_normal.png&quot; id=&quot;2_normal&quot;]

[resource]
albedo_texture = ExtResource(&quot;1_albedo&quot;)
normal_enabled = true
normal_texture = ExtResource(&quot;2_normal&quot;)</code></pre><p>The shape is sections in square brackets, each with a type and some attributes, followed by key-value pairs. <code>[ext_resource]</code> blocks declare external dependencies. <code>[resource]</code> is the main resource definition. Values can be primitives (numbers, strings, booleans) or constructor-like calls (<code>ExtResource(...)</code>, <code>Color(0.5, 0.5, 0.5, 1)</code>, <code>Vector3(0, 1, 0)</code>).</p>
<p>But this is the friendly version. Real files in real projects are denser, and the parser splits the work in two. A structural pass in <code>handlers/tres.rs</code> reads the <code>[gd_resource]</code> header, every <code>[ext_resource]</code> line, and every <code>[sub_resource]</code> block, because that grammar is uniform across resource types. The <code>[resource]</code> block is then handed off to a per-type body parser, dispatched on <code>header.resource_type</code>:</p>
<pre><code class="hljs language-rust"><span class="hljs-keyword">pub</span> <span class="hljs-keyword">fn</span> <span class="hljs-title function_">parse_tres</span>(content: &amp;<span class="hljs-type">str</span>) <span class="hljs-punctuation">-&gt;</span> <span class="hljs-type">Result</span>&lt;TresFile, TresParseError&gt; {
    <span class="hljs-keyword">let</span> <span class="hljs-variable">structure</span> = <span class="hljs-title function_ invoke__">parse_tres_structure</span>(content)?;
    <span class="hljs-keyword">let</span> <span class="hljs-variable">body</span> = <span class="hljs-keyword">match</span> structure.header.resource_type.<span class="hljs-title function_ invoke__">as_str</span>() {
        <span class="hljs-string">&quot;SpriteFrames&quot;</span> =&gt; TresBody::<span class="hljs-title function_ invoke__">SpriteFrames</span>(
            crate::handlers::tres_spriteframes::<span class="hljs-title function_ invoke__">parse_sprite_frames</span>(content)?,
        ),
        <span class="hljs-string">&quot;TileSet&quot;</span> =&gt; TresBody::<span class="hljs-title function_ invoke__">TileSet</span>(
            crate::handlers::tres_tileset::<span class="hljs-title function_ invoke__">parse_tile_set</span>(content)?,
        ),
        _ =&gt; TresBody::<span class="hljs-title function_ invoke__">Flat</span>(<span class="hljs-title function_ invoke__">parse_resource_block_flat</span>(content)),
    };
    <span class="hljs-title function_ invoke__">Ok</span>(TresFile { structure, body })
}</code></pre><p>Anything without a dedicated parser falls into <code>TresBody::Flat</code>, a <code>HashMap&lt;String, String&gt;</code> that captures multi-line array and dict values verbatim by tracking bracket balance via a string-aware scanner. That alone covers <code>StandardMaterial3D</code>, <code>ShaderMaterial</code>, <code>FontFile</code>, <code>Environment</code>, and the long tail of <code>Resource</code> subclasses where the body is just <code>key = value</code> pairs.</p>
<h2 id="format-quirks-and-how-we-handle-them">Format quirks and how we handle them</h2><div class="table-scroll"><table>
<thead>
<tr>
<th>Corner case</th>
<th>What it looks like</th>
<th>How we handle it</th>
</tr>
</thead>
<tbody><tr>
<td>Format header</td>
<td><code>format=2</code> (Godot 3) vs <code>format=3</code> (Godot 4). Same <code>.tres</code> extension, near-unrelated grammars for TileSets.</td>
<td>TileSet parser branches on the format attribute. Godot 3 keys tiles by integer on <code>[resource]</code>; Godot 4 uses <code>TileSetAtlasSource</code> sub-resources.</td>
</tr>
<tr>
<td><code>ExtResource</code> styles</td>
<td><code>ExtResource(&quot;1_albedo&quot;)</code> (Godot 4, quoted id) vs <code>ExtResource(1)</code> (Godot 3, unquoted integer).</td>
<td>Lexer accepts both.</td>
</tr>
<tr>
<td>AtlasTexture vs ExtResource frames</td>
<td>A SpriteFrames frame can be <code>SubResource(&quot;AtlasTexture_idle_0&quot;)</code> (atlas slice) or <code>ExtResource(&quot;1_xyz&quot;)</code> (whole texture).</td>
<td>Both shapes handled via a <code>FrameTextureRef</code> enum.</td>
</tr>
<tr>
<td>Aseprite Wizard metadata</td>
<td><code>metadata/_aseprite_wizard_*</code> keys written after the animations array, including a multi-line nested dict.</td>
<td>Locate <code>animations =</code> by key name rather than position, so trailing junk is ignored.</td>
</tr>
<tr>
<td>Trailing commas</td>
<td>Godot 4 emits them in dicts and arrays; Godot 3 does not.</td>
<td>Variant parser tolerates both.</td>
</tr>
<tr>
<td><code>StringName</code> literals</td>
<td><code>&amp;&quot;idle&quot;</code> form for Godot 4 dict keys, distinct from regular strings.</td>
<td>Lexed as a separate token type.</td>
</tr>
<tr>
<td>Type constructors</td>
<td><code>Color(...)</code>, <code>Vector2(...)</code>, <code>Rect2(...)</code>, <code>PackedColorArray(...)</code> and friends.</td>
<td>Lexed as opaque <code>TypedCall { name, raw_args }</code> tokens. Preserved verbatim; specific call sites parse <code>Rect2</code> and <code>Vector2i</code> by hand when needed.</td>
</tr>
<tr>
<td>One-PNG-per-tile TileSets</td>
<td>Godot 3 <code>hexagonal_map.tres</code> references 26 PNGs, one per tile.</td>
<td>Normalised into &quot;N atlas sources × 1 tile each&quot; so the rest of the pipeline does not fork.</td>
</tr>
<tr>
<td>Multi-cell tiles</td>
<td>Godot 4&#39;s <code>size_in_atlas = Vector2i(W, H)</code> declares a tile spanning W×H cells.</td>
<td>Preview compositor honours it so a 2×1 tree draws at double width.</td>
</tr>
</tbody></table></div>
<p>What we explicitly do not support: GDScript-defined custom resources (no metadata to render against, no safe way to execute), <code>.tscn</code> scenes (most of the format would work, but it is not in <a href="https://assethoard.com/releases/0.1.13" title="Read the AssetHoard v0.1.13 release notes">v0.1.13</a>), <code>TileSetScenesCollectionSource</code> (silently skipped), and Godot 3 SpriteFrames (the format is fundamentally different and currently returns an empty result rather than a partial parse).</p>
<h2 id="lexing-and-parsing">Lexing and parsing</h2><p>The lexer and parser live in their own module, <code>godot_variant/</code>, with a hard rule that it imports only from <code>std</code> and <code>serde</code>. Nothing else in the crate. The isolation is deliberate: it is a candidate to extract as a workspace crate later, then maybe to crates.io if it turns out to be useful to anyone else.</p>
<p>The token enum:</p>
<pre><code class="hljs language-rust"><span class="hljs-keyword">pub</span> <span class="hljs-keyword">enum</span> <span class="hljs-title class_">Token</span> {
    LBracket, RBracket, LBrace, RBrace, Comma, Colon,
    <span class="hljs-title function_ invoke__">String</span>(<span class="hljs-type">String</span>),
    <span class="hljs-title function_ invoke__">StringName</span>(<span class="hljs-type">String</span>),                              <span class="hljs-comment">// &amp;&quot;idle&quot;</span>
    <span class="hljs-title function_ invoke__">Int</span>(<span class="hljs-type">i64</span>),
    <span class="hljs-title function_ invoke__">Float</span>(<span class="hljs-type">f64</span>),                                      <span class="hljs-comment">// includes inf, -inf, nan</span>
    <span class="hljs-title function_ invoke__">Bool</span>(<span class="hljs-type">bool</span>),
    Null,
    <span class="hljs-title function_ invoke__">SubResourceRef</span>(<span class="hljs-type">String</span>),                          <span class="hljs-comment">// SubResource(&quot;AtlasTexture_xyz&quot;)</span>
    <span class="hljs-title function_ invoke__">ExtResourceRef</span>(<span class="hljs-type">String</span>),                          <span class="hljs-comment">// ExtResource(&quot;1_abc&quot;) or ExtResource(1)</span>
    TypedCall { name: <span class="hljs-type">String</span>, raw_args: <span class="hljs-type">String</span> },    <span class="hljs-comment">// Color(1,1,1,1), Vector2(0,0), ...</span>
}</code></pre><p><code>tokenize(input: &amp;str) -&gt; Result&lt;Vec&lt;Token&gt;, LexError&gt;</code> returns a <code>Vec</code> rather than an iterator. Inputs are tiny (a few KB per <code>animations = [...]</code> blob), the parser benefits from look-ahead, and any error short-circuits the batch.</p>
<p>The parser is recursive descent and panic-free by construction. No <code>unwrap()</code>, no out-of-bounds indexing, every fallible operation returns <code>Result</code>. The AST is intentionally minimal:</p>
<pre><code class="hljs language-rust"><span class="hljs-keyword">pub</span> <span class="hljs-keyword">enum</span> <span class="hljs-title class_">VariantValue</span> {
    <span class="hljs-title function_ invoke__">Dict</span>(HashMap&lt;<span class="hljs-type">String</span>, VariantValue&gt;),
    <span class="hljs-title function_ invoke__">Array</span>(<span class="hljs-type">Vec</span>&lt;VariantValue&gt;),
    <span class="hljs-title function_ invoke__">String</span>(<span class="hljs-type">String</span>),
    <span class="hljs-title function_ invoke__">StringName</span>(<span class="hljs-type">String</span>),
    <span class="hljs-title function_ invoke__">Int</span>(<span class="hljs-type">i64</span>),
    <span class="hljs-title function_ invoke__">Float</span>(<span class="hljs-type">f64</span>),
    <span class="hljs-title function_ invoke__">Bool</span>(<span class="hljs-type">bool</span>),
    Null,
    <span class="hljs-title function_ invoke__">SubResourceRef</span>(<span class="hljs-type">String</span>),
    <span class="hljs-title function_ invoke__">ExtResourceRef</span>(<span class="hljs-type">String</span>),
    TypedCall { name: <span class="hljs-type">String</span>, raw_args: <span class="hljs-type">String</span> },
}</code></pre><p>I did not seriously evaluate <code>nom</code>, <code>chumsky</code> or <code>pest</code>. The format is just irregular enough that a generic combinator approach would have been more code than the focused state machine, and the no-third-party-dep rule on the module makes it easier to lift into its own crate later.</p>
<p>Errors do not tear the whole parse down. The structural pass skips malformed <code>[ext_resource]</code> and <code>[sub_resource]</code> blocks and continues. A SpriteFrames body that fails to lex or parse on a <code>format=2</code> file gets downgraded to an empty result with a debug log; on <code>format=3</code> the error propagates. The TileSet parser is best-effort throughout, with partial results always valid:</p>
<pre><code class="hljs language-rust"><span class="hljs-keyword">let</span> <span class="hljs-variable">variant</span> = <span class="hljs-keyword">match</span> lexer::<span class="hljs-title function_ invoke__">tokenize</span>(animations_text) {
    <span class="hljs-title function_ invoke__">Ok</span>(toks) =&gt; <span class="hljs-keyword">match</span> parser::<span class="hljs-title function_ invoke__">parse_variant</span>(toks) {
        <span class="hljs-title function_ invoke__">Ok</span>(v) =&gt; v,
        <span class="hljs-title function_ invoke__">Err</span>(e) =&gt; {
            <span class="hljs-keyword">if</span> format == <span class="hljs-number">2</span> {
                log::debug!(
                    <span class="hljs-string">&quot;parse_sprite_frames: format=2 graceful degradation (parse): {}&quot;</span>,
                    e
                );
                <span class="hljs-keyword">return</span> <span class="hljs-title function_ invoke__">Ok</span>(SpriteFramesData::<span class="hljs-title function_ invoke__">empty</span>());
            }
            <span class="hljs-keyword">return</span> <span class="hljs-title function_ invoke__">Err</span>(TresParseError::<span class="hljs-title function_ invoke__">BodyParseError</span>(<span class="hljs-built_in">format!</span>(
                <span class="hljs-string">&quot;failed to parse animations Variant: {}&quot;</span>, e
            )));
        }
    },
    ...
};</code></pre><p>Unit tests cover every Variant shape we have seen in the wild: Godot 4 quoted refs, Godot 3 unquoted-int refs, dicts with <code>StringName</code> keys, arrays of dicts, nested <code>PackedColorArray</code> strings containing parens. Plus panic-free torture tests for unterminated strings, unbalanced parens, garbage bytes and lone <code>-</code>.</p>
<h2 id="resolving-references">Resolving references</h2><p>Parsing produces a resource with a list of declared external references. That is the easy half. The hard half is resolution: figuring out where each <code>res://</code> path actually lives on disk, whether the referenced file is in your library, and what to do when it is not.</p>
<p>Resources nest. A <code>StandardMaterial3D</code> references textures. A SpriteFrames might reference an AtlasTexture sub_resource that itself points at a PNG. A TileSet references atlas textures and can chain into terrain definitions. The full picture for any one <code>.tres</code> is a directed graph, sometimes several layers deep, but the resolver does not treat it as one. It runs per-reference on every <code>.tres</code> it sees during import, and the graph emerges implicitly as each asset&#39;s resolved entries link up to others in the library. Walking the graph as a graph only matters at drag-out time.</p>
<p>AssetHoard works on user-imported folders, and there is no guarantee a <code>.tres</code> lives inside a real Godot project tree. The resolver does not look for a <code>project.godot</code> file. Instead, for each <code>res://</code> reference on a single <code>.tres</code>, it walks up the directory tree from the <code>.tres</code>&#39;s on-disk location (capped at depth 10) and at each level tries two candidates: <code>&lt;ancestor&gt;/&lt;full stripped path&gt;</code> to preserve the directory structure inside <code>res://</code>, and <code>&lt;ancestor&gt;/&lt;basename&gt;</code> as a flattened-pack fallback for authors who stripped the <code>textures/</code> prefix when distributing. First match wins.</p>
<pre><code class="hljs language-rust"><span class="hljs-keyword">pub</span> <span class="hljs-keyword">fn</span> <span class="hljs-title function_">resolve_res_path</span>(res_path: &amp;<span class="hljs-type">str</span>, tres_file: &amp;Path) <span class="hljs-punctuation">-&gt;</span> <span class="hljs-type">Option</span>&lt;PathBuf&gt; {
    <span class="hljs-keyword">let</span> <span class="hljs-variable">rel</span> = res_path.<span class="hljs-title function_ invoke__">strip_prefix</span>(<span class="hljs-string">&quot;res://&quot;</span>)?;
    <span class="hljs-keyword">let</span> <span class="hljs-variable">rel_path</span> = Path::<span class="hljs-title function_ invoke__">new</span>(rel);
    <span class="hljs-keyword">let</span> <span class="hljs-variable">basename</span> = rel_path.<span class="hljs-title function_ invoke__">file_name</span>();

    <span class="hljs-keyword">const</span> MAX_ANCESTOR_DEPTH: <span class="hljs-type">usize</span> = <span class="hljs-number">10</span>;

    <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut </span><span class="hljs-variable">current</span> = tres_file.<span class="hljs-title function_ invoke__">parent</span>()?;
    <span class="hljs-keyword">for</span> <span class="hljs-variable">_</span> <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>..MAX_ANCESTOR_DEPTH {
        <span class="hljs-keyword">let</span> <span class="hljs-variable">full</span> = current.<span class="hljs-title function_ invoke__">join</span>(rel_path);
        <span class="hljs-keyword">if</span> full.<span class="hljs-title function_ invoke__">exists</span>() { <span class="hljs-keyword">return</span> <span class="hljs-title function_ invoke__">Some</span>(full); }
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> <span class="hljs-variable">Some</span>(name) = basename {
            <span class="hljs-keyword">let</span> <span class="hljs-variable">flat</span> = current.<span class="hljs-title function_ invoke__">join</span>(name);
            <span class="hljs-keyword">if</span> flat.<span class="hljs-title function_ invoke__">exists</span>() { <span class="hljs-keyword">return</span> <span class="hljs-title function_ invoke__">Some</span>(flat); }
        }
        <span class="hljs-keyword">match</span> current.<span class="hljs-title function_ invoke__">parent</span>() {
            <span class="hljs-title function_ invoke__">Some</span>(p) =&gt; current = p,
            <span class="hljs-literal">None</span> =&gt; <span class="hljs-keyword">break</span>,
        }
    }
    <span class="hljs-literal">None</span>
}</code></pre><p>The resolver runs as a post-import pass via the <code>resolve_tres_references</code> Tauri command. For each <code>.tres</code> asset it reads the header to assign a <code>file_type</code> of <code>material</code> / <code>spriteframes</code> / <code>tileset</code> / <code>package</code>, walks every <code>[ext_resource]</code> block, attempts to resolve each <code>res://</code> path to a real file on disk, matches resolved paths against existing library assets, and writes the lot into <code>metadata.references[]</code> on the asset row. The pass is idempotent. Rerunning it is cheap and self-healing, so a previously-missing dependency that gets imported later picks up <code>resolved_asset_id</code> on the next pass.</p>
<p>References are not a separate table. They live as a JSON array on <code>assets.metadata</code>:</p>
<pre><code class="hljs language-json"><span class="hljs-punctuation">{</span>
  <span class="hljs-attr">&quot;references&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span>
    <span class="hljs-punctuation">{</span>
      <span class="hljs-attr">&quot;path&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;res://textures/stone_albedo.png&quot;</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">&quot;resolved_asset_id&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-number">1247</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">&quot;disk_path&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;/abs/path/to/stone_albedo.png&quot;</span><span class="hljs-punctuation">,</span>
      <span class="hljs-attr">&quot;slot&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;albedo_texture&quot;</span>
    <span class="hljs-punctuation">}</span>
  <span class="hljs-punctuation">]</span>
<span class="hljs-punctuation">}</span></code></pre><p><code>categorize_tres_references</code> splits that array into three buckets at read time by stat&#39;ing each <code>disk_path</code>: <strong>imported</strong> (<code>resolved_asset_id</code> populated), <strong>importable</strong> (unresolved but the disk path exists), <strong>missing</strong> (unresolved and the file cannot be located). Stat happens at categorise-time rather than resolve-time, so a file moved between sessions does not leave stale UI state.</p>
<p>Resolution is eager at import. The whole graph for a <code>.tres</code> is walked once, the result is cached in <code>metadata.references[]</code>, and subsequent reads (preview, drag-out, references panel) never re-walk. The trade-off is staleness: if a referenced file moves on disk after import without rerunning the resolver, the cached <code>disk_path</code> is wrong. The categorise step&#39;s stat call covers the missing-now case, and there is a &quot;Re-resolve Godot References&quot; context action to force a re-walk.</p>
<p>Cycle handling lives in the drag-out path rather than the resolver itself. <code>gather_tres_drag_payload</code> recurses through <code>.tres → .tres</code> chains using a BFS queue with both a depth cap of 5 and a visited-asset-id <code>HashSet</code>, so a <code>.tres</code> referencing a <code>.tres</code> referencing back stops cleanly.</p>
<h2 id="rendering-each-resource-type">Rendering each resource type</h2><p>Parsing and resolution are mechanical. Rendering is where the work actually became interesting, because each resource type needs its own thinking about what a useful preview looks like.</p>
<p>A useful preview is the one that lets you tell two similar resources apart at a glance. A generic &quot;Material&quot; icon fails this test immediately. A solid grey sphere is barely better. The goal is a thumbnail where the difference between <code>stone_rough.tres</code> and <code>stone_polished.tres</code> is visible without opening either file.</p>
<p>One overall architectural choice worth flagging up front: PBR rendering happens on the frontend via Three.js, not headless in Rust. Tauri is already shipping a WebView, the WebGL renderer is right there, and the result is a live, rotatable preview rather than a baked image. Thumbnails for the grid view are captured from the same renderer via <code>canvas.toDataURL()</code> and round-tripped to disk. One pipeline, two outputs.</p>
<div class="figure-inline figure-inline--reverse">
<p class="figure-inline__text"><strong>StandardMaterial3D, ORMMaterial3D, SpatialMaterial.</strong> Rendered to a real sphere using <code>THREE.MeshStandardMaterial</code> and <code>THREE.SphereGeometry</code>, with an IBL studio environment for reflections and a single directional key light. The thumbnail generator keeps a singleton offscreen <code>WebGLRenderer</code> (<code>preserveDrawingBuffer: true</code>), swaps the maps onto a reused sphere, and captures the result. The preview is a real material, not a representation.</p>
<div class="figure-inline__image"><video controls muted playsinline preload="metadata"><source src="https://assethoard.com/blog/2026/godot-tech/assethoard-godot-material.mp4" type="video/mp4"></video></div>
</div>

<p><strong>ShaderMaterial.</strong> Render the linked <code>.gdshader</code> source as code with GLSL syntax highlighting via highlight.js. Trying to render an arbitrary user shader without running it is impossible, and running untrusted user shaders against a stub uniform set produces garbage at best. Code preview turns out to be more useful in practice. You can scan the shader and recognise it immediately, which is more than you can say for yet another generic sphere.</p>
<p><strong>FastNoiseLite + Gradient.</strong> These are procedural materials with no texture references at all. The naive approach is &quot;no textures, no preview, fall back to icon&quot;, which produces a folder full of identical blank spheres. Instead we feed the Godot 4 <code>FastNoiseLite</code> parameters extracted from the <code>.tres</code> body into the <code>fastnoise-lite</code> npm package, which is a JavaScript port of the same library Godot itself uses. The noise is sampled into a canvas, the gradient is applied pixel by pixel, and the result plugs into the same texture slot a real albedo map would. It will not be pixel-identical to Godot. RNG seed handling and Godot&#39;s seamless mode (4D noise sampled on a torus) differ. But visually it is equivalent, which is the point. An ice noise material looks like ice and a lava one looks like lava.</p>
<div class="figure-inline">
<p class="figure-inline__text"><strong>SpriteFrames.</strong> Animation playback. Frame data is pre-flattened in Rust during the import pass, so each frame carries its source asset id, disk path, atlas region (<code>sx, sy, sw, sh</code>) and per-frame duration multiplier. The frontend does not need to walk sub_resources at playback time. The preview component blits each frame's region onto a canvas with a <code>setTimeout</code>-driven loop, with animation tabs, transport controls, frame counter, and 0.5×/1×/2× speed control. Trying to communicate "this is animated" via a static image is a losing battle, so we just animate it.</p>
<div class="figure-inline__image"><video controls muted playsinline preload="metadata"><source src="https://assethoard.com/blog/2026/godot-tech/assethoard-godot-spriteframes.mp4" type="video/mp4"></video></div>
</div>

<div class="figure-inline figure-inline--reverse">
<p class="figure-inline__text"><strong>TileSet.</strong> Interactive zoom and pan preview. The Rust parser produces a normalised <code>TileSetData</code> covering atlas sources, tile counts, terrain names (set-major, so multi-set TileSets keep their grouping), custom data layer names, and physics and navigation layer counts. The Svelte preview renders the atlas with margin and separation honoured, multi-cell tile spans drawing across the cells they cover, and tooltip name lookup. The Godot 3 sub-rect path bakes the offset into per-tile <code>explicit_region</code> so the same renderer handles both formats.</p>
<div class="figure-inline__image"><video controls muted playsinline preload="metadata"><source src="https://assethoard.com/blog/2026/godot-tech/assethoard-godot-tilesets.mp4" type="video/mp4"></video></div>
</div>

<p><strong>Custom resource scripts.</strong> There is no safe way to run user GDScript from an external tool, so these get an &quot;indexed but no preview&quot; fallback with the flat-properties list as their detail view. This is the weakest part of the current implementation and probably the area I would most welcome community input on.</p>
<h2 id="drag-out-reconstructing-res">Drag-out: reconstructing res://</h2><p>The final piece is the drag-out behaviour, and this is the bit I am most pleased with.</p>
<p>When a user drags a <code>.tres</code> out of AssetHoard, the OS drag-and-drop pipeline expects a list of file paths. The naive implementation hands over the path to the <code>.tres</code> itself. The user drops it into their Godot project, and immediately discovers the textures are not there.</p>
<video controls muted playsinline preload="metadata">
  <source src="https://assethoard.com/pages/godot-asset-manager/assethoard-godot-dragnaddrop.mp4" type="video/mp4">
</video>

<p>The fix is conceptually simple. Before the drag begins, build a temporary directory containing the <code>.tres</code> and every file in its dependency graph, arranged in the <code>res://</code> layout each file expects. Hand the OS that whole tree as the drag payload. The user drops it, the operating system copies the lot, and the <code>.tres</code> finds its textures because the relative paths still resolve.</p>
<p>The drag-out logic lives in <code>commands/tres_drag.rs</code>. Two Tauri commands cover the cases: <code>stage_tres_for_drag</code> for one or more <code>.tres</code> assets dragged directly, and <code>stage_tres_bundle_for_drag</code> for dragging a bundle whose contents include <code>.tres</code> files. The bundle command merges the trees so the drop lands as a single self-contained project root rather than per-asset subdirectories.</p>
<p>Layout reconstruction is direct: the staging root <em>is</em> the project root. Every reference lands at <code>&lt;staging_root&gt;/&lt;res_path stripped of &quot;res://&quot;&gt;</code>, and the <code>.tres</code> itself goes at the staging root using just its filename. After the user drops the staging tree into a Godot project, the <code>res://</code> references resolve from the new location.</p>
<pre><code class="hljs language-rust"><span class="hljs-keyword">let</span> <span class="hljs-variable">staging_root</span> = std::env::<span class="hljs-title function_ invoke__">temp_dir</span>()
    .<span class="hljs-title function_ invoke__">join</span>(<span class="hljs-string">&quot;assethoard_drag&quot;</span>)
    .<span class="hljs-title function_ invoke__">join</span>(<span class="hljs-built_in">format!</span>(<span class="hljs-string">&quot;tres-{}&quot;</span>, uuid::Uuid::<span class="hljs-title function_ invoke__">new_v4</span>()));</code></pre><p>Source priority for each reference is <code>resolved_asset_id</code> first (use the library copy, which is canonical and never stale), then <code>disk_path</code> if it still exists, then skip if missing. A <code>join_relative</code> helper walks the path segment by segment, dropping <code>..</code>, <code>.</code> and empty segments, and replacing Windows-illegal characters (<code>\ : * ? &quot; &lt; &gt; |</code>) so a malformed <code>res://</code> path cannot escape the staging root. Files are copied via <code>std::fs::copy</code> rather than symlinking. Symlinks on Windows need elevation, the asset manager has no idea what filesystem the drop target sits on, and a copy is the only thing that survives a drop into a network share or a USB drive.</p>
<p>Lifetime is per-drag, not per-process. The frontend gets back a <code>staging_root</code> path plus a list of <code>dragged_paths</code> (the top-level entries inside the staging root, since dragging the staging root itself would prefix every <code>res://</code> with the folder name and break resolution). When the OS drag-completed callback fires, the frontend invokes <code>cleanup_tres_drag_staging</code>, which <code>remove_dir_all</code>s the staging directory while refusing to touch anything outside the <code>assethoard_drag</code> namespace as a safety check. As belt-and-braces against a crash mid-drag leaving directories behind, <code>cleanup_old_drag_staging</code> runs on app startup and sweeps any <code>tres-*</code> directories with stale mtimes.</p>
<p>The drag is best-effort, not all-or-nothing. Missing dependencies are skipped with a debug log rather than aborting, so the user gets a valid tree of whatever did resolve and can fill the gaps by hand. The references panel has already surfaced anything in the missing bucket before they get to drag, so this is not a surprise.</p>
<p>Within a single drag, identical sources are deduped and target-path collisions follow first-write-wins, with a warning logged. A real collision means the resolver is wrong upstream.</p>
<p>The behaviour is always-on for <code>.tres</code> assets and not user-configurable.</p>
<h2 id="what-is-next">What is next</h2><p>A few things I am still working on or thinking about.</p>
<p><strong>UID-based path recovery.</strong> UIDs are parsed and stored on the <code>[gd_resource]</code> header and on each <code>[ext_resource]</code> block, but resolution is path-only today. When a referenced file moves and the path goes stale, falling back to a library-wide UID index is the planned recovery path. Tracked as a separate card.</p>
<p><strong>Custom resource scripts.</strong> Anything driven by user GDScript currently gets the &quot;indexed but no preview&quot; fallback. The cleanest path forward is probably a render hint that resource authors can embed in their own resources, which is something I would want to coordinate with the Godot community before defining. Would love to hear what shape that should take.</p>
<p><strong>Scene file (<code>.tscn</code>) parsing.</strong> Scene files share most of the resource format and would unlock a lot. Currently in scope but not in <a href="https://assethoard.com/releases/0.1.13" title="Read the AssetHoard v0.1.13 release notes">v0.1.13</a>.</p>
<p><strong>GDExtension resources.</strong> Outside the scope of what an external tool can reasonably parse without engine-specific knowledge. Probably an &quot;indexed but no preview&quot; forever, unless GDExtension authors want to ship metadata alongside their resources.</p>
<p><strong>Extracting <code>godot_variant</code> as a crate.</strong> The lexer and parser module is <code>std + serde</code> only on purpose. If there is appetite for a published crate that handles Godot 3 and Godot 4 Variant grammar with graceful error recovery, get in touch.</p>
<p>If you have run into adjacent problems, whether that is building tooling that consumes Godot resources from outside the editor, or wrestling with the format yourself, I would genuinely like to hear about it. <a href="https://assethoard.com/discord" title="Join the AssetHoard Discord server">Discord</a> or the <a href="https://assethoard.com/contact" title="Send a message via the AssetHoard contact form">contact form</a>.</p>
<p>AssetHoard is a local-first asset manager for indie game devs and digital artists. The Godot work shipped in <a href="https://assethoard.com/releases/0.1.13" title="Read the AssetHoard v0.1.13 release notes">v0.1.13</a>. Open beta, free during beta, runs offline. Feature overview at <a href="https://assethoard.com/godot-asset-manager" title="AssetHoard for Godot — feature overview">assethoard.com/godot-asset-manager</a>.</p>
<hr>
<p><em>Mark</em></p>
]]></content:encoded>
		</item>
		<item>
			<title>Best Offline Asset Manager for Indie Developers</title>
			<link>https://assethoard.com/blog/best-offline-asset-manager-indie-developers</link>
			<guid isPermaLink="true">https://assethoard.com/blog/best-offline-asset-manager-indie-developers</guid>
			<pubDate>Sun, 03 May 2026 00:00:00 GMT</pubDate>
			<dc:creator>Mark Gandolfo</dc:creator>
			<category>Guides</category>
			<description>A look at offline asset managers for game developers, and how to pick one that handles engine-specific formats.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/hero/assethoard-backgrounds.png" alt="Best Offline Asset Manager for Indie Developers" /></p>
<div class="figure-inline">
<p class="figure-inline__text">If you've spent any time building games as an indie developer, you've probably hit the same wall: a folder full of assets that's completely out of control. Hundreds of sprites, sound files, models, textures, and Unity packages, organised by a naming convention you invented two years ago and have since partially abandoned. The folder called "final" next to the folder called "final_v2" next to the folder called "actually_final".</p>
<a href="https://assethoard.com/blog/2026/messy-assetfolder.png" target="_blank" rel="noopener noreferrer" class="figure-inline__image"><img src="https://assethoard.com/blog/2026/messy-assetfolder.png" alt="A chaotic asset folder full of duplicates, inconsistent naming conventions, and final_v2-style filenames" title="A typical messy asset folder" loading="lazy"></a>
</div>

<p>The obvious solution is an asset manager. The question is which one, and whether it needs to be online at all.</p>
<h2 id="the-problem-with-cloud-first-tools">The problem with cloud-first tools</h2><p>A lot of creative tools have gone cloud-first. It makes sense from a business perspective: recurring revenue, easy updates, cross-device sync. But for game developers, it introduces a set of problems that don&#39;t get talked about enough.</p>
<p>Connectivity is the obvious one. Game developers work everywhere. On trains with patchy mobile signal, at game jams where the venue wifi is already overloaded, in coffee shops with paywalled connections, on planes. If your asset library lives behind a login screen and an internet connection, you&#39;re stuck the moment you lose signal.</p>
<p>Then there&#39;s data ownership. If your assets and all the organisational work you&#39;ve done (the tags, the collections, the metadata) live on someone else&#39;s server, you&#39;re renting access to your own library. Cloud tools shut down. Companies get acquired. Services pivot. When that happens, your organisational work evaporates. You get an email saying you have 30 days to export what you can, and then it&#39;s gone.</p>
<p>Worth checking the terms of service while you&#39;re at it. A surprising number of &quot;free&quot; creative tools quietly grant themselves a perpetual licence to your uploads, or reserve the right to use them for &quot;improving our services&quot; (read: training the next generative model on the concept art you spent six months on). Your assets are your IP. They shouldn&#39;t be someone else&#39;s training data.</p>
<p>And then there&#39;s subscription fatigue. Indie devs are already juggling engine licences, hosting costs, asset store purchases, and a dozen other recurring expenses. Another $5 or $10 a month tool adds up. A tool that helps you organise files you already own shouldn&#39;t itself be a recurring bill.</p>
<p>An offline, local-first approach sidesteps all of this. Your data lives on your machine. No connection required. No account to log into. No risk that the company folds and takes your library organisation with it.</p>
<h2 id="what-to-look-for">What to look for</h2><p>Not all offline tools are equal. A few things actually matter for game development specifically.</p>
<p>Local storage is the baseline: all data on your machine, no cloud dependency. From there, format support is where a lot of general-purpose tools fall short. Game development uses formats that design tools have never heard of: <code>.unitypackage</code>, <code>.aseprite</code>, <code>.tres</code>, <code>.gdscript</code>, <code>.fbx</code>, <code>.gltf</code>, <code>.blend</code>. An asset manager that only handles images and videos isn&#39;t much use when half your library is game-engine-specific files.</p>
<p>You shouldn&#39;t need an account. You should be able to install the thing and start using it immediately, without creating yet another login or agreeing to yet another privacy policy. Pricing should match: a tool that organises your files is a utility. It should be bought, not rented.</p>
<p>Preview capabilities are the next thing. Filenames alone aren&#39;t enough. You need to be able to see what a file actually is, whether that is viewing a 3D model, playing a sound, or previewing an animated sprite, without opening a separate application for each one.</p>
<p>And finally, tagging and search. Folders scale reasonably well up to a few hundred files. Past that, you need a proper tagging and search system, because hierarchical folder structures break down when a single asset fits into multiple categories.</p>
<h2 id="the-options">The options</h2><h3 id="manual-folder-systems">Manual folder systems</h3><p>This is where everyone starts, and for good reason: it&#39;s free and requires no setup. For small libraries, say the assets for a single project, it works fine.</p>
<p>The problems start when your library grows across multiple projects. There&#39;s no preview beyond what your OS provides. Tagging doesn&#39;t exist. Search is limited to filenames. Duplicate files accumulate. You end up with a sprawling directory structure that only makes sense to you, and only barely.</p>
<p>Folders are a perfectly reasonable starting point. They stop being sufficient once you have more files than you can hold in your head.</p>
<h3 id="eagle-cool">Eagle.cool</h3><div class="figure-inline figure-inline--reverse">
<p class="figure-inline__text">Eagle is a polished visual file organiser with a nice interface and a solid tagging system. It handles images and video well, has a clean design, and costs $29.95 as a one-time purchase. For designers and illustrators, it's genuinely excellent.</p>
<a href="https://assethoard.com/blog/2026/best-offline-asset-manager/eagle.png" target="_blank" rel="noopener noreferrer" class="figure-inline__image"><img src="https://assethoard.com/blog/2026/best-offline-asset-manager/eagle.png" alt="Eagle.cool app icon, a polished visual file organiser aimed at designers and illustrators" title="Eagle.cool" loading="lazy"></a>
</div>

<p>For game developers, it falls short in some important ways. There&#39;s no support for <code>.unitypackage</code> or other engine-specific formats. 3D model preview isn&#39;t there. Drag-to-engine workflow isn&#39;t part of its design, because it wasn&#39;t built with game engines in mind. Eagle is a great tool aimed squarely at designers. If your asset library is primarily images, it&#39;s worth considering. If it&#39;s primarily game assets, you&#39;re using a tool that wasn&#39;t made for your use case.</p>
<h3 id="hydrus-network">Hydrus Network</h3><div class="figure-inline">
<p class="figure-inline__text">Hydrus is free, open source, and extraordinarily powerful. Its tagging and search capabilities are genuinely impressive. It's built around the kind of detailed metadata management that booru-style image collections use, and it handles large libraries well.</p>
<a href="https://assethoard.com/blog/2026/best-offline-asset-manager/hydrus-white.png" target="_blank" rel="noopener noreferrer" class="figure-inline__image"><img src="https://assethoard.com/blog/2026/best-offline-asset-manager/hydrus-white.png" alt="The Hydrus Network interface, a dense and technical UI built around tag-based image library management" title="Hydrus Network interface" loading="lazy"></a>
</div>

<p>The trade-off is complexity. The UI is dense and technical. Getting it set up and configured to your workflow takes real time and effort. And critically, it&#39;s built around images. There&#39;s no 3D model preview, no game package inspection, no concept of engine integration. It&#39;s a powerful tool for a specific use case, and that use case isn&#39;t game development.</p>
<p>If you want maximum tagging control and are willing to invest time learning the tool, Hydrus is worth exploring. If you want something you can use immediately with game-specific files, it&#39;s not the right fit.</p>
<h3 id="assethoard">AssetHoard</h3><p><a href="https://assethoard.com/hero/assethoard-backgrounds.png" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/hero/assethoard-backgrounds.png" alt="AssetHoard library showing a grid of game-ready background art with previews, tags, and search visible in a local-first asset manager built for indie developers" title="AssetHoard, an offline asset manager for indie developers" width="1920" height="1032" loading="eager" decoding="async"></a></p>
<p><a href="https://assethoard.com">AssetHoard</a> is a <a href="https://assethoard.com">game asset manager</a> built specifically for indie developers and artists. It supports 80+ game-development-specific file formats: <code>.unitypackage</code>, <code>.aseprite</code>, <code>.tres</code>, <code>.krita</code>, <code>.fbx</code>, <code>.gltf</code>, <code>.blend</code>, <code>.wav</code>, <code>.ogg</code>, and more.</p>
<p>Preview is built in for everything: 3D models with rotation, animated sprites, audio waveforms, texture tiling. You can tag assets, search across your entire library, and drag files directly into Unity or Godot. No account required. No subscription. One-time purchase at $29.</p>
<p>It runs on Windows and Linux, with macOS support in development.</p>
<p>It&#39;s narrower than Hydrus in terms of tagging depth, and it doesn&#39;t have Eagle&#39;s visual polish. What it does have is a focused set of features for the actual game development workflow, built around the file formats you&#39;re actually using.</p>
<h2 id="picking-one">Picking one</h2><p>The best tool depends on your library size and what you&#39;re actually working with.</p>
<p>Folders work fine for small collections and single projects. Eagle is a good choice if your library is primarily images and you want a well-designed, general-purpose organiser. Hydrus is for power users who want deep tagging control and are willing to spend time on configuration.</p>
<p>If you&#39;re a game developer with a growing library of engine packages, 3D models, sprites, and audio (formats that general tools don&#39;t understand), then a purpose-built <a href="https://assethoard.com">local-first asset manager</a> is worth the investment.</p>
]]></content:encoded>
		</item>
		<item>
			<title>Why your pixel art looks blurry (and how to fix it)</title>
			<link>https://assethoard.com/blog/why-your-pixel-art-looks-blurry</link>
			<guid isPermaLink="true">https://assethoard.com/blog/why-your-pixel-art-looks-blurry</guid>
			<pubDate>Sun, 26 Apr 2026 00:00:00 GMT</pubDate>
			<dc:creator>The AssetHoard Team</dc:creator>
			<category>Guides</category>
			<description>Most asset tools blur pixel art by default. Here is why it happens, what proper pixel rendering looks like, and how to stop fighting your tools.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/assethoard-pixel-renderer.png" alt="Why your pixel art looks blurry (and how to fix it)" /></p>
<img src="https://assethoard.com/blog/2026/assethoard-pixel-renderer.png" alt="AssetHoard pixel art renderer showing crisp nearest-neighbour scaling" style="width: 100%; border-radius: 0.5rem; margin-bottom: 1.5rem;" />

<p>You drag a 32x32 sprite into your asset browser. Something you spent an afternoon getting right, every pixel placed deliberately. The preview comes up. It looks like someone has rubbed butter on the screen.</p>
<p>This is not your fault, and it is not the sprite&#39;s fault. It is the rendering pipeline, and almost every general-purpose tool you have ever used gets it wrong by default.</p>
<h2 id="what-is-actually-happening">What is actually happening</h2><img src="https://assethoard.com/blog/2026/pixel-renderer.webp" alt="Comparison of bilinear filtering versus nearest-neighbour scaling on a pixel art sprite" style="float: right; width: 40%; margin: 0.25rem 0 1rem 1.5rem; border-radius: 0.5rem;" />

<p>When a tool displays an image at a size different from its native resolution, it has to invent the missing pixels. There are two main approaches.</p>
<p>The first is interpolation. The renderer looks at the source pixels around each output pixel and blends them together to produce a smooth gradient. This is called bilinear or bicubic filtering, depending on the algorithm. It is excellent for photographs, where soft transitions between colours match how the real world actually looks. A photo upscaled with bilinear filtering looks natural. The eye accepts the smoothing because real surfaces do not have hard pixel boundaries.</p>
<p>The second is nearest-neighbour. Instead of blending, the renderer simply picks the closest source pixel for each output pixel. No averaging, no smoothing, no invention. The result is a clean grid where every source pixel becomes a perfect square block.</p>
<p>For pixel art, you want the second one. Always.</p>
<p>And here is the thing. Pixel art is not low-resolution photography. Every pixel in a good sprite is there on purpose. The artist sat with a four-pixel sword tip and decided whether the highlight should be one pixel or two. They placed antialiasing by hand on the edges that needed it and left the others sharp. The whole point of the medium is that the grid is the canvas, not a limitation to be papered over.</p>
<p>Bilinear filtering takes all of that careful work and averages it into mush. The single-pixel highlight gets smeared into the blade. Hand-placed antialiasing turns into generic blur. Hard silhouettes that read cleanly at native resolution dissolve into soft halos. The render pipeline is doing what it thinks is helpful, except the help is undoing the work.</p>
<p>Nearest-neighbour just gets out of the way. Whatever the artist made survives the scaling, only larger.</p>
<div style="clear: both;"></div>

<h2 id="why-so-many-tools-get-it-wrong">Why so many tools get it wrong</h2><p>Two reasons, both reasonable in isolation.</p>
<p>The first is that photographs vastly outnumber pixel art in any general-purpose image pipeline. If a tool has to pick one default behaviour, picking the one that works for the majority is the safe choice. Bilinear filtering is fine, even good, for almost every image that is not pixel art.</p>
<p>The second reason is harder. Detecting pixel art automatically is not trivial. There is no metadata flag inside a PNG that announces &quot;I am pixel art, please render me crisply.&quot; The information has to be inferred from the image itself, and any single signal can be misleading.</p>
<p>Small dimensions are a hint, but plenty of pixel art lives at 512x512 or larger, and plenty of photos exist at thumbnail sizes. A limited colour palette is a hint, but a stylised illustration might also have few colours. Hard edges are a hint, but high-contrast photography has hard edges too. No single check is reliable on its own.</p>
<p>So most tools shrug and pick the safe default. Bilinear for everything. Pixel artists then spend years either ticking the same &quot;disable smoothing&quot; checkbox in every tool they use, or accepting that previews are going to lie about what their work actually looks like.</p>
<h2 id="what-good-detection-looks-like">What good detection looks like</h2><p>The trick is to combine signals rather than rely on any single one. A reasonable stack might check:</p>
<ul>
<li><strong>Image dimensions.</strong> Pixel art tends to live below a certain size threshold, particularly for sprites and tiles. This is a soft signal, not a hard rule.</li>
<li><strong>Unique colour count.</strong> Palette-limited art typically has far fewer distinct colours than a comparable photograph. A 64x64 image with twelve unique colours is almost certainly pixel art. The same image with eight thousand colours is almost certainly not.</li>
<li><strong>Edge transition analysis.</strong> Pixel art has hard transitions between adjacent pixels rather than gradients. Counting how often neighbouring pixels differ sharply gives a useful signal.</li>
<li><strong>File source hints.</strong> If an image came out of Aseprite, Pyxel, or any of the established pixel art tools, that is a strong signal in itself. Some of these tools embed identifying metadata that can be detected.</li>
</ul>
<p>Combine those signals into a confidence score. Above a threshold, render with nearest-neighbour. Below it, fall back to bilinear. Then expose an override so the user can correct the edge cases without ceremony.</p>
<p>This is not glamorous engineering. It is a stack of heuristics, none of which are perfect, that together get the right answer often enough to be useful. The win is that the user stops thinking about it. They drag their sprite in, and it just looks right.</p>
<h2 id="what-to-look-for-in-a-tool">What to look for in a tool</h2><p>If you work with pixel art, the question to ask of any new asset manager, file browser, or preview tool is straightforward: does it render pixel art correctly without me having to configure anything?</p>
<p>A few specific things to check:</p>
<ul>
<li>Drop a 32x32 sprite in and look at the preview. Are the pixels crisp blocks, or is the image soft and blurred?</li>
<li>Try a 16x16 tile. Tiny art exposes interpolation problems most aggressively.</li>
<li>Check whether the tool offers a per-asset override. Auto-detection will sometimes get it wrong, and you want to be able to fix individual cases without affecting everything else.</li>
<li>See whether the setting persists. A tool that requires you to enable crisp rendering every time you open it is barely better than one that does not support it at all.</li>
</ul>
<p>If the tool fails the first check, the rest does not matter. You will spend the relationship fighting it.</p>
<h2 id="how-assethoard-handles-this">How AssetHoard handles this</h2><p>AssetHoard ships with automatic pixel art detection as of v0.1.12. When you import images, the tool examines each one against a stack of heuristics and renders pixel art with nearest-neighbour scaling by default. No checkbox to find. No setting to remember.</p>
<p>If the detection misclassifies something, you can override on individual assets, or set the rendering mode at a category level so every sprite or tile inside inherits it automatically. The detection runs at import time, so existing libraries pick up the new behaviour as you add to them.</p>
<p>This is the first feature in a broader renderer system. Future renderers will handle 3D models, materials, and engine-specific package formats with the same principle: detect what the asset actually is, then render it the way the artist intended.</p>
<p>If you have been fighting blurry previews in your asset browser, <a href="https://assethoard.com">give AssetHoard a try</a>. It is in open beta, free to use during the beta, and runs entirely on your own machine.</p>
<hr>
<p><em>Mark</em></p>
]]></content:encoded>
		</item>
		<item>
			<title>PBR vs ORM: Understanding the Difference</title>
			<link>https://assethoard.com/blog/pbr-vs-orm-explained</link>
			<guid isPermaLink="true">https://assethoard.com/blog/pbr-vs-orm-explained</guid>
			<pubDate>Fri, 17 Apr 2026 00:00:00 GMT</pubDate>
			<dc:creator>Mark Gandolfo</dc:creator>
			<category>Guides</category>
			<description>One is a lighting model. The other is how you pack some of its textures. Here is what that means across Unity, Unreal, Godot and Blender.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/pbr.jpg" alt="PBR vs ORM: Understanding the Difference" /></p>
<img src="https://assethoard.com/blog/2026/pbr.jpg" alt="PBR vs ORM textures" style="float: left; width: 40%; margin: 0.25rem 1.5rem 1rem 0; border-radius: 0.5rem;" />

<p>If you have spent any time with 3D assets, you have seen both terms thrown around as if they are interchangeable. They are not. PBR and ORM operate at different levels of the pipeline, and understanding the distinction saves a lot of confusion when importing materials between engines.</p>
<div style="clear: both;"></div>

<h2 id="pbr-is-the-lighting-model">PBR is the lighting model</h2><p>PBR stands for Physically Based Rendering. It is a shading approach that simulates how light actually behaves, with energy conservation, microsurface scattering, and Fresnel effects baked into the maths. A PBR material is driven by a stack of greyscale and colour textures: base colour (sometimes called albedo), normal, roughness, metallic, and ambient occlusion, often with emissive or height on top.</p>
<p>The shader reads those inputs and produces results that look consistent under different lighting. A rusted iron surface looks rusted whether it is sitting in a sunlit field or a dim warehouse, because the maths accounts for the physics rather than faking it per-scene.</p>
<h2 id="the-textures-that-feed-it">The textures that feed it</h2><p>A PBR material is not one texture, it is a small bundle of them. Each one describes a different physical property of the surface. Here is what you will typically see in a material folder:</p>
<pre><code class="hljs language-plaintext">brick_wall/
├── brick_wall_basecolor.png     (or _albedo, _diffuse, _col)
├── brick_wall_normal.png        (or _nrm, _n)
├── brick_wall_roughness.png     (or _rough, _r)
├── brick_wall_metallic.png      (or _metal, _m)
├── brick_wall_ao.png            (or _occlusion, _occ)
├── brick_wall_height.png        (or _displacement, _disp, _h)  [optional]
└── brick_wall_emissive.png      (or _emission, _e)             [optional]</code></pre><p>What each one does:</p>
<ul>
<li><strong>Base colour</strong> is the raw surface colour with no lighting baked in. Think of it as what the surface would look like under flat, shadowless light. This is the only map stored in sRGB colour space. Everything else is linear data.</li>
<li><strong>Normal</strong> fakes surface detail by telling the shader which direction each pixel is facing. It is why a flat plane can look like a bumpy brick wall. Usually purple-blue in appearance.</li>
<li><strong>Roughness</strong> is greyscale. Black is a mirror, white is chalk. It controls how sharp or blurred reflections are.</li>
<li><strong>Metallic</strong> is also greyscale, and almost always close to pure black or pure white. Black means non-metal (plastic, wood, stone, skin). White means metal (iron, gold, aluminium). Values in between are rare outside of transition areas like rust.</li>
<li><strong>Ambient occlusion</strong> darkens crevices and contact points where light would naturally struggle to reach. Grayscale, white is fully lit, black is fully occluded.</li>
<li><strong>Height</strong> (sometimes called displacement) pushes the actual geometry in or out. More expensive than normal mapping but produces real silhouette detail.</li>
<li><strong>Emissive</strong> makes parts of the surface glow independently of scene lighting. Usually black everywhere except the glowing bits.</li>
</ul>
<p>Naming conventions are not standardised. Some packs ship <code>_diffuse</code> instead of <code>_basecolor</code>. Some use <code>_nrm</code> instead of <code>_normal</code>. You will learn to recognise them by suffix.</p>
<h2 id="orm-is-a-texture-packing-format">ORM is a texture packing format</h2><p>ORM stands for Occlusion, Roughness, Metallic. It is a way of packing three of those greyscale maps into the RGB channels of a single image:</p>
<ul>
<li><strong>R</strong> channel holds Ambient Occlusion</li>
<li><strong>G</strong> channel holds Roughness</li>
<li><strong>B</strong> channel holds Metallic</li>
</ul>
<p>This is purely an optimisation. Each of those three maps is single-channel data, so storing them as separate RGB textures wastes two-thirds of every file. Packing them together means one texture sample instead of three, less VRAM consumed, and fewer draw call overheads. It is standard practice in modern real-time pipelines.</p>
<h2 id="how-each-engine-handles-it">How each engine handles it</h2><p><strong>Unreal Engine</strong> uses the standard ORM layout. Red is occlusion, green is roughness, blue is metallic. Most Unreal-ready materials on marketplaces ship with a base colour, normal, and ORM texture, sometimes with a separate emissive. The material editor expects this convention out of the box.</p>
<pre><code class="hljs language-plaintext">Unreal ORM:
├── R channel → Ambient Occlusion
├── G channel → Roughness
└── B channel → Metallic</code></pre><p><strong>Godot</strong> matches Unreal&#39;s convention through ORMMaterial3D. Red is occlusion, green is roughness, blue is metallic. You assign the packed texture and the engine handles channel splitting automatically. This also matches the glTF 2.0 metallic-roughness spec, which is the closest thing to a cross-engine standard.</p>
<pre><code class="hljs language-plaintext">Godot ORM (and glTF 2.0):
├── R channel → Ambient Occlusion
├── G channel → Roughness
└── B channel → Metallic</code></pre><p><strong>Unity</strong> does its own thing. Note that as of 2026, Unity has announced HDRP is going into maintenance mode and URP is becoming the primary rendering pipeline going forward, so URP is the convention to care about for new work.</p>
<p>URP&#39;s Lit and Complex Lit shaders support a channel-packed texture, but the layout is completely different from Unreal and Godot:</p>
<pre><code class="hljs language-plaintext">Unity URP (Lit/Complex Lit):
├── R channel → Metallic
├── G channel → Occlusion
├── B channel → (unused)
└── A channel → Smoothness (inverse of roughness)</code></pre><p>Two things to note. First, red is metallic in Unity but occlusion in Unreal, so a texture packed for one engine will render incorrectly in the other without channel swapping. Second, Unity uses smoothness instead of roughness. Smoothness is the numerical inverse: a roughness value of 0.2 becomes a smoothness value of 0.8. Importing an Unreal-style ORM into Unity without conversion gives you materials that look wrong in a way that is hard to diagnose.</p>
<p>HDRP&#39;s Mask Map is similar but uses the blue channel for a detail mask:</p>
<pre><code class="hljs language-plaintext">Unity HDRP Mask Map (maintenance mode):
├── R channel → Metallic
├── G channel → Occlusion
├── B channel → Detail mask
└── A channel → Smoothness</code></pre><p>Unity&#39;s older Built-in Render Pipeline Standard shader packed smoothness into the alpha channel of the metallic map with no occlusion or detail slot, which is yet another convention you will still encounter in legacy projects and older asset packs.</p>
<p><strong>Blender</strong> does not have an engine preference of its own. It reads individual texture inputs on the Principled BSDF node, so working with a packed texture means using a Separate Color node to split the channels before feeding each one to the correct shader input. Most Blender addons for PBR import handle this automatically, but it is worth knowing what is happening underneath. Because Blender is agnostic, it is also the most useful place to unpack and repack textures between conventions.</p>
<h2 id="the-quick-comparison">The quick comparison</h2><div class="table-scroll"><table>
<thead>
<tr>
<th>Engine</th>
<th>R</th>
<th>G</th>
<th>B</th>
<th>A</th>
</tr>
</thead>
<tbody><tr>
<td>Unreal (ORM)</td>
<td>Occlusion</td>
<td>Roughness</td>
<td>Metallic</td>
<td>–</td>
</tr>
<tr>
<td>Godot (ORMMaterial)</td>
<td>Occlusion</td>
<td>Roughness</td>
<td>Metallic</td>
<td>–</td>
</tr>
<tr>
<td>glTF 2.0</td>
<td>Occlusion</td>
<td>Roughness</td>
<td>Metallic</td>
<td>–</td>
</tr>
<tr>
<td>Unity URP Lit</td>
<td>Metallic</td>
<td>Occlusion</td>
<td>unused</td>
<td>Smoothness</td>
</tr>
<tr>
<td>Unity HDRP Mask Map</td>
<td>Metallic</td>
<td>Occlusion</td>
<td>Detail mask</td>
<td>Smoothness</td>
</tr>
<tr>
<td>Blender</td>
<td>user-defined</td>
<td>user-defined</td>
<td>user-defined</td>
<td>–</td>
</tr>
</tbody></table></div>
<p>If you are shipping assets for multiple engines, your safest bet is to distribute individual unpacked maps alongside a pre-packed ORM for Unreal and Godot, and leave Unity users to repack using their own convention.</p>
<h2 id="where-to-find-free-samples">Where to find free samples</h2><p>These are the reliable CC0 sources:</p>
<ul>
<li><strong><a href="https://polyhaven.com/" target="_blank" rel="noopener noreferrer">Poly Haven</a></strong> has 4K and 8K PBR textures with full map sets, CC0 with no attribution required</li>
<li><strong><a href="https://ambientcg.com/" target="_blank" rel="noopener noreferrer">ambientCG</a></strong> (formerly CC0Textures) has more than 2,000 PBR materials, also CC0</li>
<li><strong><a href="https://www.cgbookcase.com/textures" target="_blank" rel="noopener noreferrer">CG Bookcase</a></strong> offers 500+ PBR textures with no account required</li>
<li><strong><a href="https://www.texturecan.com/" target="_blank" rel="noopener noreferrer">TextureCan</a></strong> has 4K-minimum textures with SBSAR files for procedural tweaking</li>
<li><strong><a href="https://www.sharetextures.com/" target="_blank" rel="noopener noreferrer">ShareTextures</a></strong> covers wood, stone, metal, and ground textures up to 4K</li>
</ul>
<p>Most of these deliver individual PBR maps rather than pre-packed ORM textures. If you need an ORM for Unreal or Godot, you can pack one yourself in any image editor by assigning AO to the red channel, roughness to green, and metallic to blue. ImageMagick does it in a single command, and most DCC tools have built-in or plugin-based packers. If you would rather not touch the command line, an AssetHoard user has created <a href="https://www.tikodevelopments.com/texture-packer-tool" target="_blank" rel="noopener noreferrer">Tiko Developments Texture Packer Tool</a>, a browser-based packer that outputs ORM layouts for all Unreal, Unity (HDRP, SRP and URP), gLTF, Godot, and even custom. </p>
<h2 id="the-practical-takeaway">The practical takeaway</h2><p>PBR is the workflow. ORM is one way of organising the textures that feed it. When someone says a material is &quot;PBR,&quot; they mean it works with a physically based shader. When they say it is &quot;ORM packed,&quot; they mean the three greyscale maps are already combined into one file.</p>
<p>Knowing which is which makes it much easier to troubleshoot when a material looks wrong after import. Nine times out of ten, it is a channel convention mismatch rather than a broken texture.</p>
<hr>
<p>If you work with a lot of PBR materials across different engines, keeping them organised gets painful fast. <a href="https://assethoard.com">AssetHoard</a> is a local-first desktop asset manager built for exactly this kind of library. It is free during open beta.</p>
<hr>
<p><em>The AssetHoard Team</em></p>
]]></content:encoded>
		</item>
		<item>
			<title>Eagle.cool Alternative for Game Developers</title>
			<link>https://assethoard.com/blog/eagle-alternative-game-developers</link>
			<guid isPermaLink="true">https://assethoard.com/blog/eagle-alternative-game-developers</guid>
			<pubDate>Fri, 03 Apr 2026 00:00:00 GMT</pubDate>
			<dc:creator>Mark Gandolfo</dc:creator>
			<category>Guides</category>
			<description>Eagle is a great visual organiser, but it wasn&apos;t built for game assets. Here&apos;s what to look for if you&apos;re a game developer.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/comparison/assethoard-tool-comparison.png" alt="Eagle.cool Alternative for Game Developers" /></p>
<p><a href="https://assethoard.com/blog/2026/comparison/assethoard-tool-comparison.png" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/comparison/assethoard-tool-comparison.png" alt="Side-by-side comparison: a competitor tool showing an unsupported-format placeholder for an Aseprite file, versus AssetHoard rendering the same file as a crisp pixel-art capybara. Tagline: One library, everything visible." title="AssetHoard versus Eagle.cool: pixel-art Aseprite preview comparison" width="1280" height="768" loading="eager" decoding="async"></a></p>
<p>Eagle.cool has built up a loyal following among digital creatives, and for good reason. If you&#39;ve been using it to organise your reference images and design assets, you already know it&#39;s a genuinely well-made piece of software. But if you&#39;re a game developer, you&#39;ve probably also hit its limits.</p>
<p>This is a straightforward comparison of what Eagle does well, where it falls short for game-dev workflows, and whether <a href="https://assethoard.com" title="AssetHoard — the local-first asset manager for game developers">AssetHoard</a> might be a better fit for your library.</p>
<h2 id="what-eagle-does-well">What Eagle does well</h2><p>Let&#39;s start with the positives, because Eagle earns them.</p>
<p>The UI is clean and thoughtfully designed. Browsing large collections of images and video references feels snappy, and the thumbnail previews are excellent. The tagging system is flexible. You can colour-code tags, nest them into groups, and filter your library in ways that actually make sense for visual work.</p>
<p>The browser extension is one of Eagle&#39;s standout features. Saving reference images from the web directly into your library, with the source URL automatically attached, is genuinely useful for mood boards and inspiration collections.</p>
<p>Audio handling is also solid. Eagle renders snappy waveform previews and supports inline playback, so auditioning sound effects or music loops while browsing feels fluid rather than clunky.</p>
<p>Format support is broad for design work: PSD, AI, EPS, Sketch, Figma exports, RAW photos, video files. The annotation tools let you mark up images and build out proper mood boards. Many game developers start with Eagle and get real value from it, particularly early in a project when you&#39;re gathering references and building a visual direction.</p>
<h2 id="where-eagle-falls-short-for-game-developers">Where Eagle falls short for game developers</h2><p>Eagle was built for graphic designers and illustrators, and that&#39;s exactly where its gaps appear when you try to use it as a game asset manager.</p>
<p><strong>Limited 3D model format coverage.</strong> Eagle previews FBX, OBJ, and STL, which covers some of the basics, but it doesn&#39;t handle glTF/GLB, Blender (.blend), or Collada (.dae). If your library leans on glTF (Godot&#39;s preferred format) or includes raw Blender files, those sit as flat icons.</p>
<p><strong>Limited 3D animation playback.</strong> Eagle&#39;s 3D viewer can show a model, but animation playback is restricted. Scrubbing through an idle loop, checking a walk cycle, or confirming a rig animates the way you expect often means opening the file in another tool.</p>
<div class="figure-inline">
<p class="figure-inline__text"><strong>No material file support.</strong> Material files like .mtl, .mtlx (MaterialX), .mat (Unity), and Substance .sbsar / .sbs aren't recognised by Eagle. They sit in your library as opaque files with no preview of what the material actually looks like.</p>
<a href="https://assethoard.com/blog/2026/comparison/competitor-material-support.png" target="_blank" rel="noopener noreferrer" class="figure-inline__image" title="Open the material-file preview comparison in a new tab"><img src="https://assethoard.com/blog/2026/comparison/competitor-material-support.png" alt="A material file open in a competitor tool, shown as an unsupported-format placeholder with no preview of the actual surface" title="A material file shown as an unsupported-format placeholder in a competitor tool" loading="lazy"></a>
</div>

<p><strong>No material sphere rendering.</strong> Even when textures are organised as a PBR set, Eagle can&#39;t render them on a 3D sphere with proper lighting to show you the actual surface. You&#39;re inspecting maps, not materials.</p>
<div class="figure-inline">
<p class="figure-inline__text"><strong>No .unitypackage support.</strong> Unity Asset Store packages are a staple of many game developers' workflows. Eagle can't inspect or browse the contents of a .unitypackage file. You'd have to import it into Unity just to see what's inside.</p>
<a href="https://assethoard.com/blog/2026/comparison/competitor-unity.png" target="_blank" rel="noopener noreferrer" class="figure-inline__image" title="Open the .unitypackage handling comparison in a new tab"><img src="https://assethoard.com/blog/2026/comparison/competitor-unity.png" alt="A .unitypackage file in a competitor tool with no way to inspect its contents, just a generic file entry" title="A .unitypackage shown as a generic file entry with no inspectable contents in a competitor tool" loading="lazy"></a>
</div>

<p><strong>No Godot resource support.</strong> If you&#39;re working with Godot, your library is likely full of .tres, .tscn, and .res files. Eagle doesn&#39;t understand these formats, so they just sit there unlabelled.</p>
<p><strong>No Aseprite preview at all.</strong> Eagle doesn&#39;t render .aseprite files. If you&#39;re working with pixel art, you&#39;ll see an unsupported-format placeholder rather than the artwork or its animation.</p>
<div class="figure-inline">
<p class="figure-inline__text"><strong>No pixel-perfect sprite rendering.</strong> Eagle displays pixel art using a blended renderer, which works great for sunsets or pictures of people, but pixel art needs precise rendering at any scale. For pixel artists, that turns the library into a wall of soft, distorted thumbnails.</p>
<a href="https://assethoard.com/blog/2026/comparison/competitor-sprite-support.png" target="_blank" rel="noopener noreferrer" class="figure-inline__image" title="Open the pixel-art sprite rendering comparison in a new tab"><img src="https://assethoard.com/blog/2026/comparison/competitor-sprite-support.png" alt="A pixel-art sprite previewed in a competitor tool with smoothing applied, edges and details come out blurry and softened instead of crisp" title="A pixel-art sprite rendered with blurry smoothing in a competitor tool" loading="lazy"></a>
</div>

<p><strong>No PBR texture set grouping.</strong> A single PBR material typically comes as a set of textures: albedo, normal map, roughness, metallic, ambient occlusion. Eagle doesn&#39;t understand the relationship between these files, so they sit separately in your library with no indication that they belong together.</p>
<p><strong>No Linux support.</strong> Eagle runs on Windows and macOS only. If your development machine is Linux, Eagle is off the table entirely, which rules it out for a meaningful slice of indie and open-source game developers.</p>
<p>None of these are criticisms of Eagle as a product. They&#39;re just evidence that it was designed with a different user in mind.</p>
<h2 id="assethoard-as-an-alternative">AssetHoard as an alternative</h2><p><a href="https://assethoard.com" title="AssetHoard — built for game developers and creative professionals">AssetHoard</a> was built specifically for game developers and artists who are managing the kind of files that Eagle can&#39;t handle well.</p>
<p>Format support covers 80+ types including .unitypackage, .aseprite, .krita, .fbx, .gltf/.glb, .blend, .dae, .obj, .stl, the full range of common image and audio formats, plus material files like .mtl, .mtlx, .mat, and Substance .sbsar / .sbs.</p>
<div class="figure-inline">
<p class="figure-inline__text">The 3D model browser lets you rotate, zoom, and play back animations directly in the app, useful when you're trying to decide between three similar character rigs. Models from .blend, .gltf/.glb, .fbx, .dae, and .obj all sit alongside one another in the same library.</p>
<a href="https://assethoard.com/hero/animations-3D.webp" target="_blank" rel="noopener noreferrer" class="figure-inline__image" title="Open the AssetHoard 3D model viewer animation in a new tab"><img src="https://assethoard.com/hero/animations-3D.webp" alt="Animated demo of AssetHoard's 3D model viewer rotating a model with interactive zoom and pan controls" title="AssetHoard 3D model viewer with rotate, zoom, and animation playback" loading="lazy"></a>
</div>

<div class="figure-inline figure-inline--reverse">
<p class="figure-inline__text">If you work with Unity, the <a href="https://assethoard.com/unity-asset-manager" title="AssetHoard Unity asset manager — inspect .unitypackage files without importing">Unity asset manager</a> workflow lets you inspect .unitypackage contents without importing into Unity first. You can see exactly what's in a package, browse its assets, and decide whether it's worth bringing into your project. For Godot users, the <a href="https://assethoard.com/godot-asset-manager" title="AssetHoard Godot asset manager — preview .tres, .tscn, and .res files">Godot asset manager</a> handles .tres, .tscn, and .res files alongside the rest of your library.</p>
<a href="https://assethoard.com/hero/assethoard-unity.png" target="_blank" rel="noopener noreferrer" class="figure-inline__image" title="Open the AssetHoard .unitypackage browser screenshot in a new tab"><img src="https://assethoard.com/hero/assethoard-unity.png" alt="AssetHoard importing a Unity Asset Store .unitypackage and listing its contents inline" title="AssetHoard inspecting a .unitypackage and listing its contents inline" loading="lazy"></a>
</div>

<div class="figure-inline">
<p class="figure-inline__text">Aseprite files have full animation support, with frame-by-frame playback rather than the frozen previews you'll see elsewhere. Pixel art is detected automatically at import (by dimensions, palette, or format) and rendered with a precise pixel renderer, so sprites stay crisp at every zoom. If the auto-pick gets it wrong, you can <a href="https://assethoard.com/docs/choose-a-renderer" title="AssetHoard docs — override the renderer per asset, bundle, or category">override the renderer</a> per asset, per bundle, or per category.</p>
<a href="https://assethoard.com/hero/animations-sprite.webp" target="_blank" rel="noopener noreferrer" class="figure-inline__image" title="Open the Aseprite animation playback demo in a new tab"><img src="https://assethoard.com/hero/animations-sprite.webp" alt="AssetHoard playing an Aseprite sprite animation frame by frame at pixel-perfect crispness" title="AssetHoard playing an Aseprite animation frame by frame at pixel-perfect crispness" loading="lazy"></a>
</div>

<div class="figure-inline figure-inline--reverse">
<p class="figure-inline__text">PBR texture sets are grouped automatically so albedo, normal, and roughness maps are shown together rather than scattered across your library. Material files render on a live 3D sphere with proper lighting, so you can see what a surface will actually look like before bringing it into your engine.</p>
<a href="https://assethoard.com/hero/assethoard-materials.png" target="_blank" rel="noopener noreferrer" class="figure-inline__image" title="Open the AssetHoard material browser screenshot in a new tab"><img src="https://assethoard.com/hero/assethoard-materials.png" alt="AssetHoard's material browser showing a PBR material rendered on a live 3D sphere with proper lighting" title="AssetHoard rendering a PBR material on a live 3D sphere with proper lighting" loading="lazy"></a>
</div>

<p>When you&#39;re ready to use an asset, you can drag it directly into Unity or Godot. No intermediate steps.</p>
<p>It&#39;s local-first. Your library lives on your machine, no cloud sync, no account required.</p>
<h2 id="honest-trade-offs">Honest trade-offs</h2><p>AssetHoard isn&#39;t better at everything, and it&#39;s worth being clear about that.</p>
<p>Eagle has a larger community and more integrations with design tools. Its browser extension for collecting web references is excellent and has no equivalent in AssetHoard. If you&#39;re regularly saving inspiration from the web, that&#39;s a genuine advantage.</p>
<p>Eagle handles a broader range of general design formats (AI, EPS, Sketch exports), which matters if your work is more aligned to graphic design.</p>
<p>On platform support, the situation is reversed. AssetHoard runs on Windows, macOS, and Linux, while Eagle is Windows and macOS only. If you&#39;re on Linux, AssetHoard is the only one of the two that will work for you.</p>
<h2 id="which-one-is-right-for-you">Which one is right for you</h2><p>If you&#39;re primarily a graphic designer or illustrator who occasionally works on game projects, Eagle is probably the better fit. Its strengths align well with that workflow.</p>
<p>If you&#39;re a game developer managing a growing library of .unitypackage files, Godot resources (.tres, .tscn, .res), 3D models, sprite sheets, Aseprite animations, and audio assets, <a href="https://assethoard.com" title="AssetHoard — local-first asset manager for game developers">AssetHoard</a> is built for exactly that workflow in a way Eagle isn&#39;t.</p>
<p>If you use both Unity or Godot and professional design tools heavily, you might find yourself reaching for both. They serve different enough use cases that there&#39;s not much overlap.</p>
<p>The simplest test: look at your asset library and count how many files are game-specific formats versus general design formats. That ratio will tell you which tool is doing more work for you.</p>
<hr>
<p><em>The AssetHoard Team</em></p>
]]></content:encoded>
		</item>
		<item>
			<title>How I Manage 100,000+ Game Assets Without Losing My Mind</title>
			<link>https://assethoard.com/blog/how-i-manage-100000-game-assets</link>
			<guid isPermaLink="true">https://assethoard.com/blog/how-i-manage-100000-game-assets</guid>
			<pubDate>Sun, 29 Mar 2026 00:00:00 GMT</pubDate>
			<dc:creator>The AssetHoard Team</dc:creator>
			<category>Guides</category>
			<description>Humble Bundle packs, asset store purchases, and indie artist downloads pile up fast. Here is how I stopped drowning in folders and started actually finding what I need.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/how-i-manage-100000-assets.png" alt="How I Manage 100,000+ Game Assets Without Losing My Mind" /></p>
<p>If you have been making games for more than a year, you probably have a problem.</p>
<p>It starts innocently enough. A Humble Bundle here, a free asset pack from itch.io there, a few purchases from the Unity Asset Store, some textures you grabbed from a Blender artist&#39;s Gumroad. The Kenney all-in-one pack alone is over 140,000 files. Before long you have hundreds of thousands of files spread across a dozen directories, and every time you sit down to work on a project you spend the first twenty minutes just trying to remember where you put that tileset.</p>
<p>I have been there. This is what I learned.</p>
<h2 id="the-directory-problem">The Directory Problem</h2><p>The instinct most developers have is to organise assets into folders. Environment, Characters, Audio, UI, and so on. It feels logical. It falls apart immediately.</p>
<p>The first issue is that folder structures are rigid. When you buy a pack from Kenney, it arrives with its own folder hierarchy. So does the next pack, and the one after that. You end up with either a mess of inconsistently structured vendor directories, or you spend hours manually reorganising files into your own structure -- only to repeat that work every time you download something new.</p>
<p>The second issue is that moving files breaks things. If a project already references an asset at a particular path, renaming or relocating it silently breaks that reference. So you stop moving things. The folder chaos becomes permanent.</p>
<p>The third issue is that folders only express one dimension of organisation at a time. An asset can only live in one folder. But a leather texture might belong under Materials, or under Fantasy Environment Pack, or under Assets Bought in 2024. Pick one and you lose the rest.</p>
<h2 id="finding-assets-is-worse-than-organising-them">Finding Assets Is Worse Than Organising Them</h2><p>Imagine you are building a level and you need &quot;rain&quot; assets. You have them. Somewhere.</p>
<p>Except rain assets do not live in one place. The rain sound effect is in <code>audio/ambient/nature/</code>. The thunder loop is in <code>Sonniss_GDC_Pack_2019/weather/</code>. The water droplet impact sounds are in <code>RPG_Sound_Pack/effects/</code>. The lightning bolt sprite is in <code>VFX_Essentials/particles/</code>. The rain particle system is in <code>UnityAssetStore/Weather_System_Pro/</code>. And somewhere in a Blender pack you downloaded there are umbrella 3D models that would be perfect for a character prop.</p>
<p>No folder structure in the world connects those dots. You find the first thing you remember, forget the rest exist, and end up with an incomplete scene.</p>
<h2 id="the-catalogue-approach">The Catalogue Approach</h2><p>The shift that actually worked for me was separating the catalogue from the directory.</p>
<p>Instead of treating your folder structure as the source of truth, you treat it as storage. Dumb storage. Assets stay wherever they landed. Your catalogue is the layer on top that knows what everything is, where it lives, and how it relates to everything else.</p>
<p>This is how AssetHoard works. You point it at your asset directories and it indexes everything in place. Nothing moves. Nothing breaks. Your project file references stay intact.</p>
<h2 id="semantic-search-changes-everything">Semantic Search Changes Everything</h2><p>The rain problem is where semantic search earns its place.</p>
<p>When you search for &quot;rain&quot; in AssetHoard, you are not just matching filenames. The search understands context. It surfaces rain sound effects, yes, but also thunder recordings, water droplet impacts, storm ambient loops, lightning sprites, puddle textures, wet surface materials, and umbrella models -- because those things all belong to the same conceptual space.</p>
<p>You go from ten minutes of directory archaeology to a single search that shows you everything relevant at once.</p>
<h2 id="tags-categories-and-your-own-taxonomy">Tags, Categories, and Your Own Taxonomy</h2><p>Every developer has a different mental model for their assets. AssetHoard does not impose one.</p>
<p>Tags and categories let you build the taxonomy that makes sense for how you actually think about your library. Tag assets by art style, by project, by quality rating, by mood. Categories give you a flat set of broad groupings you can apply consistently across your library. Assets can have as many tags as they need -- you are not limited to one folder.</p>
<p>The licence field lets you record exactly what you purchased and what it covers. Notes let you capture anything else you will definitely forget -- which pack this came from, where to download updates, quirks you discovered when you imported it.</p>
<h2 id="your-catalogue-and-your-directories-are-independent">Your Catalogue and Your Directories Are Independent</h2><p>This is the detail that matters most practically.</p>
<p>Because AssetHoard tracks assets by reference rather than by path dependency, you can reorganise your catalogue without moving a single file on disk. Create a virtual structure that makes sense to you. Rename things in the catalogue. Reclassify them. None of it touches the directory.</p>
<h2 id="projects-smart-folders-for-active-work">Projects: Smart Folders for Active Work</h2><p>When you are actively working on something, you need a different kind of organisation: not a permanent taxonomy, but a working set.</p>
<p>Projects in AssetHoard work like smart folders you populate yourself. You are building a horror level and need atmospheric audio, dark environment textures, and a handful of character animations. You drop them all into a project. Now everything for that level is in one place, regardless of where the files actually live in your library.</p>
<p>You can have multiple projects running simultaneously. Assets can appear in as many projects as you want. When the project ships, the project goes away. The library stays exactly as it was.</p>
<h2 id="it-adds-up">It Adds Up</h2><p>None of this is revolutionary in isolation. Cataloguing software has existed for decades in photography and stock asset workflows. The game dev world has just been slow to adopt it.</p>
<div class="figure-inline">
<p class="figure-inline__text">What changes when you stop fighting your directory structure is that you start actually using the assets you own. That pack you bought eighteen months ago and never properly ingested. That artist's collection you downloaded and forgot about. They are in there. You just need a way to find them.</p>
<a href="https://assethoard.com/hero/assethoard-hero.png" target="_blank" rel="noopener noreferrer" class="figure-inline__image"><img src="https://assethoard.com/hero/assethoard-hero.png" alt="AssetHoard game asset manager showing a searchable library of game files in a single, browsable view" title="AssetHoard: one searchable library for everything you own" loading="lazy"></a>
</div>

<p>Until now, indie developers have not had a purpose-built asset manager made for them. That is what AssetHoard is for.</p>
<hr>
<p><em>The AssetHoard Team</em></p>
]]></content:encoded>
		</item>
		<item>
			<title>Artist Spotlight: Tesseract Assets</title>
			<link>https://assethoard.com/blog/artist-spotlight-tesseract-assets</link>
			<guid isPermaLink="true">https://assethoard.com/blog/artist-spotlight-tesseract-assets</guid>
			<pubDate>Tue, 17 Feb 2026 00:00:00 GMT</pubDate>
			<dc:creator>The AssetHoard Team</dc:creator>
			<category>Artist spotlight</category>
			<description>We chat with Shaoul from Tesseract Assets about 3D props, weapons, stylised environments, and the invisible work that makes game assets actually work in-engine.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/artist-spotlight/tesseract-assets-hero.jpg" alt="Artist Spotlight: Tesseract Assets" /></p>
<p>Welcome to the first in our Artist Spotlight series, where we chat with creators in the game dev space about their work, their process, and what they&#39;ve learned along the way.</p>
<p>First up is Shaoul from Tesseract Assets, a 3D artist specialising in props, weapons, and stylised environments.</p>
<p><a href="https://assethoard.com/blog/2026/artist-spotlight/tesseract-assets-hero.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/artist-spotlight/tesseract-assets-hero.jpg" alt="Stylised environment scene by Tesseract Assets" width="3302" height="1798" loading="eager" decoding="async"></a></p>
<div style="margin-top: -3.5rem; margin-bottom: -2rem; display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 1rem;">
<div>

<p><a href="https://assethoard.com/blog/2026/artist-spotlight/tesseract-assets-rocks.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/artist-spotlight/tesseract-assets-rocks.jpg" alt="Stylised environment scene by Tesseract Assets" width="2559" height="1550" loading="lazy" decoding="async"></a></p>
</div>
<div>

<p><a href="https://assethoard.com/blog/2026/artist-spotlight/tesseract-assets-weapons.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/artist-spotlight/tesseract-assets-weapons.jpg" alt="Stylised environment scene by Tesseract Assets" width="1919" height="1089" loading="lazy" decoding="async"></a></p>
</div>
<div>

<p><a href="https://assethoard.com/blog/2026/artist-spotlight/tesseract-assets-houses.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/artist-spotlight/tesseract-assets-houses.jpg" alt="Stylised environment scene by Tesseract Assets" width="2559" height="1460" loading="lazy" decoding="async"></a></p>
</div>
</div>

<h2 id="what-kind-of-assets-do-you-create-and-what-got-you-into-it">What kind of assets do you create, and what got you into it?</h2><div style="margin-bottom: -1rem; display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem;">
<div>

<p><a href="https://assethoard.com/blog/2026/artist-spotlight/tesseract-assets-pack.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/artist-spotlight/tesseract-assets-pack.jpg" alt="Stylised nature pack by Tesseract Assets" width="3609" height="1816" loading="lazy" decoding="async"></a></p>
</div>
<div>

<p>I mainly create 3D assets for games, with a focus on small props and weapons. I started out doing smaller, standalone objects because they let me concentrate on shape language, materials, and storytelling without getting overwhelmed by huge scenes.</p>
</div>
</div>

<p>Over time, that naturally grew into building more cohesive sets and recently into stylised environments, where props really shine as part of a bigger world.</p>
<p>What got me into it was the mix of art and problem-solving. I&#39;ve always enjoyed breaking things down visually and figuring out how they&#39;re built, and game assets sit right at that intersection of creativity and technical constraints.</p>
<h2 id="what-does-your-process-look-like-from-concept-to-finished-asset">What does your process look like from concept to finished asset?</h2><div style="margin-bottom: -1rem; display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem;">
<div>

<p>I usually start with reference gathering and visual exploration. I sometimes use AI to generate some reference, even if there&#39;s already a concept. Understanding the style, proportions, and materials upfront saves a lot of time later. I put everything on PureRef to have a general overview.</p>
</div>
<div>

<p><a href="https://assethoard.com/blog/2026/artist-spotlight/tesseract-assets-village.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/artist-spotlight/tesseract-assets-village.jpg" alt="Stylised environment village by Tesseract Assets" width="3482" height="1732" loading="lazy" decoding="async"></a></p>
</div>
</div>

<p>From there, I block out the asset in 3D to lock in the silhouette and scale. Once the shapes feel right, I model and sometimes sculpt to final forms. Texturing comes next, where I really try to push material definition and readability, especially for stylised work.</p>
<p>The final steps are optimisation, testing in-engine when possible, and polishing things like roughness values, edge wear, and overall presentation so the asset holds up from different angles and distances.</p>
<h2 id="what-tools-do-you-use-day-to-day">What tools do you use day-to-day?</h2><p>My core tools are Blender for modelling, Substance Painter for texturing, a bit of ZBrush to sculpt, and Substance Designer for some tiled textures. Unreal Engine 5 for rendering and testing.</p>
<p>I also rely a lot on PureRef for reference and Photoshop for quick texture tweaks or presentation work. Plus some workflow apps like Upscayl, Bulk Rename Utility, XnConvert, ShareX, and Lightshot.</p>
<h2 id="whats-something-most-people-dont-realise-about-creating-3d-assets">What&#39;s something most people don&#39;t realise about creating 3D assets?</h2><div style="margin-bottom: -1rem; display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem;">
<div>

<p>People don&#39;t realise how much time goes into things that aren&#39;t immediately visible, like clean topology, proper UVs, optimisation, and making sure assets behave well in-engine. A model can look great in a render and still cause problems in an actual game.</p>
</div>
<div>

<p><a href="https://assethoard.com/blog/2026/artist-spotlight/tesseract-assets-axe.jpg" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/artist-spotlight/tesseract-assets-axe.jpg" alt="textured Axe by Tesseract Assets" width="1280" height="720" loading="lazy" decoding="async"></a></p>
</div>
</div>


<h2 id="whats-been-your-favourite-project-to-work-on">What&#39;s been your favourite project to work on?</h2><p>My last weapon pack (Volume 5) as it&#39;s the most recent and benefits from the experience gathered doing previous weapon packs.</p>
<iframe width="640" height="480" src="https://www.youtube.com/embed/2Hlseh3xmQM" frameborder="0" allowfullscreen></iframe>

<p>I&#39;m especially proud of my recent shift toward stylised environment work. Moving from individual props and weapons into a more cohesive visual world has been really rewarding. It pushed me to think more about colour, composition, and how assets support each other rather than standing alone.</p>
<h2 id="any-tips-for-game-devs-on-getting-the-most-out-of-assets-theyve-bought-or-downloaded">Any tips for game devs on getting the most out of assets they&#39;ve bought or downloaded?</h2><p>Don&#39;t treat assets as untouchable. Even small adjustments to scale, roughness, colour balance, or wear can make a big difference in how well they fit your project. Consistency matters more than individual detail.</p>
<p>Also, test assets early in-engine and in context. Lighting, shaders, and camera distance can completely change how something reads compared to a standalone render.</p>
<h2 id="what-are-you-working-on-next">What are you working on next?</h2><p>I&#39;m continuing to expand my stylised environment work, focusing on building stronger, more complete scenes and refining my visual language. I&#39;m also experimenting more with storytelling through props and environments, making assets that feel like they belong to a lived-in world rather than just looking good on their own.</p>
<hr>
<p>You can find more of Tesseract Assets&#39; work on:</p>
<ul>
<li><a href="https://www.youtube.com/@TesseractAssets" target="_blank" rel="noopener noreferrer">YouTube</a></li>
<li><a href="https://www.fab.com/sellers/Tesseract%20%20Assets" target="_blank" rel="noopener noreferrer">Fab</a></li>
</ul>
<hr>
<p><em>This is the first in our Artist Spotlight series. If you&#39;re a game asset creator and want to be featured, get in touch at <a href="mailto:mark@assethoard.com">mark@assethoard.com</a>.</em></p>
]]></content:encoded>
		</item>
		<item>
			<title>When 120,000 Files Meet Tauri: A Story of IPC, Rust, and Hard-Won Performance</title>
			<link>https://assethoard.com/blog/when-120000-files-meet-tauri</link>
			<guid isPermaLink="true">https://assethoard.com/blog/when-120000-files-meet-tauri</guid>
			<pubDate>Fri, 30 Jan 2026 00:00:00 GMT</pubDate>
			<dc:creator>The AssetHoard Team</dc:creator>
			<category>AssetHoard news</category>
			<description>How we optimised AssetHoard to handle massive asset libraries without freezing your entire computer.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/100_000-files-meet-tauri.png" alt="When 120,000 Files Meet Tauri: A Story of IPC, Rust, and Hard-Won Performance" /></p>
<h2 id="the-dream">The Dream</h2><p>We built AssetHoard to solve a problem every game developer knows: assets scattered across dozens of folders, forgotten purchases buried in download directories, and no good way to find that perfect texture you know you bought three years ago.</p>
<p>The tech stack was solid. Tauri 2 for the native shell, SvelteKit for the frontend, Rust for the backend, SQLite for storage. Everything worked great in testing.</p>
<p>Then a beta tester tried to import a large asset bundle... 120,000 files.. The app froze for minutes... shit.</p>
<h2 id="the-naive-approach">The Naive Approach</h2><p>Our first implementation was straightforward. Scan the folder in Rust, send the file list to the frontend, let the user configure options, then import:</p>
<pre><code class="hljs language-rust"><span class="hljs-meta">#[tauri::command]</span>
<span class="hljs-keyword">fn</span> <span class="hljs-title function_">scan_folder</span>(path: <span class="hljs-type">String</span>) <span class="hljs-punctuation">-&gt;</span> <span class="hljs-type">Vec</span>&lt;ScannedFile&gt; {
    walkdir::WalkDir::<span class="hljs-title function_ invoke__">new</span>(path)
        .<span class="hljs-title function_ invoke__">into_iter</span>()
        .<span class="hljs-title function_ invoke__">filter_map</span>(|e| e.<span class="hljs-title function_ invoke__">ok</span>())
        .<span class="hljs-title function_ invoke__">filter</span>(|e| <span class="hljs-title function_ invoke__">is_supported_extension</span>(e.<span class="hljs-title function_ invoke__">path</span>()))
        .<span class="hljs-title function_ invoke__">map</span>(|e| ScannedFile::<span class="hljs-title function_ invoke__">from_path</span>(e.<span class="hljs-title function_ invoke__">path</span>()))
        .<span class="hljs-title function_ invoke__">collect</span>()
}</code></pre><pre><code class="hljs language-javascript"><span class="hljs-keyword">const</span> files = <span class="hljs-keyword">await</span> <span class="hljs-title function_">invoke</span>(<span class="hljs-string">&#x27;scan_folder&#x27;</span>, { <span class="hljs-attr">path</span>: selectedFolder });
<span class="hljs-comment">// files now contains 120,000 objects</span>
<span class="hljs-title function_">setScannedFiles</span>(files);</code></pre><p>Simple. Elegant. Completely broken at scale.</p>
<h2 id="the-ipc-wall">The IPC Wall</h2><p>Tauri&#39;s invoke system is fantastic for most use cases. You call a Rust function, it returns data, TypeScript receives it as a Promise. Under the hood, it serialises your Rust structs to JSON, passes them through the webview bridge, and deserialises them in JavaScript.</p>
<p>For 120,000 ScannedFile objects, that meant roughly 70MB of JSON serialisation in Rust, another 70MB crossing the IPC bridge, 70MB of JSON parsing in JavaScript, and 70MB stored in JavaScript memory.</p>
<p>During all of this, the UI thread is blocked. No spinner. No progress. Just a frozen window and a user wondering if the app crashed.</p>
<h2 id="attempt-one-stream-the-data">Attempt One: Stream the Data</h2><p>Our first instinct was streaming. Send files in batches of 1,000, update a progress bar, keep the UI responsive.</p>
<pre><code class="hljs language-rust"><span class="hljs-keyword">for</span> <span class="hljs-variable">chunk</span> <span class="hljs-keyword">in</span> files.<span class="hljs-title function_ invoke__">chunks</span>(<span class="hljs-number">1000</span>) {
    app_handle.<span class="hljs-title function_ invoke__">emit</span>(<span class="hljs-string">&quot;scan-chunk&quot;</span>, chunk)?;
}</code></pre><p>Better! The UI stayed responsive. But now we had a new problem: 80 separate IPC calls, each with serialisation overhead. The scan that took 8 seconds in pure Rust now took 45 seconds with the streaming overhead.</p>
<p>Worse still, we had to accumulate all those chunks in JavaScript memory anyway. We had traded one 70MB transfer for eighty 625KB transfers, plus the overhead of 80 event emissions.</p>
<h2 id="the-revelation-do-not-send-what-you-do-not-need">The Revelation: Do Not Send What You Do Not Need</h2><p>We stepped back and looked at what the import process actually involved. It was not a single operation but a multistep pipeline: scan the filesystem and count files, then process metadata for each asset, then generate thumbnails for previews. For smaller imports of around 2,000 files, running this as one synchronous operation worked extremely well. The user clicked import, waited a few seconds, and everything appeared in their library.</p>
<p>But at 120,000 files, that same pipeline ground to a halt. And the more we looked at it, the clearer it became that we were sending data to the frontend that the frontend did not actually need.</p>
<p>The user does not need to see 120,000 individual files. They need to see the total file count, a breakdown by type (textures, models, audio), a list of top-level folders, and maybe some detected engine packages. Everything else can stay in Rust until import time.</p>
<h2 id="the-cache-pattern">The Cache Pattern</h2><p>We introduced a scan cache on the Rust side:</p>
<pre><code class="hljs language-rust">lazy_static! {
    <span class="hljs-keyword">static</span> <span class="hljs-keyword">ref</span> SCAN_CACHE: Mutex&lt;HashMap&lt;<span class="hljs-type">String</span>, <span class="hljs-type">Vec</span>&lt;ScannedFile&gt;&gt;&gt; =
        Mutex::<span class="hljs-title function_ invoke__">new</span>(HashMap::<span class="hljs-title function_ invoke__">new</span>());
}

<span class="hljs-meta">#[tauri::command]</span>
<span class="hljs-keyword">fn</span> <span class="hljs-title function_">scan_folder_async</span>(path: <span class="hljs-type">String</span>) <span class="hljs-punctuation">-&gt;</span> ScanSummary {
    <span class="hljs-keyword">let</span> <span class="hljs-variable">files</span>: <span class="hljs-type">Vec</span>&lt;ScannedFile&gt; = <span class="hljs-comment">/* ... scan logic ... */</span>;

    <span class="hljs-keyword">let</span> <span class="hljs-variable">scan_id</span> = Uuid::<span class="hljs-title function_ invoke__">new_v4</span>().<span class="hljs-title function_ invoke__">to_string</span>();
    SCAN_CACHE.<span class="hljs-title function_ invoke__">lock</span>().<span class="hljs-title function_ invoke__">unwrap</span>().<span class="hljs-title function_ invoke__">insert</span>(scan_id.<span class="hljs-title function_ invoke__">clone</span>(), files.<span class="hljs-title function_ invoke__">clone</span>());

    ScanSummary {
        scan_id,
        total_files: files.<span class="hljs-title function_ invoke__">len</span>(),
        by_type: <span class="hljs-title function_ invoke__">count_by_type</span>(&amp;files),
        top_level_folders: <span class="hljs-title function_ invoke__">extract_folders</span>(&amp;files),
        detected_packages: <span class="hljs-title function_ invoke__">find_packages</span>(&amp;path),
    }
}</code></pre><p>Now the IPC payload is tiny. Maybe 2KB instead of 70MB. The frontend gets everything it needs to show the user, and when they click Import, we just send the scan_id back:</p>
<pre><code class="hljs language-rust"><span class="hljs-meta">#[tauri::command]</span>
<span class="hljs-keyword">fn</span> <span class="hljs-title function_">import_files</span>(scan_id: <span class="hljs-type">String</span>, options: ImportOptions) <span class="hljs-punctuation">-&gt;</span> ImportResult {
    <span class="hljs-keyword">let</span> <span class="hljs-variable">files</span> = SCAN_CACHE.<span class="hljs-title function_ invoke__">lock</span>().<span class="hljs-title function_ invoke__">unwrap</span>()
        .<span class="hljs-title function_ invoke__">remove</span>(&amp;scan_id)
        .<span class="hljs-title function_ invoke__">ok_or</span>(<span class="hljs-string">&quot;Scan expired&quot;</span>)?;

    <span class="hljs-comment">// Import using the cached files</span>
    <span class="hljs-comment">// ...</span>
}</code></pre><p>The files never cross the IPC bridge. Rust scans them, Rust stores them, Rust imports them.</p>
<h2 id="progress-events-the-right-way">Progress Events: The Right Way</h2><p>With the heavy data staying in Rust, we could use Tauri&#39;s event system for what it excels at: lightweight progress updates.</p>
<pre><code class="hljs language-rust"><span class="hljs-meta">#[tauri::command]</span>
<span class="hljs-keyword">async</span> <span class="hljs-keyword">fn</span> <span class="hljs-title function_">scan_folder_async</span>(path: <span class="hljs-type">String</span>, app: AppHandle) <span class="hljs-punctuation">-&gt;</span> ScanSummary {
    <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut </span><span class="hljs-variable">files</span> = <span class="hljs-type">Vec</span>::<span class="hljs-title function_ invoke__">new</span>();

    <span class="hljs-keyword">for</span> <span class="hljs-variable">entry</span> <span class="hljs-keyword">in</span> WalkDir::<span class="hljs-title function_ invoke__">new</span>(&amp;path) {
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">let</span> <span class="hljs-variable">Ok</span>(e) = entry {
            <span class="hljs-keyword">if</span> <span class="hljs-title function_ invoke__">is_supported</span>(&amp;e) {
                files.<span class="hljs-title function_ invoke__">push</span>(ScannedFile::<span class="hljs-title function_ invoke__">from</span>(&amp;e));

                <span class="hljs-keyword">if</span> files.<span class="hljs-title function_ invoke__">len</span>() % <span class="hljs-number">1000</span> == <span class="hljs-number">0</span> {
                    app.<span class="hljs-title function_ invoke__">emit</span>(<span class="hljs-string">&quot;scan-progress&quot;</span>, ScanProgress {
                        files_found: files.<span class="hljs-title function_ invoke__">len</span>(),
                        current_path: e.<span class="hljs-title function_ invoke__">path</span>().<span class="hljs-title function_ invoke__">display</span>().<span class="hljs-title function_ invoke__">to_string</span>(),
                    })?;
                }
            }
        }
    }

    <span class="hljs-comment">// Cache and return summary...</span>
}</code></pre><p>Now the frontend receives a lightweight event every 1,000 files. Just two fields, maybe 200 bytes. The UI updates smoothly, the user sees &quot;Scanning... 45,000 files found&quot;, and Rust keeps churning through the filesystem.</p>
<h2 id="send-to-background">Send to Background</h2><p>But what if the user does not want to watch a progress bar? What if they want to keep browsing their existing library while the scan runs?</p>
<p>We added a Send to Background button that appears after 2 seconds of scanning. Click it, and the dialog closes, a notification appears in the header with live progress, and when complete, clicking the notification reopens the import dialog with all the options ready.</p>
<p>This required a scan session system. A way to track that a background scan belongs to a specific notification, and when complete, the notification knows how to resume the import flow.</p>
<pre><code class="hljs language-javascript"><span class="hljs-keyword">function</span> <span class="hljs-title function_">handleSendToBackground</span>(<span class="hljs-params"></span>) {
    <span class="hljs-keyword">const</span> notifId = <span class="hljs-title function_">createNotification</span>(<span class="hljs-string">&#x27;import&#x27;</span>, <span class="hljs-string">`Scanning <span class="hljs-subst">${folderName}</span>`</span>, {
        <span class="hljs-attr">progress</span>: { <span class="hljs-attr">current</span>: scanProgress, <span class="hljs-attr">total</span>: scanProgress },
        <span class="hljs-attr">status</span>: <span class="hljs-string">&#x27;in_progress&#x27;</span>,
    });

    <span class="hljs-keyword">const</span> sessionId = <span class="hljs-title function_">createScanSession</span>(folderPath, notifId);
    backgroundScanSessionId = sessionId;
    backgroundNotifId = notifId;

    importDialogOpen.<span class="hljs-title function_">set</span>(<span class="hljs-literal">false</span>);
    <span class="hljs-comment">// Original scan continues running...</span>
}</code></pre><h2 id="the-subtle-race-condition">The Subtle Race Condition</h2><p>This is where we learned a painful lesson about async state management.</p>
<p>Our first implementation of Send to Background cancelled the current scan (set SCAN_CANCELLED = true), closed the dialog, and started a new scan in the background. Seemed logical.</p>
<p>But there was a bug. In Rust, every scan starts by resetting the cancellation flag:</p>
<pre><code class="hljs language-rust"><span class="hljs-keyword">fn</span> <span class="hljs-title function_">scan_folder_async</span>(...) {
    SCAN_CANCELLED.<span class="hljs-title function_ invoke__">store</span>(<span class="hljs-literal">false</span>, Ordering::SeqCst);  <span class="hljs-comment">// Reset flag</span>
    <span class="hljs-comment">// ... scan logic that checks SCAN_CANCELLED ...</span>
}</code></pre><p>When we started the new background scan, it immediately cleared the cancellation flag before the original scan had checked it. Result: two concurrent scans, both running, both emitting progress events, interleaving their results.</p>
<p>The fix was embarrassingly simple: do not start a new scan. The original scan is already running. Just set up the notification tracking and let it complete.</p>
<h2 id="results">Results</h2><p>Before optimisation, 120,000 files caused a 47 second freeze. Users reasonably assumed the app was broken.</p>
<p>After optimisation, 120,000 files scan in 8 seconds with live progress. Users can send to background and keep working. Memory usage dropped by roughly 70MB because the files never hit the JavaScript heap.</p>
<h2 id="lessons-learned">Lessons Learned</h2><p><strong>IPC is not free.</strong> Treat the Tauri bridge like a network call. Minimise payload size, batch intelligently, and do not send data you do not need on the frontend.</p>
<p><strong>Keep heavy data where it belongs.</strong> If Rust is going to use the data anyway, let Rust hold it. Send summaries and IDs across the bridge, not raw data.</p>
<p><strong>Events are for progress, not data transfer.</strong> Tauri&#39;s event system is great for lightweight updates. Do not abuse it as a chunked data transfer mechanism.</p>
<p><strong>Async state is tricky.</strong> When you have operations that can be cancelled, restarted, or sent to background, trace through every possible interleaving. Race conditions hide in the gaps.</p>
<p><strong>The user&#39;s time is sacred.</strong> A frozen UI is not just a performance problem. It is a trust problem. If users cannot tell whether your app is working or crashed, they will assume crashed.</p>
<hr>
<p><em>The AssetHoard Team</em></p>
]]></content:encoded>
		</item>
		<item>
			<title>The 15 Best Free HD Game Asset Sites in 2026</title>
			<link>https://assethoard.com/blog/where-to-find-free-game-assets-2026</link>
			<guid isPermaLink="true">https://assethoard.com/blog/where-to-find-free-game-assets-2026</guid>
			<pubDate>Tue, 20 Jan 2026 00:00:00 GMT</pubDate>
			<dc:creator>The AssetHoard Team</dc:creator>
			<category>Guides</category>
			<description>Hand-picked HD game asset sites for 2026. 2D sprites, 3D models, PBR textures, audio. Mostly CC0, no sign-up, free for commercial use.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/blog/2026/asprite-animation.png" alt="The 15 Best Free HD Game Asset Sites in 2026" /></p>
<p><em>Last updated April 2026</em></p>
<p><a href="https://assethoard.com/blog/2026/asprite-animation.png" target="_blank" rel="noopener noreferrer"><img src="https://assethoard.com/blog/2026/asprite-animation.png" alt="AssetHoard Asprite" width="1780" height="888" loading="eager" decoding="async"></a></p>
<p>Asset hunting is one of the great time sinks of indie game development. You sit down to build a level and somehow lose the morning to forum threads, broken Patreon links, and downloads that turn out to be 32x32 placeholders in disguise.</p>
<p>The good news is that 2026 is a genuinely excellent year to be doing this. Plenty of artists, studios, and one-person operations now release HD, professional-quality work for free, often under licences that let you ship commercially without attribution.</p>
<p>Here are 15 sites worth bookmarking, grouped by what they&#39;re best at.</p>
<p>We&#39;ve also gathered the best CC0 picks from across these sites into a single <a href="https://assethoard.com/free-game-assets">free game assets directory</a> you can filter by type, style, and engine, then jump straight to the source. It&#39;s a good starting point before you go spelunking through the full catalogues below.</p>
<h2 id="the-all-rounders">The All-Rounders</h2><p>These sites cover multiple asset types and should be your first stops.</p>
<h3 id="itch-io">itch.io</h3><p>The indie darling of game distribution also happens to be one of the best places to find free assets. Head to <a href="https://itch.io/game-assets/free" target="_blank" rel="noopener noreferrer">itch.io/game-assets/free</a> and you&#39;ll find everything from pixel art character sprites to complete game kits with 3D models, audio, and animations bundled together.</p>
<p>The curation is decent, the community is active, and you can filter by asset type, art style, and licence. Many creators release their work under CC0 (public domain), meaning you can use it commercially without attribution.</p>
<p><strong>Best for:</strong> 2D sprites, pixel art, complete game kits, audio packs</p>
<h3 id="opengameart-org">OpenGameArt.org</h3><p>The granddaddy of free game assets. OpenGameArt has been around for over a decade and hosts a massive collection of 2D art, 3D models, music, and sound effects—all under open licences like CC0, CC-BY, or GPL.</p>
<p>The search tools are... functional, let&#39;s say. But the depth of the library makes up for it. You&#39;ll find everything from retro pixel art to orchestral soundtracks.</p>
<p><strong>Best for:</strong> Large variety, open-source projects, finding hidden gems</p>
<h3 id="kenney">Kenney</h3><p>If you don&#39;t know Kenney, you&#39;re missing out. This one-person operation has released over 40,000 assets—all CC0, all free, no sign-up required. The art style is clean, colourful, and remarkably consistent across packs, which means you can mix and match assets without your game looking like a ransom note.</p>
<p>The <a href="https://kenney.nl" target="_blank" rel="noopener noreferrer">kenney.nl</a> site offers 2D assets, 3D models, UI elements, fonts, and audio. There are also free tools like Asset Forge for creating your own 3D models.</p>
<p><strong>Best for:</strong> Consistent art style, rapid prototyping, UI elements</p>
<h3 id="unity-asset-store-free-section">Unity Asset Store (free section)</h3><p>Unity&#39;s <a href="https://assetstore.unity.com/?free=true" target="_blank" rel="noopener noreferrer">free asset filter</a> sits inside a paid marketplace, which makes it easy to overlook, but the free catalogue is enormous. Big publishers regularly release free packs to seed adoption of their commercial ones, and Unity itself publishes high-quality demo assets and starter kits.</p>
<p>Worth a periodic browse rather than a one-off visit. Licences vary across publishers, so check each pack before shipping.</p>
<p><strong>Best for:</strong> Unity-ready 2D and 3D packs, demo content, professional publishers</p>
<h2 id="2d-assets">2D Assets</h2><h3 id="craftpix">CraftPix</h3><p><a href="https://craftpix.net/freebies/" target="_blank" rel="noopener noreferrer">CraftPix.net</a> offers free 2D game assets including tilesets, character sprites, backgrounds, icons, and GUI elements. Their &quot;Game Kits&quot; are particularly useful—complete sets with everything you need for a particular genre or theme.</p>
<p>The freebies are a subset of their paid catalogue, so quality is generally solid. Assets work well with engines like Unity, Godot, and Construct.</p>
<p><strong>Best for:</strong> 2D platformers, RPGs, mobile games</p>
<h3 id="chequered-ink">Chequered Ink</h3><p>A smaller studio that releases pixel art assets alongside their commercial games and fonts. You&#39;ll find character sprite packs, inventory icons, platformer tilesets, and UI graphics—all free for commercial use.</p>
<p>Check their <a href="https://chequered.ink/category/game-assets/free-game-assets/" target="_blank" rel="noopener noreferrer">free game assets section</a> for regular updates.</p>
<p><strong>Best for:</strong> Pixel art, retro-styled games</p>
<h2 id="3d-models">3D Models</h2><h3 id="quaternius">Quaternius</h3><p>If you&#39;re making a 3D game with a stylised low-poly look, <a href="https://quaternius.com" target="_blank" rel="noopener noreferrer">Quaternius</a> is essential. This Argentinian artist has released thousands of models—characters, animals, vehicles, environments, weapons—all under CC0.</p>
<p>The signature &quot;Quaternius style&quot; is instantly recognisable: clean geometry, bright colours, charming animations. Assets come rigged and animated, ready to drop into Unity, Unreal, or Godot.</p>
<p><strong>Best for:</strong> Low-poly 3D games, stylised aesthetics, animated characters</p>
<h3 id="poly-haven">Poly Haven</h3><p><a href="https://polyhaven.com" target="_blank" rel="noopener noreferrer">Poly Haven</a> started as HDRI Haven and has grown into a comprehensive library of 3D models, HDRIs, and textures—all CC0. The models tend toward realistic props and environmental pieces rather than stylised game assets, but they&#39;re high quality and instantly usable.</p>
<p>No sign-up required. Just download what you need.</p>
<p><strong>Best for:</strong> Realistic 3D assets, environment art, lighting reference</p>
<h3 id="sketchfab">Sketchfab</h3><p><a href="https://sketchfab.com" target="_blank" rel="noopener noreferrer">Sketchfab</a> is primarily a 3D model marketplace, but there&#39;s a substantial collection of free downloads. Filter by &quot;Downloadable&quot; and check the licence for each asset—many are CC0 or CC-BY.</p>
<p>The built-in 3D viewer lets you inspect models before downloading, which saves time.</p>
<p><strong>Best for:</strong> Browsing and previewing 3D models, varied styles</p>
<h3 id="mixamo">Mixamo</h3><p><a href="https://www.mixamo.com" target="_blank" rel="noopener noreferrer">Mixamo</a> is Adobe&#39;s free library of rigged characters and motion-captured animations. Sign in with an Adobe ID, pick a character, and apply any animation in the library. Everything is free for commercial use, with no royalties or attribution required.</p>
<p>The animation set covers walks, runs, combat, idles, and more abstract dance and gesture clips. There is also auto-rigging for custom characters you bring in yourself, which saves a serious amount of time if rigging is not your strong suit.</p>
<p><strong>Best for:</strong> Rigged 3D characters, motion-capture animations, prototyping movement</p>
<h2 id="textures-and-materials">Textures and Materials</h2><h3 id="ambientcg">ambientCG</h3><p>Formerly CC0Textures, <a href="https://ambientcg.com" target="_blank" rel="noopener noreferrer">ambientCG</a> offers over 2,000 PBR materials, HDRIs, and 3D models—all completely free under CC0. Materials come with all the maps you need: albedo, normal, roughness, metallic, height, and ambient occlusion.</p>
<p>Assets are available in resolutions up to 8K (or even 16K for some), and Substance Designer source files are available for Patreon supporters.</p>
<p><strong>Best for:</strong> PBR textures, realistic materials, HDRIs</p>
<h3 id="cgbookcase">CGBookcase</h3><p>Another solid CC0 texture source. <a href="https://www.cgbookcase.com" target="_blank" rel="noopener noreferrer">CGBookcase</a> has a smaller library than ambientCG, but the quality is excellent and the site includes tutorials on creating your own PBR textures.</p>
<p><strong>Best for:</strong> High-quality PBR textures, learning texture creation</p>
<h2 id="audio-music-and-sound-effects">Audio: Music and Sound Effects</h2><h3 id="freesound">Freesound</h3><p><a href="https://freesound.org" target="_blank" rel="noopener noreferrer">Freesound.org</a> is a collaborative database of Creative Commons licensed sounds. With over 600,000 audio samples, it&#39;s massive—though quality and licensing vary by upload. Filter by CC0 if you want no-strings-attached usage.</p>
<p>The search can be finicky, but the depth of the library is unmatched for specific sound effects.</p>
<p><strong>Best for:</strong> Specific sound effects, ambient audio, foley</p>
<h3 id="sonniss-gdc-audio-bundles">Sonniss GDC Audio Bundles</h3><p>Every year for GDC, <a href="https://sonniss.com/gameaudiogdc/" target="_blank" rel="noopener noreferrer">Sonniss</a> releases a free bundle of professional game audio. The archive now contains years&#39; worth of these bundles—we&#39;re talking gigabytes of royalty-free sound effects you can use commercially with no attribution required.</p>
<p>These aren&#39;t amateur recordings. They&#39;re from professional sound libraries, and they&#39;re genuinely excellent.</p>
<p><strong>Best for:</strong> High-quality sound effects, bulk downloads</p>
<h3 id="pixabay">Pixabay</h3><p>Yes, the stock photo site. <a href="https://pixabay.com/sound-effects/" target="_blank" rel="noopener noreferrer">Pixabay</a> also has a growing library of royalty-free sound effects and music. Everything is CC0-equivalent, so you can use it commercially without attribution.</p>
<p>The search and filtering are better than most audio sites.</p>
<p><strong>Best for:</strong> Quick sound effect searches, background music</p>
<h2 id="a-note-on-licences">A Note on Licences</h2><p>Before you ship anything, double-check the licence on every asset you use. The main ones you&#39;ll encounter:</p>
<ul>
<li><strong>CC0 / Public Domain</strong>: Use however you want. No attribution required. Commercial use allowed.</li>
<li><strong>CC-BY</strong>: Free to use, but you must credit the creator.</li>
<li><strong>CC-BY-SA</strong>: Free to use with attribution, and derivative works must use the same licence.</li>
<li><strong>GPL/LGPL</strong>: Common for code; can have implications for your project if not careful.</li>
</ul>
<p>When in doubt, read the licence. It takes 30 seconds and can save you headaches later.</p>
<h2 id="keeping-it-all-organised">Keeping it all organised</h2><p>Here&#39;s the thing about free assets: you&#39;ll download more than you use. Way more. That sprite pack catches your eye, then a tileset, then some sound effects, then a character pack &quot;just in case&quot;—and suddenly you&#39;ve got thousands of files scattered across your downloads folder, external drives, and cloud storage.</p>
<p>Finding that one animation you remember downloading six months ago becomes an archaeological expedition.</p>
<p>Once you have a library worth searching, <a href="https://assethoard.com">AssetHoard</a> is a <a href="https://assethoard.com">game asset manager</a> built for exactly this problem. Import your downloaded packs, preview files without opening another app, and drag assets directly into Unity or Godot. It supports 80+ formats including .unitypackage, .aseprite, .fbx, .gltf, .wav, and more—all searchable and previewable in one place.</p>
<p>One-time purchase, local-first, no subscription. Your files stay on your machine.</p>
<h2 id="the-bottom-line">The Bottom Line</h2><p>You don&#39;t need to spend money to make a good-looking game. The resources above represent thousands of hours of work that creators have generously made available to the community—often under licences that let you use them commercially without restriction.</p>
<p>The challenge isn&#39;t finding free assets. It&#39;s finding the right assets, keeping them organised, and actually using them before you forget they exist.</p>
<p>Now stop reading and go make something.</p>
<hr>
<p><em>The AssetHoard Team</em></p>
]]></content:encoded>
		</item>
		<item>
			<title>Welcome to AssetHoard: Your Digital Dragon&apos;s Treasure Cave</title>
			<link>https://assethoard.com/blog/hello-world</link>
			<guid isPermaLink="true">https://assethoard.com/blog/hello-world</guid>
			<pubDate>Thu, 09 Jan 2025 00:00:00 GMT</pubDate>
			<dc:creator>The AssetHoard Team</dc:creator>
			<category>AssetHoard news</category>
			<description>We built the asset manager we wished existed. No accounts, no subscriptions, no uploading your files to someone else&apos;s server. Just you and your hoard.</description>
			<content:encoded><![CDATA[<p><img src="https://assethoard.com/releases/v0.1.0/assethoard-v0.1.0.png" alt="Welcome to AssetHoard: Your Digital Dragon&apos;s Treasure Cave" /></p>
<h2 id="the-quest-begins">The Quest Begins</h2><p>If you&#39;ve ever whispered &quot;where did I put that texture?&quot; into the void at 2 AM, congratulations. You&#39;re our people.</p>
<p>We&#39;re the AssetHoard team, and we&#39;ve spent the last year building the asset management tool we desperately needed but couldn&#39;t find. You know the drill: you&#39;ve got .blend files in three different folders, a Unity Asset Store backlog that rivals your Steam library (we see you), and somewhere in the depths of your Downloads folder lurks that <em>perfect</em> sprite sheet you bought six months ago.</p>
<p>Welcome to the hoard. Make yourself at home.</p>
<h2 id="why-we-built-this-thing">Why We Built This Thing</h2><p>Here&#39;s the thing about existing asset management solutions: they either want your firstborn child (subscription fees), your data (cloud-mandatory uploads), or they&#39;re so complex you need a PhD in taxonomy just to organize your pixel art.</p>
<p>We wanted something different:</p>
<ul>
<li><strong>Local-first, because your assets are <em>yours</em>.</strong> Everything lives on your machine in a SQLite database. No accounts.  We literally cannot see your files, and we like it that way.</li>
<li><strong>Actually searchable.</strong> Tags, filters, metadata extraction. Find that one PBR material set from 2019 without excavating through folder archaeology.</li>
<li><strong>Preview everything.</strong> Over 30 formats including Aseprite animations, glTF models (spinnable!), PSD layers, and audio with waveforms. No more &quot;let me just open Blender real quick to see what this is.&quot;</li>
<li><strong>Drag and drop into your engine.</strong> Unity and Godot integration that just works. Like it should. In the year 2025.</li>
</ul>
<h2 id="whos-this-for">Who&#39;s This For?</h2><p><strong>Indie game devs</strong> drowning in assets from too many Humble Bundles and itch.io sales. We&#39;ve been there. We bought the 47,000-asset mega pack too.</p>
<p><strong>2D artists</strong> with Aseprite files scattered across project folders like confetti. Now you can see your animations <em>without</em> opening Aseprite.</p>
<p><strong>3D artists</strong> who need to preview that FBX without launching a full DCC application. Spin it, zoom it, check the polycount. Move on.</p>
<p><strong>Sound designers</strong> with audio libraries that have grown beyond mortal comprehension. Waveform previews and inline playback mean you can audition sounds without leaving your library.</p>
<p>Basically, if you make things and those things have become... <em>many</em>... we built this for you.</p>
<h2 id="the-tech-under-the-hood">The Tech Under the Hood</h2><p>For the nerds in the audience (that&#39;s a compliment), here&#39;s what&#39;s powering the hoard:</p>
<p>The <strong>desktop app</strong> is built with <strong>Rust</strong>, running on Windows, macOS, and Linux. We&#39;re using <strong>SQLite</strong> for the database because it&#39;s battle-tested, fast, and (crucially) entirely local.</p>
<p>This <strong>website</strong> you&#39;re reading? <strong>SvelteKit</strong> with static site generation, deployed to GitHub Pages. TypeScript throughout, because we have <em>some</em> self-respect. No dark patterns, no cookie banners (we don&#39;t track you), no &quot;sign up to continue reading.&quot; Just... a website. Revolutionary, we know.</p>
<h2 id="whats-next">What&#39;s Next?</h2><p>We&#39;re actively building. The <a href="https://assethoard.com/roadmap">roadmap</a> has the full picture, but the highlights:</p>
<ul>
<li><strong>Collections</strong> for organizing assets into project-specific groups</li>
<li><strong>Improved 3D management</strong> with better material handling</li>
<li><strong>Blender file support</strong> (yes, .blend previews—we&#39;re working on it)</li>
<li>And eventually, a <strong>plugin system</strong> for the power users who want to extend things</li>
</ul>
<h2 id="join-the-party">Join the Party</h2><p><a href="https://assethoard.com/purchase">Get AssetHoard</a>, throw your chaotic asset folders at it, and let us know what you think. We&#39;re building this for the community, and your feedback shapes where we go next.</p>
<p>Got questions? Feature requests? Found a bug? Hit us up through the <a href="https://assethoard.com/contact">contact form</a> or just yell into the void on social media. We&#39;re listening.</p>
<p>Now if you&#39;ll excuse us, we need to go organize our own asset libraries. They&#39;re... <em>fine</em>. Everything is fine.</p>
<hr>
<p><em>The AssetHoard Team</em></p>
<p>P.S. No light mode. We&#39;re not monsters.</p>
]]></content:encoded>
		</item>
	</channel>
</rss>