October 12, 2012 0

A fling with MVC and Games

By in Code theory, Unity3D

Well well, it’s been 6 months since I last posted, you know how it is. Since my last post I took part in the Ludum Dare 48 hour game jam based on theme ‘Evolution’ and created Kitty Breeder 2012. I’ve also released an iOS game that with my company called Electric Tentacle - I was Lead Developer and Game Designer on this project.

But that’s not what this post is about. This week I’ve been experimenting with using the MVC pattern for programming our next game which is particularly logic, data and UI heavy. It’s been an interesting week. Every day I’ve left the office frustrated with MVC in general, not just with using it in Unity, but there are things that the pattern just seems terrible at. Then every morning I wake up and think I have a solution to the problem – I just wasn’t using MVC properly. So, is it really worth that hassle? MVC has some good things, but it seems like every new feature I try to add MVC just gets in the way of getting it done. So this post is my way of evaluating whether or not it’s worth it.

What I like about MVC

Event Driven Data

In MVC the Model has no reference to the View. That means you need to update your View indirectly by using the Observer pattern. In Unity this is done easily by using events and property accessors. I’ve built a simple generic class called Subject that fires an event ‘Changed’ whenever the subjects data is assigned to. Additionally it fires this event whenever the listener is first added to make for easy initialisation. Models have Subjects and Views listen for ‘Changed’ events coming from those subjects. When they receive the new data they update the view and the job is done. The alternative is calling functions to update that part of the view whenever some data changes, but what happens if you want two different views displaying the data of one model? Trust me, if you’ve never used this pattern then you should start using it right away.

Separation of Responsibilities

MVC creates a very clear separation of responsibilities. In MVC each ‘entity’ in your system is actually a Triad of classes that work together.

The Model class handles the ‘business logic’ of the triad i.e. a player has ‘health’ and colliding with an enemy subtracts some health.

The View class maintains the graphical representation of the Triad i.e. it listens for changes in the health of the player and changes the colour and size of a UI element.

The Controller class is responsible for detecting input from the user and telling the Model or View how to update i.e. the user pressed the ‘jump’ button so the Controller tells the Model to jump which in turn fires a ‘jumped’ event that the view listens for and plays the jump animation. Or perhaps the user pressed the ‘third person’ button which would prompt the Controller to tell the View to switch to third person mode.

Decoupling

If you were smart and used interfaces to connect up your Triad then now it’s easy to swap any part of the triad out and change the behaviour of the system. For example you could switch the JoystickPlayerController out for a KeyboardPlayerController without having to change a single line in the other classes. Or you could attach a PlayerInventoryView and PlayerInventoryController that displays info about what the player has equipped and allows input to change the very same PlayerModel. If all of the responsibilities for the system were in one class this job would be much harder.

What I HATE about MVC

Now this is where in all likelihood I just don’t know how to do MVC properly. I’ve been wracking my brains trying to figure out ways to do these things but all my solutions break the rules somehow, or make things more longwinded or complicated than they ought to be.

To the end user Controller and View are the same

So separating them just makes things that much more difficult especially when using complex gestures such as drag and drop. This is alleviated a bit by allowing the View to interpret user input and publish distinct events for the Controller to react to e.g. InventoryItemDroppedOnInventorySlot. However this leaves the Controller with little to do except translate the events into commands the Model understand. It becomes little more than an adapter.

Observing object references gets messy!

Maybe the Observer pattern is only really meant for primitive types, but I’ve been using it for references to Model instances in other triads. While this is really useful and you can do some cool stuff, things get tricky when you start listening for changes to references and then listening for events on those references. Cleaning up your listeners can be pretty tricky. An interesting way I got around this was to also pass the old value of the Subject’s data while passing the new value. This means you can remove your listeners to the old reference and add new listeners to the new reference. Today I found myself adding an extra layer of listeners. I can see this pattern turning into something even worse then spaghetti code – events make control flow harder to read at the best of times but adding Observers to references that you got via an Observer than you got via an Observer is just getting ridiculous.

MVC doesn’t associate Models with a ‘main’ View

Suppose you have an InventoryModel class that holds a list of InventoryItemModels but you want to know when any of the respective InventoryItemViews is double-clicked. The problem is that InventoryItemModel has no reference to any View because there might be multiple Views referencing the same model. The way I’ve gotten around this is to mirror events from the View in the Model. For example InventoryItemController might listen for the DoubleClicked event from InventoryItemView and then call EquipRequested on the InventoryItemModel. InventoryController would listen for this even on each InventoryItemModel and then perform the appropriate action to equip the item on the Player. Maybe a better way would be to have the InventoryView reference each of the InventoryItemViews, but then you have a duplication of structure in the Model and View. If the Model simply held a reference to a ‘main View’ then this problem would be far less long winded.

Conclusions

Before trying to use MVC I just got things done, I made them work. Fast. Now I worry more about the architecture than the problem. With Electric Tentacle we kind of used MVC when building the meta-game. We had AchievementViews that displayed the state of their respective Achievements. We had ShopItemViews that displayed ShopItems. When those items changed their events fired and the Views updated. Somehow it all just worked, we never got caught up on how we were going to get hold of references.

I think the difference was that none of this data was hierarchical, it was just lists of objects that had data – they didn’t reference other objects that also needed displaying. The structure of the data was also static, objects started in a collection and stayed there. With my current project that simply isn’t the case. Objects are moving around all the time and creating Views that can react to these changes is proving problematic. In the real world objects are their representation. They can’t be looked at in two ways at the same time. Games are pretty much always abstractions of the real world, so generally in games an object only has one representation at a time.

The game I’m working on is FULL of complexly structured data and references between objects that change all the time. It has requirements where data can only change once the View has completed it’s animation in order to reflect previous changes in the data. There is absolutely no physics in this game or strange 3D logic. This game is purely about the data and the interaction between data, so silly old me thought maybe MVC was a good candidate for structuring this program.

I feel like I’ve contracted some nasty disease from MVC. It’s promises of clean code seduced me, but actually I feel like this was the dirtiest code I ever wrote. Where before I would see a problem to solve and would come up with a solution for it, now I have a solution and a desperate struggle to make it fit the problem.

Last week I still loved coding. Creating abstract mathematical representations of real world systems was one of my favourite activities. The problem I have with MVC is I just can’t make it represent real world systems. It’s great at representing data but it’s terrible at representing structure and for me at least, structure is way more interesting than data. I know I’m an MVC noob. I bet there are solutions to all of the problems I found this week. The thing is, I don’t want to solve coding problems, I want to solve system modelling problems.

Next week I’m going to set about tearing down all of the crap MVC has made me produce. Don’t worry, I’m still going to hold on to my beloved Observer pattern, but this time the structure of my architecture is actually going to represent the structure of my system.

Goodbye MVC.

Tags: , , , , ,

April 1, 2012 0

Wheeler Dealer

By in Games, Unity3D

Last month I finally got around to making an entry for the Experimental Gameplay Project! I’ve been meaning to enter for a while but never summoned up the effort or courage to attempt it. This month was different. I actually started work on two different ideas and managed to finish the good one to quite a high degree of polish.

I even got a great little review from the guys at EGP.

Extremely addictive truck delivery game about making a selling various goods.  Traveling and time burn fuel.  Looking forward to updates on this one!

You can try it out here - Wheeler Dealer

Read the rest of this entry »

Tags: , , ,

December 9, 2011 2

A Vector3 Cross Product optimisation

By in Code theory, Free Code, Unity3D

I’m about to implement a custom LineRenderer for Unity3D as I’ve noticed that the built-in one does not batch draw calls properly. I’m gonna be rendering a lot of lines, so an extra draw call for each LineRenderer isn’t really acceptable.

One of the calculations you have to perform to find the vertex positions for the line is to get the cross product of the direction of the line with the direction the camera is facing. So for every line segment that’s a cross product – 6 multiplications and 3 subtractions. In my case I need quite a few segments, and they’re going to be updating in real time. This is going to be running on mobile, so I’m trying to eek out every last bit of performance I can.

In my case the camera is always facing in the same direction as it’s a 2D game so the cross product will always be of the form Vector3.Cross(lineDirection,-Vector3.forward). Surely there is some mathematical optimisation that can be done there! Yep, and it’s really simple!

public static Vector3 ForwardCross( Vector3 v ) {
	return new Vector3( v.y, -v.x, 0 );
}

That’s a saving on 6 multiplications and 2 subtractions (does negation count as subtraction?!). So I was expecting some pretty amazing performance increase from this…

For 100,000,000 random vectors and cross products, computed on my laptop:

Normal Cross Time: 13.187
Quick Cross Time: 11.354
Performance increase: 13.9%

What, is that it?! So what about manually inlining the function:

Normal Cross Time: 12.723
Quick Cross Time: 9.381
Performance increase: 26.2%

That’s more like it. But weird… I was under the impression that C# dynamically inlined functions. Maybe it’s different on the mobile, needs testing!

So another lesson learned – if you need a cross product with a constant vector, premultiply; and (maybe) manually inline functions if they’re called a lot!

December 2, 2011 0

Unity3D Perlin Benchmark

By in Code theory, Unity3D

I was wondering if the Perlin noise class from this package was quicker than the built in Mathf.PerlinNoise(x,y). So I did some quick benchmarks! For 1,000,000 Perlin look-ups the time taken was:

  • Built-in 2D Perlin took: 0.09539998s
  • C# 1D Perlin took: 0.04631203s
  • C# 2D Perlin took: 0.167416s

So if you just need 1 dimensional Perlin noise use the C# class rather than Mathf.PerlinNoise(x,0f). For 2 dimensional Perlin noise use the built-in function (although it’s not documented so is it even officially supported?!). For 3D Perlin noise you’re stuck with the C# class.

November 29, 2011 1

Reaching Terminal Velocity

By in Code theory, Free Code, Unity3D

Limiting a rigidbody’s velocity is a problem I’ve tried to solve in Unity over and over again with this trick:

rigidbody.velocity = Vector3.ClampMagnitude( rigidbody.velocity, terminalVelocity );

The problem with this method is that by setting the velocity in every frame, adding forces to the rigidbody can’t have any effect. In general, using this trick has always led to strange things happening. There must be a better solution.

Recently I remembered my high school physics lessons about how objects have a terminal velocity – a velocity they cannot move quicker than. This occurs when drag (a force proportionate to the object’s velocity) cancels out the constant force on the body (such as gravity). I realised this could be used with Unity’s built in drag to get a very simple solution for limiting velocity on bodies with a constant force applied.

So first I had to make an assumption about Unity’s drag equation. I guessed at this:

Vector3 dragForce = -rigidbody.velocity * rigidbody.drag

Terminal velocity occurs when the constant force and the drag force are equal, so this can be rearranged to find the drag required for a particular terminal velocity.

rigidbody.drag = boostForceMagnitude / terminalVelocity;

Simple right? Actually, it turns out that the drag equations can’t be what I thought. I did some tests with this method and it turned out that the limiting velocity was always exactly 0.2 less than what I wanted, no matter what the boostForceMagnitude or terminalVelocity was… So a bit of fiddling and it turned out that drag must have some sort of dependency on the length of the time step. I also tried to emulate the ConstantForce component in FixedUpdate and interestingly it turns out that it doesn’t scale the force by Time.fixedDeltaTime … So that means if you use this component (or indeed drag), changing your time step will have side-effects on your physics.

rigidbody.drag = boostForceMagnitude/ ( terminalVelocity + 10f*Time.fixedDeltaTime );

The full ‘Boost’ class:

using UnityEngine;
using System.Collections;

public class Boost : MonoBehaviour {
	
	public float acceleration, terminalVelocity;
	
	// Use this for initialization
	void Start () {
		float boostForceMagnitude = rigidbody.mass*acceleration;
		rigidbody.drag = boostForceMagnitude/(terminalVelocity+10f*Time.fixedDeltaTime);
		ConstantForce f = gameObject.AddComponent();
		f.relativeForce = Vector3.forward*boostForceMagnitude;
	}
	
	void OnGUI() {
		GUI.Label( new Rect(0,0,200,20), "Speed: " + rigidbody.velocity.magnitude.ToString("N4") );
	}
	
}

This implementation will only limit velocity when you have a constant force on your body. Soon I’ll try to work out a generic solution to clamping velocity within a certain range just with drag. I wonder if there is an analytical solution using momentum or something…

October 26, 2011 0

Spinors

By in Free Code, Unity3D

I was prototyping for a *top secret 2D project* yesterday when I realised that Slerping (Spherical Linear Interpolation) a 3D vector just doesn’t work when you need to stay constrained to 2D. That’s when I found this article about Spinors, which are essentially 2D Quaternions, along with an implementation (in Visual Basic?!).

So I went ahead and ported the code for Unity3D and it seems to work really well! So thanks to Parade of Rain for the base code.

using UnityEngine;

public class Spinor
{

	float real;
	float complex;

	public Spinor (float angle)
	{
		angle *= 0.5f;
		real = Mathf.Cos (angle);
		complex = Mathf.Sin (angle);
	}

	public Spinor (float realPart, float complexpart)
	{
		complex = complexpart;
		real = realPart;
	}

	public Spinor GetScale (float t)
	{
		return new Spinor (real * t, complex * t);
	}

	public Spinor GetInvert ()
	{
		Spinor s = new Spinor (real, -complex);
		return s.GetScale (s.GetLengthSquared ());
	}

	public static Spinor operator + (Spinor a, Spinor b)
	{
		return new Spinor (a.real + b.real, a.complex + b.complex);
	}

	public float GetLength ()
	{
		return Mathf.Sqrt (real * real + complex * complex);
	}

	public float GetLengthSquared ()
	{
		return (real * real + complex * complex);
	}

	public static Spinor operator * (Spinor a, Spinor b)
	{
		return new Spinor (a.real * b.real - a.complex * b.complex, a.real * b.complex + a.complex * b.real);
	}

	public Spinor GetNormalized ()
	{
		float length = GetLength ();
		return new Spinor (real / length, complex / length);
	}

	public float GetAngle ()
	{
		return Mathf.Atan2 (complex, real) * 2f;
	}

	public static Spinor Lerp (Spinor startVal, Spinor endVal, float t)
	{
		return (startVal.GetScale (1f - t) + endVal.GetScale (t)).GetNormalized ();
	}

	public static Spinor Slerp (Spinor start, Spinor end, float t)
	{
		float tr;
		float tc;
		float omega, cosom, sinom, scale0, scale1;
		
		//calc cosine
		cosom = start.real * end.real + start.complex * end.complex;
		
		//adjust signs
		if (cosom < 0) {
			cosom = -cosom;
			tc = -end.complex;
			tr = -end.real;
		} else {
			tc = end.complex;
			tr = end.real;
		}
		
		// coefficients
		if ((1f - cosom) > 0.001f) {
			//threshold, use linear interp if too close
			omega = Mathf.Acos (cosom);
			sinom = Mathf.Sin (omega);
			scale0 = Mathf.Sin ((1f - t) * omega) / sinom;
			scale1 = Mathf.Sin (t * omega) / sinom;
		} else {
			scale0 = 1f - t;
			scale1 = t;
		}
		
		//calc final
		Spinor res = new Spinor (0f, 0f);
		res.complex = scale0 * start.complex + scale1 * tc;
		res.real = scale0 * start.real + scale1 * tr;
		return res;
	}

	public static float Slerp2D (float fromAngle, float toAngle, float t)
	{
		Spinor a = new Spinor (fromAngle);
		Spinor b = new Spinor (toAngle);
		return Spinor.Slerp (a, b, t).GetAngle ();
	}
	
}
October 10, 2011 0

One day game – ‘Survival’

By in Games, One day games

Another week another one day game! This time the theme was ‘survival’. It turned out really, really simple and but I think it’s a good a base for a more elaborate game. The idea is that you are stranded on a chain of desert islands and must try to find enough food to survive. The problem is that much of the available food is below the sea and is only exposed at low tide.

You can try it out here!

October 2, 2011 0

One day game – Advance To Contact H-Hour

By in Games, One day games

The idea for this one came about while chatting with @inslayn about old games we’d made. One of his was ‘Advance to contact H-hour’ – a military term for something to do with artillery and death and suchlike. But the game didn’t match the title so we both decided to jam on it and see what happened. Here is the result of my weekends coding. If you don’t like cute sphere men being brutally shot to pieces in bloody explosions then don’t press play…

PLAY IT HERE!!!

OK so this one was a little more than a day, but it was totally worth it. Most of the SFX were done with bfxr and the music was written by me with Logic Pro.

September 26, 2011 0

5 hour game!

By in Games

Wow, what a prolific weekend I’ve had. Internet has been up and down all day so what else could I do but program?! This time Sandra gave me the verb ‘Run’ as inspiration. First thought was Canabalt (ugh) so I took the other meaning of ‘Run’ I know, which is to run a program.

The game that has emerged is definitely not a casual one. In fact I think to really play well you probably need to be like a chess grand master and plan many moves in advance. I thought the rules were actually quite simple, but when I wrote them down I realised there are a lot of them, and they are rather complex. Even with zero randomness (except for the starting position), a lot of different situations can emerge.

A lot of the rules were added so that infinite loops are impossible. I believe it is also impossible for the player to help create an infinite loop (and thus an infinite score) by clever tile swapping, but I’m pretty sure there must be a way. Even if there is, it’s part of the fun of the game trying to work out how to break it! I certainly had a lot of fun causing infinite loops and then finding ways to change the rules to prevent them.

My top score so far is a pathetic 6. If you can best that I’d love to hear how!

http://davidrzepa.com/games/runprogram/

September 24, 2011 1

One day game – ‘Cry’

By in Games, One day games

Last night I had the idea that it would be nice to try and make a game in a day. Once again I asked my girlfriend for a verb to inspire a game and she came up with ‘cry’. Oh dear! Anyway rules are rules so I gave it a go. It kind of turned out as more of a toy than a game, but I don’t think that’s a bad thing. You can play it HERE and here’s a video:

I’d love to say that there is a deep meaning to all this, but really ‘cry’ just led to ‘tears’ which led to water drops falling in a desert with cactuses. Ah well was fun making it, and the hope is I’ll try to make a new ‘One day game’ every week or so.