SpriteKit vs Unity: Scripts

One of my goals this year was to learn Unity. There is a local indie game developer meet up that I attend with some awesome accomplished game developers. I started going while I was working on the Metal book to ask how to break into the game industry. The primary thing they told me was to know Unity. I thought that knowing Metal and programming would be enough to get into the industry, but I have found a lot of people don’t really know what Metal is.

Additionally, knowing programming and knowing how to work with an incredibly powerful and complex tool are two entirely different skills. As someone who spent two years learning Pro Tools and Photoshop, I am painfully aware of how important it is to have an idea about what a tool can do and how to best utilize it.

Also, honestly, if you’re not going to bother to learn something in your spare time, then it’s probably not that important to you. I can understand the barrier to entry being at least having a working sample project in a skill as opposed to just saying “I want to be a game designer!!” I understand that not everyone has vast amounts of free time to spend dicking around with every cool game engine out there. A lot of people are parents and have family obligations and I am in no way shaming those people because family is way more important than mucking around with programming 24/7. But if you do have a lot of free time and you spend it partying or whatever, then the cool thing is really not that important to you. There’s nothing wrong with that. I want to be in better shape but not enough to actually make time to go to the gym.

If you’ve been reading my blog, you know that right now I am trying to build a game in SpriteKit. I have been interested in SpriteKit since it was released several years ago, but it took me a while to come to grips with how it works. You learn best by having a project that you try to get working, so that is the point of the tic tac toe project. So most of my background in game development is doing native Apple game development with their frameworks, languages, and workflow.

One thing that massively confused me when talking to people who primarily came from Unity was scripting. With SpriteKit, everything I do is done in code. They have an Interface Builder-esque tool that I have not yet used in any real capacity, but beyond that everything is done in code. Sprites are placed and skinned in code. They are moved in code. Labels are created in code.

I asked about the point of scripting over coding. I was told it is easier to edit a script than it is to change things in code. That made no sense to me because if you have to edit something in Xcode it doesn’t really matter where it is, the amount of work is the same.

So one big thing I wanted to get out of learning Unity was to get a better idea about what is meant by scripting as opposed to what I am familiar with from SpriteKit. I have only been working with Unity for about two weeks. I am working through the Unity Games by Tutorials book from Ray Wenderlich. There will probably be things that I am missing in this post about scripting because I still haven’t used it much, but these are kind of my initial thoughts coming in from another perspective.

SpriteKit

The approach I have seen most people take in SpriteKit programming is to approach solutions in a third-person, God-like perspective. There is a single update() method that you code with everything you want to happen on each iteration of the game loop. There is a method to detect touches and within that method to express what you want to have happen when the user touches the screen.

You create subclasses of game scenes, but not really of SKSpriteNode. You create instances of SKSpriteNode named for the different objects you have in the game with different sizes and textures, but you tend to generally not subclass SKSpriteNode.

I will be showing a few examples of what I mean using the first project from Ray Wenderlich’s SpriteKit book. Yes, I use a lot of his books. No, I am not getting paid to shill them. They are good examples of showing how to put a completed project together and I find it useful.

The first game you build in that book is a 2D platformer called Zombie Conga. The point of the game is to bite cats to turn them into zombies while avoiding crazy cat ladies. You win when you reach a certain number of cats or you lose if you collide with too many cat ladies.

The project is architected with a lot of small methods that involve explaining an action you want to occur. One such action is move:

func move(sprite: SKSpriteNode, velocity: CGPoint) {
	let amountToMove = velocity * CGFloat(dt)
	sprite.position += amountToMove
  }

This is a reusable method that can have any instance of SKSpriteNode and any point passed into it. Within the project, there is actually only one instance where you are using this method, and it’s on the zombie protagonist:

move(sprite: zombie, velocity: velocity)

The entire project is composed of small methods that are abstracted away from the main game loop so that it’s not cluttered by every little thing it needs to do. Here is an example of an update() method in a game scene in SpriteKit:

override func update(_ currentTime: TimeInterval) {
	if lastUpdateTime > 0 {
	  dt = currentTime - lastUpdateTime
	} else {
	  dt = 0
	}
	lastUpdateTime = currentTime

	move(sprite: zombie, velocity: velocity)
	rotate(sprite: zombie, 
               direction: velocity, 
               rotateRadiansPerSec: zombieRotateRadiansPerSec)

	boundsCheckZombie()
	moveTrain()
	moveCamera()

	if lives <= 0 && !gameOver {
	  gameOver = true
	  print("You lose!")
	  backgroundMusicPlayer.stop()
	}
  }

You don’t necessarily have to understand everything this is doing, but just look at how this is laid out. The update is nearly entirely composed of method calls to abstracted methods within the game scene. You pass in the sprite you want to modify for some of these. Other void methods such as moveCamera() directly mutate a specific SKSpriteNode instance that is not subclassed. The way of thinking about a SpriteKit project is from a God-like perspective where you think about all of the things you want to do and how to move your pieces around to make it happen. You abstract out methods even if they are only called once and only work on one instance of SKSpriteNode.

Unity Scripts

Unity takes a fundamentally different approach to game objects than SpriteKit does. I mentioned a few times that in SpriteKit you don’t really subclass SKSpriteNode. This is not how Unity deals with game objects.

In Unity, game objects tend to start out as meshes that you import from a tool like Blender. These objects have meshes, materials, and animations associated with them. These can be composed of multiple meshes that are imported separately. All of these aspects are collected together into a single game object called a prefab. Instead of creating a generic Unity sprite node, you create instances of these prefabs in your game. You can apply a change to a prefab universally among all the instances of the prefab or you can create changes locally to a single instance of a prefab.

One fidgety and highly powerful feature of Unity is the ability to add components to both the prefabs and instances of the prefabs. These components include physics, rendering, and scripting.

Scripting is more like a first person perspective as opposed to the third person God perspective utilized in SpriteKit. Instead of thinking of your methods globally, you think about them as being the internal monologue of your game object. These scripts watch for input and respond to it rather than creating a method around the input method.

I have a script for a gun in the learning project I am working on. The update method in it’s script looks like this:

void Update () {

    if (Input.GetMouseButtonDown (0)) {
        if (!IsInvoking ("fireBullet")) {

            InvokeRepeating ("fireBullet", 0f, 0.1f);

        }

    }



    if (Input.GetMouseButtonUp (0)) {
        CancelInvoke ("fireBullet");

    }

}

The script is actively observing the mouse button input and making a determination about its behavior based on the button’s state. The script only knows about itself and anything that impacts its ability to function. Rather than having an update method that is controlling the gun, the alien, and the protagonist, each of these objects has their own self-encapsulated update method.

This is a different way of doing things. I can see how this would be more efficient when you reach a certain scale of project. Even within the small SpriteKit projects I have worked on, I have found project organization to be difficult. My logic always looks messy and I actively look for ways to abstract logic away from my main game scene.

I am not certain if this a pattern that can be applied to SpriteKit or not. I know in programming there isn’t anything that is impossible, but there are ways of working with and against a framework. I could completely recreate Android’s UI in iOS using views and so forth, but why would I want to?

I do know that Apple also has a supplementary framework called GameplayKit that includes an entity-component system. Ray Wenderlich’s SpriteKit book used to have several chapters on this system, but those chapters were replaced with tile maps in the latest version. A few of GameplayKit’s functions, such as state machines, seem to have been coopted by Swift’s architecture. I am uncertain if Swift protocols could fulfill a similar function to entity-components or if SpriteKit and Unity have incompatible design patterns. Either way, it’s a different way of approaching the problem of coordinating actions and behaviors on game objects.

Components vs @IBInspectable

I would be remiss in not explaining the single biggest feature that make scripts easier to work with in Unity. One big aspect of game development is the ability to tweak variables to tune the game. The line between the game being fun and impossibly hard isn’t very wide.

Having to open up a script and dig around in code to change a time or a number of spawned objects is a bad design pattern, especially if you are considering that your user base isn’t necessarily composed of programmers. Unity is designed to be worked on by large teams of people who do things other than programming. It’s important for a designer to be able to change variables easily on the fly.

Unity gets around this by integrating the scripts with the user interface. In your script, you can make a determination about what variables you have that may need to be changed to tune the game. These can be made public within the script:

Unity looks in these scripts to see what variables are public and exposes them within the UI so they can be modified and edited without having to open the script editor:

People can sell scripts on the Unity marketplace, so it’s possible for someone who has no programming experience at all to be able to buy a script written by someone else and use it effectively without looking at it once. The programmer part of me feels dirty when thinking about this, but there are many roles on a game development team that don’t require programming. Creating a system that allows these people to work quickly and effectively by abstracting away that unnecessary complexity is smart. I can also see why it would be a lot easier to just change a value in a field within the IDE than it would be to open the code and find the variable and edit that crap by hand.

The closest thing I think Xcode has to this design pattern is @IBDesignable and @IBInspectable. If you are creating custom views/buttons/etc… in iOS, you can tag your subclass as @IBDesignable. You can then publicly expose properties you want to tweak by tagging them as @IBInspectable. Xcode will see these tags and modify itself to allow you to change these within Interface Builder. There is a great tutorial about doing this with Core Graphics here.

Conclusions

I have really been enjoying getting familiar with Unity. Before I got into programming I spent a lot of time learning Photoshop and Illustrator. It always astonished me how much you can do with these complex and powerful tools. I can appreciate the fact that a lot of work is abstracted away that doesn’t really matter.

For the last few years I have felt somewhat creatively shut down. I dwelled on implementation details and mechanics because they were a comfortable place to be. Something either works or it doesn’t. You spend a lot of time thinking about how something works rather than thinking about what you want to create with it.

Going back and doing Unity and SpriteKit, and to a more limited extent Illustrator, has stimulated areas of my brain that had kind of shut down. I abandoned design because I thought it was too subjective and that I would never be good at it. I forgot how wonderful it feels to understand a tool well enough to use it to express something you’re thinking or feeling or imagining.

I am glad that I have gotten over my stubbornness about learning Unity. It’s a large and complex tool. I needed some time to mentally process the idea of jumping into this tool and to organize myself so I don’t just curl up in a ball and sob. I feel actively excited about scripting in Unity and I’m looking forward to figuring out some sample projects I can do with it.