Archives

All posts for the month February, 2013

This year I decided to do something interesting for Valentine’s day. Rather than battling crowds at a florist, I figured I’d be much better off going with flowers of the digital variety, and I’m not talking shoddy e-cards.

I wanted to create an interactive experience in quite a short time – illustratively, when telling the idea to a friend his response was “you know valentines is tomorrow right?”, so Unity3D was an obvious choice. I had a quick look on the Asset Store during my lunch break and identified some decent free and affordable models. I even found a pre-made environment I liked, which would save me a lot of time.

This paragraph is a placeholder: I’ll enhance this post with details of the development process and assets used when it isn’t 2:30 a.m. and I haven’t just spent 9 hours at work followed by 6 hours of coding.

For now, you can try out the final result. You too could be saying things like:

  • “Where there’s smoke, there’s mushrooms!”
  • “Yeeeeaaah, your rock is on fire” (to the tune of Sex on Fire by Kings of Leon)
  • “Physics is mah bitch.”

valentine-game-preview

Play: Happy Valentine’s Day Ally!

In a previous post (Custom Editors in Unity – C# Example), I demonstrated the use of properties and custom editors to ensure that scripts always receive valid values. Recent changes in Unity have rendered this approach ineffective in Unity 3.5, so I present here an updated approach that is almost as good. Thanks to Stefan for pointing out that this had stopped working.

As with the previous approach, this is based on the Unity Script Reference – info on making a custom editor but I will use C# instead of JavaScript. I will assume you’ve read the previous post, so check that out if you get lost.

The script for which a custom editor will be written is very similar to the script in the previous example, but with one important change:

// MyScript.cs
using UnityEngine;

public class MyScript : MonoBehaviour {

	[SerializeField]
	private int myValue;

	// property is not used by custom editor,
	// but is used to ensure valid values from other scripts
	public int MyValue {
		get { return myValue; }
		set {
			// MyValue should be between 1 and 10
			myValue = Mathf.Clamp(MyValue, 1, 10);
		}
	}

	void Update () {
		// do something with MyValue
	}
}

Note the addition of [SerializeField] on the private field. This makes the value of the private field available for the more advanced custom editor that will be used.

// MyScriptEditor.cs
using UnityEditor;
using UnityEngine;
using System.Collections;

[CustomEditor(typeof(MyScript))]
[CanEditMultipleObjects]
public class MyScriptEditor : Editor {

	SerializedProperty valueProperty;

	void OnEnable() {
		// Setup serialized property
		valueProperty = serializedObject.FindProperty("myValue");
	}

	public override void OnInspectorGUI() {
		// Update the serializedProperty
		// always do this at the start of OnInspectorGUI
		serializedObject.Update();
		EditorGUILayout.IntSlider(valueProperty, 1, 10, new GUIContent("My Value"));
		serializedObject.ApplyModifiedProperties();
	}

}

There are a few differences here from the previous editor script. First is the [CanEditMultipleObjects] annotation. This allows this editor to be used to modify the values of multiple selected objects at the same time.

The next addition is a SerializedProperty that will hold a reference to the value that we’re modifying. The reference is set up in OnEnable(), by looking up the property by name (in this case the name of the private field with the [SerializeField] annotation).

With the property reference set up, the property is then used in OnInspectorGUI to be set by a slider. Note that a different method is used here than in the previous example, a method which takes a SerializedProperty argument. Check out the script reference for methods with SerializedProperty arguments that can be used, for example they are found near the bottom of the page on the reference page on EditorGUILayout.intSlider.

Finally, note that since we are now referring to a serialized object, we need to ensure that it is properly synchronized, so we call Update() before making changes to the properties, and ApplyModifiedProperties() when the changes are made.

And that’s the best we can do without getting overly complicated. Strictly speaking it is still possible for an invalid value to be set in the field by deserializing a serialized object that has an invalid value, which could happen if we have an object that hasn’t been updated since we changed the valid range. Things start to get a bit complicated trying to eliminate this little validation gap so I’ll leave it un-filled, but I did suggest an idea of how to approach it in a comment on my previous example.

Note: I will be switching to Unity 4 tomorrow, so I’ll likely make another example shortly for that. I’ll keep my 3.5 install around so feel free to ask any questions and I’ll do my best to help out.

Happy coding 🙂