Quick Summer 2015 Game Jam Postmortem

Category : Coding, Games, Reflections · No Comments · by Jul 24th, 2015

Screen Shot 2015-07-22 at 11.01.54 PM

Though UA GameDev Club’s summer jam was only 30 hours, I came out of the experience full of new insights.

What worked well:

  • The brainstorming process – I tried some free association at the very beginning and was organically led to an idea that’s both unique, technologically feasible, and has a lot of potential for quick polish. It was the most painless brainstorming session I ever had, and I suspect that two factors may be behind it: working solo, and keeping the most difficult constraints as the first ones I consider. Regarding the latter, I think recognizing the uniquely abundant affordances of using real-portraits early on was a big win.
  • Solutions bred from time constraints – the huge time constraint prompted me to make decisions that ironically benefitted the game itself. The game was originally intended to contain endless-levels, with each level a new room with new portraits. The lack of time to make animations and adjust difficulty forced me to constrain the entire game into one room with fading portraits. Narrative-wise it seems to make less sense, but I near the end of the project I knew instinctively that this approach would be better. I learnt that the logic of the game world is in fact as malleable as its graphics and sounds.
  • New tech requirements made the Jam a learning experience – Over the past two GJs I have been gradually inching out of the familiar territory of 2D games into 3D, but each time I made sure I only bite off as much as I can chew.
    The feeling of learning a lot of new skills AND finishing a nicely-designed concept is one of the most positive out there.
  • Game immersion – Perhaps by luck, I stumbled upon an idea that affords a lot of immersion. I think the idea of using memory and instilling panic as an integral part of the gameplay had somehow erased the boundary between the player and the avatar. The identity of the avatar as a powerless human character also helped covering up the fourth wall.
  • Built-in breaks – the knife-removal part of the game took longer than it should to implement, but I am happy with the break in tension and realism that it affords in the end. I was originally worried that the player would take too long of a break or find the task boring, but I think to a certain extent the human psyche is built in to continue the game at the optimal level of interest/arousal. To say simply – players make subtle attempts to stay in the flow state.

What went wrong:

  • Not really a team effort – The game was originally going to be an effort of a team of two. However, I think I was a bit intimidating initially in my ambition to create a really polished game and in my obsession over details that later on seemed relatively minor, especially since my potential teammate was much less experienced in game jams. The teammate did not return the second day, despite promising twice that he would contact me.
    I think during the jam I was struggling between knowing that I would likely construct a higher-quality game on my own and the sense that I should pick up less-experienced developers to learn about both social skills and team-management. I initially wanted to work solo but wavered during the team-forming phase. I think in later jams, I should commit to either solo or team options right away and stick to it till the end.
  • I didn’t compose the music – I think it’s better idea to not even consider composing for a GJ entry.
  • Didn’t finish the introduction and the ending – thinking back to the GJ, I don’t actually recognize any point when I could have done more to mitigate this problem without hurting the game in some other way.
  • Players didn’t have much motivation to stay – from the intro, the players know that there will be four levels and that the levels will generally be the same. For this reason, several players decided that they don’t need to see what’s beyond the first. I think that the issue lies in the game progression rather than the introduction though, and that I can probably add later hooks to keep the player engaged.

Other thoughts:

  • Negative thoughts during GJ – while I felt extremely good upon completion of the GJ, during the day of the competition my thoughts often lapsed into pessimism – “perhaps I should have picked a different idea after all”, “at this pace I will never finish”, “shouldn’t have slept for so long”.
    I began to realize that pessimism can occur in perhaps all but the most magnificent game projects, and that it’s a significant cost of working solo.
  • Don’t underestimate other players’ entries – being an extremely competitive person, I had thought that the game will likely be the best entry from the Jam. But looking at the final entries, I don’t think that this is actually the case, and was a bit ashamed for putting so much pride into the game.
    But then again, perhaps this is required to combat the pessimism outlined above.
    After all, Orson Scott Card once said something to the effect that “as you write, you should think of your writing as simultaneously the worst thing and the best thing ever written.”

In the next week or so, I will take a day to polish the game and add the features that didn’t make it on time. Stay tuned for the release!

Disabling Youtube Front Page Recommendations

Category : Coding · No Comments · by Jul 2nd, 2015

Youtube’s front page recommendations have always been a distraction for me. Due to reasons I can only interpret as political, the Chrome store has no extension to disable front page recommendations on Youtube. Thus I wrote a quick and dirty script to remove the recommendations.

Note that since Youtube uses a JS framework that prevents me from disabling the recommendations once and for all, I had to settle for the solution where the recommendations are cleared every half a second. The cost this incurs in the browser should be negligible. Please let me know if you find a better way!

The script was tested on the Tampermonkey extension in chrome. Install the script here.

Let me know if you run into any issues!

Unity3D General Tricks and Gotchas

Category : Coding, Games · No Comments · by Jun 13th, 2015

This is a continuation of Unity 2D Tips and Tricks, some of which are adaptable to 3D as well.

Tricks:

1. Translate or Rotate relative to world space
Unity3D’s API doesn’t advertise the optional parameters Translate and Rotate functions as much as their importance merits. By default, translations and rotations are conducted in the local transform space. This is usually convenient, but can be annoying when parent/children relationships are used for their convenience in referencing each other. The optional RelativeTo parameter in Translate and Rotate takes either Space.World or Space.Self, saving us from nasty workarounds.

2. Choosing random enums
Stolen from the Unity Answers thread, a shortcut function to pick a random enum is not provided by Unity3D, but is immensely helpful for fighting technical debt while rapid prototyping.

3. Use a Tweening Engine
Tweening refers to the action of exercising fine-tuned control over the transition of variables, often done through existing mathematical functions. See an example here (automatic-audio warning).

In the context of a game, it is a invaluable time-saving tool for two reasons. Firstly, tweening adds a great amount of polish to a game in very little time; Secondly, tweening engines usually comes with timeline functionalities that dramatically simplify potentially annoying tasks.

For example, consider simulating a ball that bounces once, then stops, fades, and gets destroyed one second after fading. Using Update, we must hand-write the sine function to approximate the trajectory each frame, keeping track of the amplitude and the phase of the function. We must keep variables that track time since bouncing started, whether the ball has finished bouncing, the alpha value of the ball, and amount of time elapsed since the fading has finished. The result is ~20 lines of ugly code that is inflexible to change.

Using something like DOTWeen, we can simply do:

Sequence mySequence = DOTween.Sequence();
mySequence.Append(transform.DOMoveY(100, 0), timeToMove / 2f).SetEase(Ease.InSine);
mySequence.Append(transform.DOMoveY(0, 100), timeToMove / 2f).SetEase(Ease.OutSine);
mySequence.AppendInterval(1);
mySequence.Append(DOTween.ToAlpha(()=> renderer.color, x=> renderer.color = x, 0, 1);
mySequence.AppendCallback(Destroy);

 

Note that the alpha-tweaking line has some fancy syntax for referring to getters and setters, it will be well worth your time to learn this notation, if only for giving you more power in using the tweening engine.
Note that using a tweening engine, the code is much shorter and more readable, and it’s easier to tweak for different types of effects.

Gotchas:
1. Rounding
Unity’s Math.Round function has an odd behavior, from the API:

If the number ends in .5 so it is halfway between two integers, one of which is even and the other odd, the even number is returned.

Here is a more minimalistic round function that behaves according to expectation.

public static int Round(float value){
	return Mathf.FloorToInt(value + .5f);
}

 

2. Photoshop Color Management
Unity’s texture import feature does not account for color profile settings in photoshop, as seen here.

The difference looks something like this:
Screen Shot 2015-06-13 at 1.13.29 PM

This is a small detail that could cause massive headaches in reworking textures if not properly dealt with.
To prevent it, select “Don’t color manage this file” on all graphic assets intended for import through Unity.

3. Corrupt Prefabs via Git
As late as Unity 4.6, saving a prefab without saving the scene the prefab is in transmits a corrupt version of the prefab to the remote git server. This is one more reason to attend to the good practice of always saving the scene before a git push.

4. Viewport Space, Screen Space, and World Space
Unity’s Camera class provides a wide variety of useful functions to convert between dimension measurements on the screen, in the view port, and in the game’s world. Distinguish between these carefully:

      The Screen space provides the dimension of the game in pixels. The bottom left of the camera is (0, 0), the top right is (Camera.pixelWidth, Camera.pixelHeight), respectively the width and the height of the camera in pixels. The Z value is the distance of a particular point in the world from camera.

The Viewport space is normalized. The bottom-left of the camera is (0, 0), and the top right is (1, 1). The Z value is the distance of a particular point in the world from camera. This is useful for positioning GUI elements.

The World space is the global positioning space that Transform components inhabit.

Note that when converting between any two spaces, we are not confined within the screen or the port. It’s perfectly valid to ask the Camera to convert from (2, 2, 0) in Viewport space to world space, in this case, we will obtain a point in the world that is about one camera outside of the current camera.

When working within 2D, it’s tempting to use the dimensions of the camera to determine the positioning of GUI elements. I find viewport space to be more reliable, since it’s immutable to both camera size changes and game screen resize.

5. OnDestroy in Child Transform
OnDestroy is a convenient callback, but beware that when a child is destroyed due to it’s parent being destroyed, the OnDestroy function on the child is not called.

6. Proper way of checking whether an object has been destroyed
Due to Unity’s gameObject implementation, checking whether an object has been destroyed in not very obvious. The correct way to do so is:

if(target == null || target.Equals(null)){
	//Assume that target has been destroyed.
}

This is a handful of code to type for each destruction check, so consider writing a static function under some utility class to handle the check instead.

7. Unity Canvas Crossfade
The new canvas GUI system in Unity seems very powerful, but UI.Graphic.CrossFade and UI.Graphic.CrossFadeAlpha are broken in the sense that both will not work if the color of the Graphic element was change right before them.
The solution turned out to again be Tweens. Example code that I used:

menu.color = new Color(1f, 1f, 1f, 0f);
Color c = new Color(1f, 1f, 1f, 0.7f);
menu.DOColor(c, 3f);

This code shifts the menu’s color from completely transparent to a transparent white in 3 seconds.

Unity 2D Tips and Tricks

Category : Coding, Design, Games, Productivity · (1) Comment · by May 28th, 2015

While the 2D features in Unity3D gets a lot less love than the rest of the engine, Unity3D is still a very powerful tool for rapid prototyping in 2D given some customization. Since the 2D features leverage design decision catered toward 3D, there are occasional gotchas in 2D as well to be aware of. Here I detail some of the tricks and gotchas I noticed while working with 2D in Unity.

In general, it is a VERY GOOD IDEA to extend the given MonoBehavior class to create shortcuts for verbose but necessary instructions. The shortcuts can be implemented by way of C# properties. This reduces clutter in code and leads to less bugs. In fact, all but one of the “tricks” uses this to simplify 2D programming.

Tricks:
1. Barring very special cases, most of your objects are going to have the SpriteRenderer component. When extending MonoBehavior, you can implement a shortcut to access spriteRenderer:

private SpriteRenderer _spriteRenderer;
public SpriteRenderer spriteRenderer{
	get{
		if(_spriteRenderer == null){
			_spriteRenderer = GetComponent();
		}
		return _spriteRenderer;
	}
}

The _spriteRenderer in this code caches the spriteRenderer to skip extraneous costly GetComponent calls.
Now, monoExtendedObj.GetComponent() can essentially be replaced with monoExtendedObj.spriteRenderer.

2. Angle manipulation in 2D is usually limited to rotation on the Z axis. However, to specify Z rotation you must go through Quaternions, which are necessary for 3D rotations. We can shove the messy quaternion operations under the rug by defining a custom “angle” property:

public float angle {
	set {
		Quaternion rotation = Quaternion.identity;
		rotation.eulerAngles = new Vector3(0, 0, value);
		transform.rotation = rotation;
	}
	get {
		return transform.rotation.eulerAngles.z;
	}
}

Note that when getting a value from this property, you will always obtain a value between 0f and 360f. If this is undesirable, consider defining a private variable that stores the non-moded angle value.

3. Alpha (opaqueness) values require dealing with colors property of the spriteRenderer – an extremely verbose operation even with the existing spriteRenderer shortcut. This property lets you set transparency of the spriteRenderer easily

public float alpha {
	set {
		if(spriteRenderer != null){
			Color _color = spriteRenderer.color;
			spriteRenderer.color = new Color(_color.r, _color.g, _color.b, value);
		}
	}
	get {
		if(spriteRenderer != null){
			return spriteRenderer.color.a;
		}
		else return 0;
	}
}

An alpha value of 1 or more is fully opaque; 0 or less is fully transparent. The values are not clamped between getting and setting so that the alpha may double as a transparency counter/timer. However you might want to use a Tweener to achieve timing effects more gracefully.

Tips:
1. Most graphic bugs from your 2D game will come from drawing order or faulty z-values. Unity3D’s ordering scheme for 2D sprites is versatile but also confusing. The determining factors for sprite ordering are (from highest to lowest priority):
-Sorting Layers (Bottom ones in the Unity UI are drawn on top)
-Order in Layer (Higher orders are drawn on top, negative values are possible)
-Z value (Closer in camera line-of-sight (LoS) drawn on top)

By default, the camera is at a height of 10 with LoS pointing downward. This implies that without changing the camera, higher Z values are drawn on top. HOWEVER, the camera also has a near-clipping plane of 0.3, meaning that it will not see anything closer than 0.3 units away from the plane perpendicular to the camera LoS (using default values, any Z-value > 9.7).

Finally, note that Order in Layer is a signed short ranging from -32,768 to 32,767. Attempts to utilize numbers outside of this range will likely mess up your drawing order.

There are several takeaways from this. The first is that you should be careful with modifying default camera values unless you are certain about how camera works in 2D. The next is that while working with dynamic Order in Layer and/or Z values are convenient, you will be working with their respective constraints. In general, Z values are better for handling cases where many more layer values than 64,000 are needed (this does occasionally happen), but can cause sprite to disappear if you are not careful. Z value is also a float, so keep rounding errors in mind.

2. Unity3D’s particle and trail renderers do not have their “sorting layer” field exposed, and that’s terrible because suddenly you cannot control the drawing order of your particles and trails.
To fix this, write a custom component that has the below code and attach to your particle or trail renderer:

void Start () {
        //Change Foreground to the layer you want it to display a particle
        //system on, otherwise particles will not show up.
        GetComponent().GetComponent().sortingLayerName = "YOUR_LAYER_NAME";
}

Note that this will set your object’s drawing layer to a static layer called “YOUR_LAYER_NAME”. If this is not your wish, or you prefer to select the drawing layer in the Unity3D UI, check here to obtain a list of drawing layers and work from there.

3. As these reddit users have found, Unity3D’s 2D collision detection system will make your life very tough if you do not use physics. This is problematic for a lot of simple 2d games where physics would either be a overkill or make debugging difficult.

I have found that the 3D collision detection system has much less stringent requirements. You must still have at least one rigidbody per collision detection, but if you tightly control the z values of your objects (usually by clamping it to 0), you can get around a lot of weird issues that arises in 2D collision detection without physics.

Note that doing both this and ordering with Z value can get hairy fast. Avoid one or the other.

4. Often it is useful to know the dimensions of the sprite either at import time or after stretching, the variables below have very similar names, but only some will be correct:

SpriteRenderer.sprite.rect will specify the size of the sprite in pixels.
SpriteRenderer.sprite.bounds.size will provide the rectangle bounding box of your sprite before scaling in game units. The size of this bound is usually SpriteRenderer.sprite.rect divided by it’s “pixel per unit” under the sprite import settings.
SpriteRenderer.bounds.size will provide a rectangle bounding box of your (sprite)render as it appear in the game, which means after stretching SpriteRenderer.sprite.bounds.size through transforms.

All .size can be replaced by .extents to obtain a box with each dimension halved, this is a useful shortcut when only the size of half the bound box is required.

These are all I have regarding 2D, for now! I’m planning on starting a general Unity3D tips and tricks post soon, and most of that post will apply to 2D as well, so stay tuned!

CS425- Virtual OSPF Router Postmortem

Category : Coding, Design, Reflections · No Comments · by May 21st, 2014
CS425- Virtual OSPF Router Postmortem

I have redeemed myself from the disgrace that is Networking homework! Through approaching the program in a systematic manner, I…

R.I.P.- Networking Program 1

Category : Coding, Reflections · No Comments · by Mar 13th, 2014
R.I.P.- Networking Program 1

Image Courtesy of UOTTAWA   My first mission for Computer Networking is the implementation of the Sliding Window Protocol (SWP)…