Software engineering
Some people suspect that if they know too much about a subject, they won't be able to enjoy it anymore. Let's call it the Critic's Curse: because they have analysed so much, they will find fault in everything and enjoy nothing.
Of course, there are the people that argue that this also applies to game design, as outlined by Josh Foreman in a blog post over at Gamasutra:
I’ve been interested by a pattern that I’ve noticed on Gamasutra and a few other game design related sites. Almost every time an article or blog is posted that gets into the psychology of gaming and game design there will be a comment or two along the lines of:
“You can’t turn art into a system of numbers and metrics! You are killing the FUN in games when you analyze them like this! Don’t deconstruct the magic that makes games what they are!”
He argues that this might be partially right, but more importantly that the medium of games is currently just in its infancy (or adolescence at best). It is trying to catch up to other media that have a long been established:
We are still working too hard at mimicking other mediums like film, but at the same time starting to pull away and define our own personality. This is a time for introspection.
We’ve been on the playground for a long time now. We’ve outgrown out our magical imagination world, and I think it’s time to leave Peter Pan behind and grow up. But that doesn’t mean we have to ignore Lewis’ warnings.
GUIs are not exactly easy to program in Unity 3D, since there is only one method available (OnGUI()) that obviously has to take up everything.
This becomes a problem as soon you try to create different menu screens that have to be switched out. One way to do it would probably be to use different scenes (which would be cumbersome); another way to use a switch, which would be just as cumbersome.
My way of doing it is using delegates, which allows to keep each screen encapsulated in a distinct method, while still retaining the same scene all the time.
using UnityEngine; using System.Collections; using System; //Necessary to access Action /// <summary> /// An example for using delegates to show different menu screens. /// </summary> public class DelegateGUI : MonoBehaviour { #region Setup /// <summary> /// The delegate that is going to be used. /// </summary> private Action OnGUIMethod; /// <summary> /// The standard GUI method, as inherited by MonoBehaviour. /// </summary> private void OnGUI () { if (OnGUIMethod != null) { OnGUIMethod(); } } /// <summary> /// Define what screen to show first. /// </summary> private void Start () { OnGUIMethod = Screen1; } #endregion #region Screens /// <summary> /// A very simple function that will theoretically show two buttons, /// which in turn show the other screens.
Since I'm currently cleaning up my code to hand it in with my project, I figured I could write some of the stuff down I learned during my work on our game.
All of it applies, of course, to C#, and was used in Unity 3D.
Checking for a type
Using the is keyword, you can easily check whether a certain object is of a desired type. Also, you should be aware of the as keyword, that allows you to cast an object as something else (given that this is possible).
if (obj is ISource) { ISource s = obj as ISource; if (!s.isEndpoint) { Connect (s); } }
Modelling Behaviour Over Multiple Frames Without Update()
Sometimes, you need to model some behaviour over several frames (like fading stuff in or out), but doing it in Update() or FixedUpdate() would require unwieldy if constructions.
So ... coroutines to the rescue! Using WaitForFixedUpdate(), you can model a behaviour over several frames without using FixedUpdate(), and quits as soon as it is done.
float i; private void SomeMethod() { // do some stuff here i = 1f; StartCoroutine(FadeOut()); } private IEnumerator FadeOut() { while (i > 0f) { yield return new WaitForFixedUpdate(); i -= 0.1f; } }
Delegates – The Easier Way
I wrote about delegates before, explaining how they could be used.
Beautiful procedural jellyfish by Marcin Ignac, found via The Science of Creativity:
More about the project over at Marcin's project website Cindermedusae.
Another script that is the result of the ProXedural project at the ZHdK. It produces a somewhat randomly generated level of the size of a collider that is placed over a terrain in Unity 3D.
By using a somewhat mixed approach of completely random raycast placing and placing objects using an array, the script can ensure that the different kinds of objects are distributed all over the terrain.
Again, the script may be oddly specific at times, so you might have to adapt it to your needs if you intend to reuse it.
using UnityEngine; using System.Collections; /// <summary> /// Right now, this class does not do a whole lot. The principle, however, /// could be applied and extended for other purposes. The approach ensures /// that the objects are distributed all over the place. /// </summary> public class RandomPopuliser : MonoBehaviour { public GameObject[] stuffToPlace; private int[,] grid = new int[6, 6]; public int maxNumberOfObjectsToPlace = 30; // Use this for initialization void Start () { for (int i = 0; i < grid.GetLength (0); i++) { for (int j = 0; j < grid.GetLength (1); j++) { // Define some data we will need later on. float cellWidth = this.collider.bounds.size.x / grid.GetLength (1); float cellDepth = this.collider.bounds.size.z / grid.GetLength (0); float minX = cellWidth * j; float maxX = cellWidth * j + cellWidth; float minZ = cellDepth * i; float maxZ = cellDepth * i + cellDepth; // Let's define a counter that looks on which placeable we // are working on.
A simple walker script for Unity 3D in C# that tries to avoid obstacles. It has been used in the ProXedural project at art school, and it made the cows walk towards one of the players. To be honest, it does not really deserve the I in AI. But then again, no one expects cows to be very clever.
Maybe someone can use it as a base to produce something better (oh well, who am I kidding, this has already been done).
using UnityEngine; using System.Collections; /// <summary> /// A simple AI walking script. Follows a target. /// </summary> public class AIWalker : MonoBehaviour { internal Vector3 target; private CharacterController controller; private int counter = 0; private Vector3 avoidNormal; private Vector3 semiStaticDirection; private RaycastHit hit; /// <summary> /// The delegate that will execute the current state of the FSM. /// </summary> private delegate void FState (); private FState stateMethod; /// <summary> /// Returns the vector of the current forward motion of the controller. /// </summary> /// <value> /// Returns a vector. /// </value> private Vector3 forward { get { return transform.TransformDirection (Vector3.forward); } } /// <summary> /// Helper function to get a right or left vector. /// </summary> /// <value> /// Returns left of right (Vector3). /// </value> private Vector3 randomLeftOrRight { get { return UnityEngine.Random.value > 0.5 ? Vector3.right : Vector3.left; } } /// <summary> /// Calculates the direction to the target object.
Finite State Machines are quite a convenient design pattern in Game Design, as they allow for quite some flexibility when programming AI behaviour.
Unfortunately, our first encounter with FSMs was poorly explained, and badly executed in ActionScript 3 using a bunch of switch statements – disregarding the fact that there would have been clearly more elegant solutions.
So, let's do the same for Unity 3D in C#, using delegates.
using UnityEngine; using System.Collections; public class FiniteStateMachine : Monobehaviour { // Create the delegate private delegate void FState (); // Create a holder for the delegate private FState stateMethod; #region UnityEngine methods /// <summary> /// Sets up the controller and puts the object into the new mode. /// </summary> void Start () { stateMethod = new FState (EnterStateA); } /// <summary> /// Executes in every frame once. Only calls the current state method. /// </summary> void FixedUpdate () { stateMethod (); } #endregion #region State A /// <summary> /// Sets up State A. /// </summary> private void EnterStateA () { // Things to prepare State A come here. stateMethod = new FState (StateA); // The next line will ensure that the first run of State A // will occur in the same frame.
... is, apparently, something Tale of Tales are rather good at. Robert Yang has a neat timeline of the current events. And it is not the first time they make people angry.
Of course, you can debate the value of their provocations, you can debate their contribution to game culture –
Tale of Tales is important and interesting... but also kind of not. Their conception of video games seems really narrow, perhaps out of necessity in order to target it effectively in their crazy dogmatic manifestos.
– the thing is: there is a discussion about what games are and what not. People might consider them to be wrong. But people might also consider Blizzard to be wrong, inasmuch as they pretty much only polish up the games they did ten years ago.1
No matter how aggravating/boring this argument may seem: It is important that it is discussed. Every game designer that plays a Tale of Tales game will either see how games could be made as well – or she or he will realise how games are not to be designed. Either way: everybody learns.
Here’s to the crazy ones, so to speak.
The misfits.
The rebels.
The troublemakers.
The round pegs in the square holes.
The ones who see things differently.
They’re not fond of rules.
... indeed.
-
Just an example, I am not trying to flame anyone here. Not much, anyway. ↩


