read

Builderment is a game about building and automation, so it’s only natural that the development process is also automated. As a programmer my philosophy is to do as little work as possible. But that doesn’t mean to cut corners and deliver a worse product, instead it means use code to do much more work than I ever could manually.

My approach to creating game assets is similar; repeat myself as little as possible. Some Blender tools like the mirror & array modifiers help immensely when creating models. But I’m no where close to good enough to writing a guide on how to model in Blender. I do however have two small but incredibly useful tools that make development easier. First is the workflow I have for exporting all game assets to Xcode, and second is linking materials in Blender to easily change the visuals of all assets.

First let us export all the assets.

Scripts to export and convert game assets

Once I had more than a couple models in the game I wanted a way to easily re-export and convert them to usable SceneKit files. The process to do that was anything but straight forward or well documented 🙄. Hopefully this helps someone in the future who is in need of a similar setup.

The first step was to find a way to get blender to export objects from the command line. Luckily Blender has a very comprehensive Python API. With that I was able to create this simple Python script that can export a .dae file by running the command
blender $FILE_TO_EXPORT -b -P scripts/export-dae.py.

file: scripts/export-dae.py

#!/usr/bin/env python3

import bpy
import os

# The export command is configured to only export selected objects.
# Select all objects that are not hidden from the renderer.
for obj in bpy.context.visible_objects:
    obj.select_set(not obj.hide_render)

# Create output file from the asset's file name
# ex. assets/models/copper_ore.blend => assets/exports/copper_ore.dae
output_path = os.path.basename(bpy.data.filepath)
output_path = os.path.splitext(output_path)[0]
output_path = "/assets/exports/{}.dae".format(output_path)

# Export as collada (.dae)
bpy.ops.wm.collada_export(filepath=output_path,
                          check_existing=False,
                          filter_collada=True,
                          apply_modifiers=True,
                          selected=True,
                          use_texture_copies=False)

As I learn more about scripting in Blender I want to add more commands here to create a camera and lights to render an image for the icons/thumbnails in the game.

The second and final script calls that first script on each .blend file in my models folder and saves them to an exports folder. Then it converts each .dae file to a .scn file using the scntool command built into Xcode. Lastly it copies the textures into the games directory incase anything changed (note to self: I should first remove the existing textures from that folder).

file: scripts/convert-game-assets.py

#!/usr/bin/env python3

import glob
import os
import subprocess

# glob all .blend files and export them as .dae objects
blender_files = glob.glob("assets/models/*.blend")
for file in blender_files:
    blender_export_cmd = "blender {} --factory-startup --background --python scripts/export-dae.py".format(file)
    subprocess.run(blender_export_cmd, shell=True, check=True)

# Convert exported collada models to SceneKit .scn files
convertable_files = glob.glob("assets/exports/*.dae")
for file in convertable_files:
    asset_name = os.path.basename(file)
    asset_name = os.path.splitext(asset_name)[0]
    # scntool options list https://gist.github.com/matux/4a30c4b4b29d636fe6847b6a3234bc4f
    convert_cmd = ["xcrun scntool",
                   "--convert {}".format(file),
                   "--format scn",
                   "--force-y-up",
                   "--output ios/GameAssets.scnassets/{}.scn".format(asset_name)]
    rt = subprocess.run(' '.join(convert_cmd), shell=True, check=True)
    if rt.returncode == 0:
        os.remove(file) # cleanup exported .dae file

# Copy textures to scenekit assets texture directory
copy_textures_cmd = "cp -R assets/textures/ ios/GameAssets.scnassets/textures/"
subprocess.run(copy_textures_cmd, shell=True, check=True)

While these scripts are specific to .dae and .scn files I hope the concept is abstract enough that you could use in your own workflow.

Linking Materials

Working with a low poly style means I have materials/textures that can to be repeated in many of the assets. Truth be told it took me a while to find this solution but now that I did it’s incredibly useful. I created a Library.blend file that contains all the reusable content such as materials or meshes that get linked into the individual asset files. Combined with the previous scripts it’s easy to change the material in one place and have all the game assets updated in seconds.

Reloading is useful if you changed something in the library blend-file and want to see those changes in your current blend-file without having to re-open it.

Blender 🙌

It looks a little something like this:

Blender material linking workflow

There are a lot of options for game dev in iOS including Unity, UE4, or Godot. If you’re interested in why Builderment is built in Swift and SceneKit have a quick read through my first dev log.

Follow and Subscribe 👍

This journey is just beginning. If you like what you read I’ll be posting more of it, hopefully weekly. Currently on twitter and instagram sharing images and videos from development. Reach out via email or come join discord!

Twitter @builderment
Instagram @builderment
Discord https://discord.gg/VkH4Nq3
Email contact@builderment.com

Blog Logo

Builderment


Published