Introduction

When developing an application, a website or a video game, some architectures and patterns to facilitate the separation of layers as UI, controllers or data access are used.

For example, we have the MVC pattern (Model – View – Controller) well-known by Web developers (but not only), the MVVM pattern (Model – View – ViewModel) frequently used by .NET developers using XAML. But how to do that with Unity?

Implementation in Unity

When developing with Unity, we must also keep this approach in mind constantly. Here is an example of bad practice that mixes UI and game logic.

Wrong design

using UnityEngine;
using UnityEngine.UI;

namespace UnityBadSample
{
	public class BadBehavior : MonoBehaviour
	{
		public Text CurrentTime;
		private float _elapsedTime;

		public void Start()
		{
			_elapsedTime = 0;
		}

		public void Update()
		{
			_elapsedTime += Time.deltaTime;

			// Update UI
			CurrentTime.text = _elapsedTime.ToString("N0");
		}
	}
}

In this example, our script updates the time spent in a Text control (UI 4.6) placed on our scene. It’s something very classic but  some problems may occur:

  • When changing the display type of CurrentTime, we must change all the scripts using it.
  • When deleting the Text control in the scene, our scripts stop working.
  • When changing the display via another script, it would be necessary to maintain multiple connections to the control and if you change it, it’s many connections to bind.

So, don’t do it like this !

Good design

using UnityEngine;

namespace UnityGoodSample
{
	public class GoodBehavior : MonoBehaviour
	{
		private float _elapsedTime;

		private TimerView _timerView;

		public void Start()
		{
			_elapsedTime = 0;
		}

		public void Update()
		{
			_elapsedTime += Time.deltaTime;

			// Update UI
			_timerView.UpdateTime(_elapsedTime);
		}
	}
}

No reference to any part of the UI is present in this class, only one instance to a new TimerView class that will manage the display.

using UnityEngine;
using UnityEngine.UI;

namespace UnityGoodSample.Views
{
	public class TimerView : MonoBehaviour
	{
		public Text CurrentTime;

		public void UpdateTime(float time)
		{
			if (CurrentTime != null)
				CurrentTime.text = time.ToString("N0");
		}
	}
}

A class to manage the display of the CurrentTime and full of advantages:

  • When changing the display type of CurrentTime that only change a single script.
  • When deleting the Text control in the scene, our scripts continue to work.
  • When changing the display via another script, we just need to reference the TimerView script and call the UpdateTime() method.

good_behavior

Conclusion

Like most other types of developments (Web, application, …) it is important to know how to separate the code to facilitate maintainability of your video game.