I first got a position at a small firm in IT around the advent of the W2K issue. The first day someone handed me a specification for the application being worked on by the senior developers; An A4 book thicker than a bible sat on a desk having been worked on by a team of over twenty people in the year preceding it solely concerned with taking the two digit component of a date field to four. They had in that year been unable to fully prototype the design goal in this "bible" with thirty people.
Thankfully the world has caught up a lot in the world of prototyping and sadly devolved a little in the world of specifications. Tools such as unity, coupled with something like probuilder and other free or reasonably cheap addons can make designing a prototype of your game a doddle!
A Valve fanboy of my time the community would often put up prototypes using Valve's "dev" textures for trying the feel of the sdk game map to play through. The idea of prototyping in games is not new but the idea is still the same and highly worthwhile. Unlike valve maps you'll mostly likely want custom components that don't exist in code but many features will exist for you to drop in a fairly accurate replica to play around with.
Game jams have become their own thing of late but ultimately! These little mini projects made in a seriously stressful timeline are just prototypes for games that may never see the light of day as commercial products. Games such as super hot started life as a game jam, but take note how long that took to become a commercial project. A prototype is a great start to a game but requires a lot more to make a final polished product you, as a developer, can feel comfortable selling and often require specification and scoping to really make a decent product, something i'll get to in another post.
Useful Links:
Probuilder Tools
Goblin Development at it's Finest
Unity Hints & Tips
Unity Development Hints & Tips
On occasion I’m asked what I would recommend to someone in
my position. Ironically enough it’s a question I’ve seen countless times before
and would throw my penny’s worth into the pot for fellow developers and game
designers.
Frame Timings Matter
Consider logging or monitoring the Time.deltaTime variable
as the first debug variable you want to observe. As stated in the documentation; Time.deltaTime
shows the period of time the previous frame took to process from start to end.
This variable will can highlight any obvious bottlenecks in your system as
early as possible, as well as seeing when processes "clump" up
together repeating over short bursts of poor performance. As you start to
add more objects the source of the delay is not always apparent but this variable
will at least highlight there is a problem.
Avoid OnGUI & Update Calls
Every frame Unity has to call every monobehaviour within the
scene, firing its Update routine. If you're running at the baseline of 60fps
that's every 0.017 seconds a call will be made to your class. Although this is
over simplifying the way Unity handles threading and other features every
action within these routines slows the frame time and creates a bottleneck.
Avoid it if possible using more event driven mechanics such as coroutines or
consider remaking the class to use less resource during update. Equally every
OnGUI call also fires every frame, but moreover drains frame-time using a
somewhat resource intensive system of displaying the GUI drawn in this routine.
Can you use a draw call from a GUITexture for the background? I would typically
tend to using up a draw call or two than using the OnGUI functions personally.
Use Coroutines
As mentioned in my "Coroutines
Coroutines Coroutines" Article the benefits of using coroutines are
massive and can reduce the use of Update can be avoided with them, and allows
much more control over a longer period of time. Developers from software
development backgrounds can often dismiss or miss them when transferring over
to Unity from other C# environments. Nesting Coroutines or Parallel Coroutines
used in conjunction with callback delegates can make AI and other complex
systems much simpler to build and more cost effective especially when using
this across different projects or within custom frameworks.
Waste Not Want Not
As your projects increase in quantity you'll see common
elements of code you want to use over and over. As John Warner highlighted
in his blog
If you're going to
invest the time to write code, you should be adding value to your business and
creative process as well!
Building a system will become only more valuable as you use
it more will add value to your business and make every game a progression in a
history of games development. Taking time on things like inventory or dialogue
systems that can become limited to configuration alone become massive time
savers.
Small iterative upgrades to systems can evolve as you expand
your libraries with each game leveraging the limited time you have as an indie
to work on games. Imagine an evening of setup could have 60% of your mechanics
ready to go, awaiting new assets... DAY 1! Which it can be the third or fourth
project, done right!
Customise the Editor
If you have used Unity for some time you will want to
consider starting to leverage the development IDE to build GUI for your
components and frameworks. A dialogue system, looping and deviating on
variables from gender to reputation with an NPC could be bothersome to set up
and populate for a large RPG, especially when taking multiple languages into
account. Building custom pop out panels, and visual items on screen aping the
animation window or even the sprite editor are possible within Unity given a
solid foundation in the code and can make these tasks much easier and
streamlined to complete.
Pool Objects at run time
Did you ever play the game Lemmings? Just think back for a
second; several Lemmings escape from the entrance hit the ground, and without
user interaction typically fall to their death shortly afterwards. When a
lemming "dies" the temptation may be to destroy the object or leave
it disabled where it is. At the same time your code will be spawning the new
lemmings at the entrance, incurring an overhead to create, initialise and
position the new lemming in place. Always consider ways to limit runtime
creation of objects where possible, assuming your game is not 100% generated at
runtime of course.
Testing Methodologies
Whatever level of development you intend some form of maintenance
and bug fixing is going to occur after customers start playing your game. The
difference between a smooth launch with positive reviews, and low end scores
detailing several bugs is ultimately up to the quality of your testing. Luckily
this probably is also applicable in the software development industry and
various evolving concepts for automating and managing testing exist already. Although limited a good starting point can be
found and given a quick google search of MVVM and Dependency Injection will get
you several current examples, probably in C#.
Watch Streams and / or YouTube
If you have a game there is probably going to be other games
that are similar in the market being reviewed. If you have an
"amazing" idea check if anyone tried the same thing before in a game.
This should not be used to steal ideas but to validate how small subsets of
people you’ve never met respond to a mechanic or system. See how that idea was
received by the streamer or reviewer. YouTube and Twitch provide invaluable
information that AAA companies had to pay for before these services existed.
Coroutines, Coroutines, Coroutines
Whether crafting fluid AI routines or just fading out a screen coroutines can provide a useful tool to any coder wanting to complete an action (or series of actions) across a number of frames. Coroutines are explained on the Script Reference Example quite well but wanted to highlight a few features so decided to include a demonstration below;
using UnityEngine;
using System.Collections;
public class CoroutineDemoClass : MonoBehaviour
{
public float MoveSpeed = 0.5f;
public float WaitPeriod = 0.1f;
public void Awake()
{
Debug.Log("Started Walking");
StartCoroutine(Walk());
}
public IEnumerator Walk()
{
//Always quantify a loop with a valid exit condition
//(at worst enabled status of the component)
while (this.enabled)
{
//movement actions (especially physics based movement)
//should be completed during fixed update
yield return new WaitForFixedUpdate();
//move forward
transform.Translate(transform.forward * MoveSpeed);
//wait for a period of time.
yield return new WaitForSeconds(WaitPeriod);
}
Debug.Log("Stopped. Walking... Disabled");
yield return null;
}
}
This simple MonoBehaviour moves the GameObject it is attached to X amount forward every N seconds. This example is overly simplistic but should highlight the value of using coroutines.
This coroutine was initiated by directly calling the routine meaning there is no way to stop the Walk function from outside of the routine. Here only disabling the component would stop the behaviour "walking".
All coroutines can be stopped at anytime using the StopAllCoroutines() function. However to stop an indivdual routine you need to initialise the coroutine differently.
StartCoroutine("Walk");
Changing this one line of code will have a cost associated it with it, as the string name needs to be resolved on the component you are calling. However you can now use the Stop Coroutine features to halt a single coroutine at anytime, provide it was started this way, even from outside the component itself.
GameObjectName.StopCoroutine("Walk");
Nesting Coroutines or Parallel Coroutines used in conjunction with callback delegates can make AI and other complex systems much simpler to build and more cost effective than using update when implemented correctly.
Subscribe to:
Posts (Atom)