Reap is a game made in GameMaker by Daniel Linssen for Ludum Dare 34. This thread will detail my efforts in attempting to make a Unity version of the game, a fan project if you will, because Reap is a truly spectacular game, especially considering it’s been made in less than 48 hours.
Reap is an exploration game with a procedurally generated world. It has stunning pixel art, but it also has this really ingenious gameplay mechanic where you’re given a map, but the map doesn’t show your own location, you have to figure that out based on the landmarks around you, and thanks to the fantastic procedural world generator in the game, you’re given a huge new world with interesting landmarks for every new playthrough.
The world generator was the reason I decided to download the source code for Reap even though the game is made with GameMaker, a game engine I know practically nothing about. Initially I was thinking about just trying to learn enough about GameMaker and Daniel’s code to be able to fish the world generator code out of there, but I’ve decided that I’m going to challenge myself and try to port Reap in it’s entirety from GameMaker to Unity. By trying to port the entire game I’m hoping to gain some valuable knowledge about doing pixel art games in Unity as well, because like most GameMaker games, Reap is pixel perfect and that’s not something that’s easily achieved in Unity. The motivating factor here is that the original game was made in under 48 hours, which means there can’t possibly be that much for me to port, right? I guess time will tell.
Whenever I accomplish something noteworthy I will upload a Web Player build for you to play with and after (if) I finish the game I will make the entire project available to download for free. I’m also considering writing an accompanying article detailing anything I learned in regards to this. Perhaps there are other people out there who are curious about the differences between Unity and GameMaker and what it is like to port a 2D game made in a 2D engine into a 3D engine.
Disclaimer: I’ve spoken with Daniel and I’ve been given permission to do this. Everything in the project will remain the property of Daniel Linssen - all the graphics, the sounds, and the source code belongs to him. You’re free to download the project, learn from it and play around with it, but don’t redistribute it and please don’t be a dick and try to sell it.
I will be back shortly with more information, in the meantime you can check out the original game or some of Daniel’s other games through the links below.
The original GameMaker game is available from Daniel’s website, here:
Also consider checking out Daniel’s other games, they are all really clever and beautifully crafted:
Such a cool idea. More people should try to do this kind of thing. There are a lot of great games made in these jams by devs using GameMaker, Construct and so forth.
I’ve currently managed to get the world generator working and I’ve uploaded the first build to my website. Here’s an image of the sort of world it creates:
There are hundreds of thousands of sprites in this image and Unity has crashed at least a dozen times while I’ve been working on this. It’s perfectly fine when you’re viewing just a small section of the map at the time, which will be the case in the actual game, so I doubt I’m going to optimize it any, but if there are some simple tricks I can do I would like to hear them.
You can try out the current build, version 0.0.1 :p, here:
Interesting discoveries so far:
In both GameMaker and Unity C# you can have implicitly typed variables, that is using the “var” keyword instead of int, float etc. When porting this game I chose to explicitly type each variable just to get a better understanding about what I was working with because there seems to be a lot of implied casts between float and int in the original source code, which isn’t allowed in C#.
irandom_range() in GameMaker is inclusive for the max value, Random.Range() in Unity is exclusive for the max value so everywhere this function is used I’ve had to increase the max value by 1 to achieve the same range.
In GameMaker 0,0 on the coordinate system is top left, in Unity 0,0 is bottom left. This meant a few changes had to be made regarding the tile map. This took me a few hours to figure out.
Thanks, and yeah. The code for the world generator I could pretty much just copy and paste into Unity and it worked. I had to change the syntax to C# of course, but there wasn’t much more to it than that. This actually surprised me a bit. I thought GameMaker was more like that visual scripting asset, PlayMaker?, or Blueprint in Unreal Engine. But it turns out it’s very familiar if you’re used to Unity. The project is organized in much the same way, you can debug your code in much the same way. It wasn’t hard to get used to at all.
I’m doing everything I can to make this port as identical to the original as possible which means implementing some of the standard GameMaker quirks as well. Just like almost any GameMaker game out there Reap is framerate dependent, so I’ve made my Unity version framerate dependent as well, even though it pained me to do it. You also move faster diagonally just like in the original game.
I know GameMaker has delta time, but almost no developers seem to use it. It seems like a really poor practice to me. Perhaps it’s not taught in the beginner tutorials or something. Reap is a 48-hour game so I won’t read much into it here, but I have a lot of released games on Steam made with GameMaker that are framerate dependent.
It also seems like this project is going to take a lot longer than I anticipated. Mostly because 2D in Unity is really foreign to me, but at the same time it seems to to a lot more convoluted than I expected it to be at this point. Porting the world generator was really easy because it was so engine-agnostic, but sprite drawing etc. is trivial in GameMaker and apparently extremely involved in Unity. From what I can gather I have to involve Mecanim, the dope sheet and do so much just to be able to animate a sprite. I honestly thought I could just assign a sprite to the sprite renderer and give it a framerate or something like that. Why is it so convoluted?
But we’ll see once I get to that. It’s probably the next thing I tackle. Read below for all the changes to this version.
Changes for version 0.1.0:
Removed the initial debug camera and world re-generation functionality.
Implemented the player character with grid based movement just like in the original.
All the input methods of the original should work the same here.
Implemented collision detection. With the grid based movement and Daniel’s clever algorithm this collision detection is just 1(!) line of code.
I’ve left my debug boxes in there so you can see how funky the character is positioned on the grid. It took me many hours to figure that one out.
The player spawning code which ensures the player spawns with some room around him is implemented, but because you don’t yet have the axe you may be forced to restart the game if you spawn in a less than ideal position.
I’ve also tweaked the pixel perfect rendering in this build.
I postponed the animations because I felt it was more important the game was properly playable first. In this update I’ve added the axe and you can use it to traverse the entire world. Chop down trees, build rafts and bridges and go where no one has gone before.
I’m still amazed at how much code I can pretty much take directly out of GameMaker and paste into Unity and have it work, but I sense I will have some pretty major challenges ahead of me when it comes to dealing with sprites. One such challenge I’ve already faced and I haven’t found a very good solution for it yet. In GameMaker you have access to direct draw methods and can just draw sprites anywhere you want without consequence. In Unity you can’t do that. So I’ve had to refactor some code to keep track of prefab instances and swap the parent/position of those instead of just being able to draw sprites for anything whenever I feel like it. One clear example of this is the raft. I still haven’t found a good way for interpolating its movement so at the moment it jumps to the next grid position when you use it. In the original game Daniel just draws the raft sprite independently of the raft object using GameMaker’s draw_sprite() function. I guess I would have to put the sprite as a child of the raft or something to be able to do something similar in Unity.
But when it comes to sprite animation and the definition of a sprite in Unity I don’t really understand the reasoning behind it. There seems to be no way to access a “sprite strip” or “sprite sheet” in Unity because Unity’s definition of a sprite is just 1 frame of the sprite. I don’t get that at all. Why isn’t a sprite the entire thing and then in the sprite renderer we can reference the individual frames as we please? I guess I will need to write some helper classes for this part as I refuse to use Mecanim for it, that’s just way too overkill for something like this, and I would constantly have to fight transitions and all the other crap Mecanim throws at you.
I’ve already made one helper script:
using UnityEngine;
using UnityEditor;
public class SpritePostProcessor : AssetPostprocessor {
/// <summary>
/// Allows you to assign defaults to the texture importer so you don't have
/// to set the same values manually for every sprite you import.
/// </summary>
void OnPostprocessTexture(Texture2D texture) {
// I found this line of code through Google. I don't know how it works,
// but without it you're not able to change texture importer values
// manually anymore. With this line the defaults below only apply to
// newly imported textures.
Object asset = AssetDatabase.LoadAssetAtPath(assetPath, typeof(Texture2D));
if (asset) {
return;
}
// Set the defaults we want all the sprites in our project to have.
TextureImporter textureImporter = assetImporter as TextureImporter;
textureImporter.spritePixelsPerUnit = 1;
textureImporter.filterMode = FilterMode.Point;
textureImporter.mipmapEnabled = false;
textureImporter.textureFormat = TextureImporterFormat.AutomaticTruecolor;
}
}
You place it in a folder named “Editor” in your project and it sets the default texture import values for all the sprites you add to your project. Very handy compared to having to set them manually for every single sprite.
Changes for version 0.2.0:
Added the axe. Use it to cause global warming.
You can now chop down trees and use the logs that drop to build rafts and bridges.
This means the entire world should be explorable now.
Added the ambient wind sound. It feels a bit louder in Unity than in GameMaker. Not sure if it’s just me or if there’s a difference there.
Removed the debug visuals, they are no longer needed.
More interesting discoveries:
The tilemap in Reap is offset so the player is actually walking on the corners between the tiles rather than in the middle of the tiles (this is visible in my screenshot from version 0.1.0). This means that when you chop down a tree you’re not interacting with just 1 tile, but with 2x2 tiles. I still don’t know why it’s done this way, but I’m sure it has something to do with the very sleek algorithm used for finding the correct neighbour tiles.
GameMaker has a special keyword called “with” which allows you to very easily run code on all instances of a prefab. What I’m doing in Unity to approximate this is to keep track of all instances of a prefab in a list and then iterate over that list wherever the original code uses “with”. It seems to work fine, but it obviously requires quite a bit more code than the GameMaker alternative.
I’d just make a wrapper function using the name irandom_range() that adds one to the max value. Then use that function for everything and you can basically copy and paste without needing to be sure you are continually incrementing the max value. Just something to consider.
Yeah, I could do that, but that would be more work than putting on a +1. Anyways, I’m making this for people who use Unity, but I’m commenting the source code sort of as if you were switching from GameMaker to Unity or had experience with both engines. I’ll do an evaluation of the entire project before I release it to see what makes the most sense. At the moment the Unity source code is probably ~90% identical to the GameMaker source code and if it stays like that I’ll probably keep Daniel’s original naming conventions etc. just to keep the two sources as identical as possible, but if it turns out I have to make big changes to make it work in Unity I may just refactor everything to use my own naming conventions.
At the moment I’m also making an effort to stay as faithful to the original GameMaker source as possible, even in places where Unity offers tools that perhaps make more sense. Like for instance the “with” statement. In Unity I could use triggers, bounding boxes or raycasts to find the item I’m standing on, rather than looping over all the items in the world to see if there is one under my feet, but it’s fun trying to replicate the original exactly.
Thanks, yeah, I played through most of the top 100 games and this one really stood out to me as something special. After playing it I started following Daniel on Twitter, checking out his website etc. and he’s constantly making amazing games.
No new content has been added in this version, but I’ve polished everything up quite a bit and I’ve put down a lot of the foundation for completing the rest of the game. I’ve added controllers for handling animations and sounds among other things.
For the animations I knew I didn’t want to mess around with Mecanim. I’ve tried that before and it was awful. But as it turns out, making my own sprite animator wasn’t much work at all, and best of all it supports some of the same tricks that GameMaker and the original Reap utilizes. Here’s the code for it in its current form. I will surely tweak it some before I’m done with the game:
using UnityEngine;
public class SpriteAnimator : MonoBehaviour {
[System.Serializable]
public class Animation {
public string name;
public Sprite[] frames;
}
public Animation[] animations;
// Set this to control the speed of the animation.
[HideInInspector]
public int fps;
// Set this to control the animation to play.
[HideInInspector]
public string currentAnimationName = "";
// Set this to control the current frame of the animation. F. ex. setting
// fps to 0 and this to 0 let's us show only the initial frame of the animation
// for as long as we wish.
[HideInInspector]
public int currentFrame;
// The default sprite is the one we've assigned to the sprite renderer.
// Store it here so we can put it back later if we need to. We'll lose the
// one on the sprite renderer when we play an animation.
[HideInInspector]
public Sprite defaultSprite;
SpriteRenderer spriteRenderer;
Animation currentAnimation;
string lastAnimationName = "";
float timer;
void Start() {
spriteRenderer = GetComponent<SpriteRenderer>();
defaultSprite = spriteRenderer.sprite;
}
void Update() {
// Don't do anything if there is no animation assigned.
if (currentAnimationName == "") {
return;
}
// If the name for the current animation is different from the animation
// we played last frame it means we should swap the animation we're playing.
if (currentAnimationName != lastAnimationName) {
SetAnimation(currentAnimationName);
}
// This is a really clever way of handling looping.
// Taken from GameMaker, and inspired by Daniel Linssen's code.
currentFrame = currentFrame % currentAnimation.frames.Length;
// If the framerate is zero don't calculate the next frame, just keep
// returning the current frame. We can change the current frame
// from outside this script and animate the sprite this way as well.
if (fps == 0) {
spriteRenderer.sprite = currentAnimation.frames[currentFrame];
return;
}
timer += Time.deltaTime;
if (timer > (1f / fps)) {
timer = 0;
spriteRenderer.sprite = currentAnimation.frames[currentFrame];
currentFrame++;
lastAnimationName = currentAnimationName;
}
}
void SetAnimation(string name) {
foreach (Animation animation in animations) {
if (animation.name == name) {
currentAnimation = animation;
}
}
}
}
It’s almost no code at all, but it works almost perfectly in my opinion. The coolest thing about it is the looping mechanism, which for all I know may be the standard way of doing something like this, but it surely wasn’t my initial approach. Rather than writing something like:
if (currentFrame >= currentAnimation.frames.Length) currentFrame = 0;
which in fact was my initial approach I’m instead using the modulus operator to loop the animation. The reason I started investigating this at all was because the code in the original game was asking for frames 0-20 when it was animating a 3 frame animation. How this could work at all made no sense to me until I found a section about it in the GameMaker documentation. It described that asking for frame 4 in a 3 frame animation would return frame 1, asking for frame 6 would return frame 3 and so on. It just counts over the frames like 1,2,3,1,2,3 until it reaches the frame number you asked for. And using the modulus operator gives me this exact functionality. It has no downsides and it makes it a whole lot easier to animate certain things. The axe swinging animations uses this functionality.
To use the sprite animator just put it on a game object with a sprite renderer. And then to play the different animations you do something like:
if (_v < 0) {
spriteAnimator.currentAnimationName = "s_player_south";
}
else if (_h < 0) {
spriteAnimator.currentAnimationName = "s_player_west";
}
else if (_h > 0) {
spriteAnimator.currentAnimationName = "s_player_east";
}
else if (_v > 0) {
spriteAnimator.currentAnimationName = "s_player_north";
}
where _v and _h are the values returned from Input.GetAxis. To control the speed you just set the fps. Set it to 0 when you’re standing still and to whatever value you like when you’re moving. It’s just as simple as it is in GameMaker which is what I wanted. That is one way of animation your sprite, but you can also animate the sprite by setting the current frame directly, which is what I’m doing for the axe swinging animation, just like in the original GameMaker version of the game.
My biggest gripe with 2D and sprites in Unity so far is the fact that a sprite in Unity is just 1 frame of a sprite and not the entire sheet. There doesn’t seem to be any way to get a reference to the entire sheet. With the current method whenever I change anything in my animation like for example add a new frame or reorder the frames I have to add all the frames to my public variables in the inspector again. I just don’t understand why Unity decided to do it this way.
Ohh, and I also figured out why audio was much louder in Unity than in GameMaker. You set the volume directly on the audio clips in GameMaker. You set them by dragging a slider between what I assume is 0 and 1, but there is no label on the slider so I’ve had to guess what volume I should set each sound to in Unity, but at least it sounds a lot nicer now and a lot more like the original.
Changes for version 0.3.0:
Added a custom sprite animator script so I won’t have to mess around with Mecanim and the dope sheet.
Added animations to the player and the axe.
Added most of the sounds in the game.
Fixed the raft movement.
Reordered some of the sprites to make them appear correctly behind and in front of the player depending on the context.
hm not sure what you mean with “you can’t get reference to whole sheet” I was quite sucessfully using a sprite sheet with unity and it was holding all my animations which I imported as a (quite huge) sprite sheet and I could then define in unity which sprites from that sheet it should use and I was able to reimport the sheet and just reassign those which I had changed or maybe I missunderstood what you mean, but it doesn’t seem right that unity would make this more difficult…
I can only assign 1 frame of my sprite animation to that variable. If I try dragging the entire sprite sheet onto the variable in the inspector Unity still only assigns the first frame. So the only way for me to get a reference to the entire sprite animation is to define it as:
public Sprite[] sprites;
and drag all the individual frames to the variable, but then every time I make a change to the sheet I will have to update the reference because I’m not referencing the sheet, I’m referencing specific frames in the sheet. In GameMaker you reference the sheet and then say that you want frame 0, frame 1, frame 2 etc. I don’t understand why we can’t do that in Unity.
I was thinking that if a sprite in Unity held a reference to the entire sheet then we could do things like sprite.index[0] to get the first frame, and ideally we would be able to set things like framerate etc. directly on the sprite renderer to animate our sprites. I don’t feel like this would have many downsides, but it would make it a whole lot easier to work with sprite animation in Unity. The sprite renderer could assume a framerate of 0 and show the first frame of the sprite by default to ensure todays functionality is kept intact. At least in my opinion.
A workaround I thought about was to change my code to:
public Texture2D spriteSheet;
and assign the texture (my sprite sheet) to this variable, and then in code programatically create the individual frames as sprites, but that means bypassing the entire sprite importer and sprite editor and it will only work if I’m using grid based animation so it felt too hacky.
okay what I mean is, that whenever you create a spritesheet in unity you can open all it’s frames inside your asset folder by clicking the little arrow on it and then you can shift+left click to select all the frames you want and then rightclick and “create animation”
it creates an animation file which includes those frames you selected and as far as I know, then you can use Animationclips: Unity - Scripting API: AnimationClip
to define framerate, to play it etc.
then you would only need to update the animations which frames you changed in a sprite sheet.
I should mention that this approach is best used with making an animation file for every movement you want from a spritesheet to gain the most out of it, so not making the whole spritesheet into an animation
Yeah, that’s the approach I meant when I initially mentioned Mecanim and the dope sheet. To each his own I guess, but I feel that way of doing it was very clumsy. I have an older project where I tried doing it like you describe, but in my opinion the way I’m doing it here in Reap is much faster and more intuitive. It’s just missing a few tiny features.
Perhaps it’s possible for me to create my own asset type or something in Unity, but I have never tried doing something like that. It’s perhaps also possible to extend the default sprite renderer to make it include my sprite animator functionality or something like that as well, but these are advanced topics that I haven’t explored yet, and probably won’t bother to explore with this project.
But the thing you say about having a big sprite sheet and not wanting to make the entire thing into a single animation is a good point. For this project I’m using the original art files and each animation is a separate sprite sheet. I like this way of doing it as it’s very organized, but I agree but both ways would have to be supported. I guess Unity’s current implementation support them both equally well/bad.
I am glad I am not the only one who finds that animation system very tedious to work with. It is far simpler to just code it up. I just define arrays of Sprite for the anims and load them in the editor. Then it is super easy to animate everything exactly as you want in code by defining animation tables. Certainly more efficient than working in the editor to do it or at least for me (and apparently you) it is.
I also used the array animation way as I am not used to Mecanim, but I did some research beforehand and thought this was an interesting read. In the end it really depends on the situation…
I’m glad somebody found that article useful! Yes, I agree, in a case like this it is much easier to just take control of the sprite frames yourself. Unity’s animation system is very powerful, particularly if you need to animate colliders or sub-objects of any kind, but for a lot of games (like this one) you don’t need all that.