Skip to main content

· 6 min read
Byungnam Lee

Leviathan Game Overview

The player completes his impossible missions of two assassinations and stealing a vault of information in possession of his company's rival and foe. In revenge for the attempt on his life by his own squad member, he took out his might power even unknown to himself on the CEO's life.

High Concept

Unique Selling Points

The use of Azure Kinect makes the game play a fun without much hassle of donning a HMU with hand controllers. The very simple game mechanism and storyline will allow a game novice even easier immersion into the gameplay.

Platform Minimum Requriements

Windows with Nvidia 1070 with 8 RAM and USB3.

Competence Titles

Leviathan The Saga of a Fixer

Synopsis

I really enjoyed the movie Mechanic: Resurrection with Jason Stathm starring as Bishop(?). The game's storyline happens to reflect the mission statement without my meaning to. I must admit that I watched the movie about 2 months after I have developed a basic storyboard. So forgive me if you want to argue otherwise over this point. The player in this case was sick of his several failures to make it to a national Archery squad and decides to work under a contract. That's how he ends up on a training gallery in the world of SWAT boot-camp.

Game Development Objectives

The following goals in the dev work have been set for myself;

스토리텔링 룰

• Setting and introduction: Before you start describing the game mechanics, put the reader inside the game. Describe the world, the player character, their backstory, their motivations, and what the main problem is that the player needs to struggle with. Make the reader of the GDD interested in the setting of the game and want to keep reading, to see how they will be able to play the game and tackle all the quests the player will face in the game.

• Gameplay sections: These are sections that break the game into several systems and subsystems linked to each other. Some examples can be Inventory, Quests, Crafting, Battle, Movement, Shops, and so on. You will want to be super specific about every aspect of how those systems work because—remember—this document will be used by the team to craft the code and assets of your game. All the analysis we did in the previous sections of the chapter will be part of the GDD and will be further explained and analyzed.

• Content sections: You will also want to create content sections, such as the ones we previously designed. These can be—but are not limited to—Characters, Story, World, Levels, Aesthetics, Art Assets, Sound and Music Assets, Economics, and Input.

• Share your idea: Before immortalizing your ideas in the GDD and making everyone start crafting them, discuss the different GDD sections before marking them as finished. Discuss with your team, people on the internet, friends—anyone and everyone can give you valuable feedback about your idea. I'm pretty sure you are thinking that your idea will be stolen by some random person on the internet who will release the same game before you—and that can happen—but I'm not saying share the whole GDD, just some details about certain implementations you are not sure about.

• Keep control: Everyone in the team is a game designer—some more than others. Everyone will have ideas and things they will do differently. Listen to them—doing so will be useful, but remember you are in charge and you will have the final say. You need to be open, but set some limits and don't deviate from your original idea and concept. Prevent the famous feature creep, which consists on lots and lots of game systems unnecessarily, and know when enough is enough, especially considering the limited amount of resources we will have when beginning to create games. Again, not an easy task—you will learn this the hard way, believe me, but remember this when that happens (I told you!).

• The game will change: I already said that, but I like to stress this as much as I can. The game will change a lot due to many reasons you will find in the process of creating it. You may find that X mechanic is not that fun, you could have created a better way of handling Y system, or maybe test sessions with players prove that Z level needs to be completely redesigned. Be open to change and pivot your game idea when needed. If you do this the right way, your game won't be as you originally imagined but will be a better version of it.

• Graphics: Use graphics, diagrams, charts, and so on. Try to prevent huge text walls. Remember that a picture is worth a thousand words. You are communicating, and nobody wants to spend valuable minutes trying to understand what you want to say. Improve your visual communication skills, and you will have a focused team.

• Paper prototypes: You can test some ideas in your head on paper before putting them in the GDD. Even if your game is a frenetic "beat 'em up," you can have little paper characters moving around a table, seeing how they can attack the player, and which movement pattern they will have. Do some math to look at how to perfect timing, damage, health values, and so on.

• Regular prototypes: While your game is being developed, the GDD will constantly change based on player feedback. You must test your game, even if it's not finished, and get feedback from players as early as you can. Of course, they will tell you lots of things that you already know, but they will see lots of problems you don't see because you are creating and playing your game every day. They have the advantage of playing the game for the first time, and that is a real change.

Game Rules

Game Structure

Game Scene Architecture

Bringing the stage to life

Game scene limits

Game scene boundaries

Gameplay

Creating the arrow launching system

Bringing input architecture

Physics is your friend

Game Controls

Game Camera

HUD

Orchestrator's symphony

Player

Enemies

Generating enemies dynamically

Configuring enemies

Kinect Game

Kinect setup and integration

Metagame

Character Lineup

NPC Enemies

NPC Allies

Art

Level Design

Audio

MVP (minimum viable product)

Wishlist

Testers

· 20 min read
Byungnam Lee

Preface

For detailed examples, go to Unity Project Template

Rule of Thumb

  1. Readability first (your code should be your documentation most of the time)
  2. Follow IDE's auto formatted style unless you have really good reasons not to do so. (Ctrl + K + D in Visual Studio)
  3. Learn from existing code
  4. Rely on UWP_Namespace for Kinect-realted codes

References

This coding standards is inspired by these coding standards

IDE Helper

The settings that can imported into your IDE can be found here.

I. Main Coding Standards

  1. Use Pascal casing for class and structs

    class PlayerManager;
    struct PlayerData;
  2. Use camel casing for local variable names and function parameters

    public void SomeMethod(int someParameter)
    {
    int someNumber;
    int id;
    }
  1. Use verb(base form)-object pairs for method names, by default.

    public uint GetAge()
    {
    // function implementation...
    }
  1. However, if a method simply returns a boolean state, the verb part of the name should be prefixed Is, Can, Has or Should. If the function name becomes not natural by doing so, use the 3rd-person singular form of another verb.

    public bool IsAlive(Person person);
    public bool Has(Person person);
    public bool CanAccept(Person person);
    public bool ShouldDelete(Person person);
    public bool Exists(Person person);
  2. Use pascal casing for all method names except (see below)

    public uint GetAge()
    {
    // function implementation...
    }
  3. Use camel case for any non-public method. You might need to add custom Visual Studio style rule as described here

    private uint getAge()
    {
    // function implementation...
    }
  4. Use ALL_CAPS_SEPARATED_BY_UNDERSCORE for constants

    const int SOME_CONSTANT = 1;
  5. Use static readonly if an object is a constant

    public static readonly MyConstClass MY_CONST_OBJECT = new MyConstClass();
  6. Use ALL_CAPS_SEPARATED_BY_UNDERSCORE for static readonly variables

  7. Use readonly when a variable must be assigned only once

    public class Account
    {
    private readonly string mPassword;

    public Account(string password)
    {
    mPassword = password;
    }
    }
  8. Use pascal casing for namespaces

    namespace System.Graphics
  9. prefix boolean variables with b.

    bool bFired;        // for local variable
    private bool mbFired; // for private member variable
  10. prefix boolean properties with Is, Can, Should or Has.

    public bool IsFired { get; private set; }
    public bool HasChild { get; private set; }
    public bool CanModal { get; private set; }
    public bool ShouldRedirect { get; private set; }
  1. prefix interfaces with I

    interface ISomeInterface;
  2. prefix enums with E

    public enum EDirection
    {
    North,
    South
    }
  3. prefix structs with S unless they are readonly structs

    public struct SUserID;
  4. prefix private member variables with m. Use Pascal casing for the rest of a member variable

    Public class Employee
    {
    public int DepartmentID { get; set; }
    private int mAge;
    }
  5. Methods with return values must have a name describing the value returned

    public uint GetAge();
  6. Use descriptive variable names. e.g index or employee instead of i or e unless it is a trivial index variable used for loops.

  7. Capitalize every character in acronyms only if there is no extra word after them.

    public int OrderID { get; private set; }
    public string HttpAddress { get; private set; }
  8. Prefer properties over getter setter functions

BAD:
```cs
public class Employee
{
private string mName;
public string GetName();
public string SetName(string name);
}
```

GOOD:
```cs
public class Employee
{
public string Name { get; set; }
}
```
  1. Declare local variables as close as possible to the first line where it is being used.
  1. Use precision specification for floating point values unless there is an explicit need for a double.

    float f = 0.5F;
  2. Always have a default: case for a switch statement.

    switch (number)
    {
    case 0:
    ...
    break;
    default:
    break;
    }
  1. If default: case must not happen in a switch case, always add Debug.Assert(false); or Debug.Fail();

    switch (type)
    {
    case 1:
    ...
    break;
    default:
    Debug.Fail("unknown type");
    break;
    }
  2. Names of recursive functions end with Recursive

    public void FibonacciRecursive();
  3. Order of class variables and methods must be as follows:

    a. public variables/properties
    b. internal variables/properties
    c. protected variables/properties
    d. private variables
    Exception: if a private variable is accessed by a property, it should appear right before the mapped property.
    e. constructors
    f. public methods
    g. Internal methods
    h. protected methods
    i. private methods
  4. If parameter types are general, function overloading must be avoided

Use:
```cs
public Anim GetAnimByIndex(int index);
public Anim GetAnimByName(string name);
```

Instead of:
```cs
public Anim GetAnim(int index);
public Anim GetAnim(string name);
```
  1. Each class must be in a separate source file unless it makes sense to group several smaller classes.

  2. The filename must be the same as the name of the class including upper and lower cases.

    public class PlayerAnimation {}

    PlayerAnimation.cs

  3. When a class spans across multiple files(i.e. partial classes), these files have a name that starts with the name of the class, followed by a dot and the subsection name.

    public partial class Human;

    Human.Head.cs Human.Body.cs Human.Arm.cs

  4. Use assert for any assertion you have. Assert is not recoverable. (e.g, most function will have Debug.Assert(not null parameters) )

  1. The name of a bitflag enum must be suffixed by Flags

    [Flags]
    public enum EVisibilityFlags
    {
    None = 0,
    Character = 1 << 0,
    Terrain = 1 << 1,
    Building = 1 << 2,
    }
  2. Prefer overloading over default parameters

  1. When default parameters are used, restrict them to natural immutable constants such as null, false or 0.
  1. Shadowed variables are not allowed.

    public class SomeClass
    {
    public int Count { get; set; }
    public void Func(int count)
    {
    for (int count = 0; count != 10; ++count)
    {
    // Use count
    }
    }
    }
  2. Always use containers from System.Collections.Generic over ones from System.Collections. Using a pure array is fine as well.

  3. Use real type over implicit typing(i.e, var) unless the type is unimportant. Some acceptable var usage includes IEnumerable and when the new keyword is used for anonymous type.

  4. Use static class, not singleton pattern

  5. Use async Task instead of async void. The only place where async void is allowed is for the event handler.

  1. Validate any external data at the boundary and return before passing the data into our functions. This means that we assume all data is valid after this point.

  2. Therefore, do not throw any exception from inside non-boundary methods. Also, exceptions should be handled at the boundary only.

  1. As an exception to the previous rule, exception throwing is allowed when switch-default is used to catch missing enum handling logic. Still, do not catch this exception

    switch (accountType)
    {
    case AccountType.Personal:
    return something;
    case AccountType.Business:
    return somethingElse;
    default:
    throw new NotImplementedException($"unhandled switch case: {accountType}");
    }
  2. Prefer not to allow null parameters in your function, especially from a public one.

  1. If null parameter is used, and postfix the parameter name with OrNull

    public Anim GetAnim(string nameOrNull)
    {
    }
  2. Prefer not to return null from any function, especially from a public one. However, you sometimes need to do this to avoid throwing exceptions.

  3. If null is returned from any function. Postfix the function name with OrNull.

    public string GetNameOrNull();
  4. Try not to use an object initializer. Use explicit constructor with named parameters instead. Two exceptions. a. When the object is created at one place only. (e.g, one-time DTO) b. When the object is created inside a static method of the owning class. (e.g, factory pattern)

  5. Declare the variable for an out parameter on a seprate line. Do NOT declare it int the argument list.

  6. Do not use using declaration, introduced in C# 8.0. Use using statement instead.

  7. Always specify a data type after new keyword unless you are using annoymous type inside a function.

  8. Use private init-only setter(private init), introduced in C# 9.0, wherever possible.

  9. Use file scoped namespace declarations, introduced in C# 10.0.

  10. When strong-typing a generic type, use readonly record struct, introduced in C# 10.0.

II. Code Formatting

  1. Use Visual Studio's default for tabs. If another IDE is used, use 4 spaces instead of a real tab.

  2. Always place an opening curly brace ({) in a new line

  1. Add curly braces even if there's only one line in the scope

    if (bSomething)
    {
    return;
    }
  2. Declare only one variable per line

    BAD:

    int counter = 0, index = 0;

    GOOD:

    int counter = 0;
    int index = 0;

III. Framework Specific Guidelines

A. Auto Serialization/Deserialization (e.g. System.Text.Json)

  1. Auto-serializable data must be defined as class.

  2. Auto-serializable class must not contain any library-specific attribute in it.

  3. All data in auto-serializable class must be declared/defined via public auto properties. (1-to-1 mapping between properties and member variables)

  4. If you need a read-only property in auto-serializable class, make a public method instead.

  5. Auto-serializable class must have only one public constructor. This constructor must not take any parameter.

  6. Do not directly call a auto-serialization method. (e.g. JsonSerializer.Serialize<>()). Make a wrapper method instead to limit the parameter types.

B. XAML Controls

  1. Do not name (i.e, x:name) a control unless you absolutely need it
  1. Use pascal casing with prefixed x character for the name.

    xLabelName
  2. Prefix the name with full control type

    xLabelName
    xButtonAccept

C. ASP .NET Core

  1. When using DTO(Data Transfer Object)s for a request body for a RESTful API, make each value-type property as nullable so that model validation is automatic

    [Required]
    public Guid? ID { get; set; }
  2. Validate all the requests as the first thing in any controller method. Once validation passes, all inputs are assumed to be correct. So no [required] nullable properties will be null.

  3. Unlike above, [RouteParam] will not have ?

    public bool GetAsync([RouteParam]Guid userID)

D. Service/Repo Pattern

  1. For the DTO classes and enums that are only used internally (e.g, internal microservice or DTO between service and repo), prefix it with X. This means they are transient classes and enums

    public sealed class XNode
    {
    }

    public enum EXTransactionStatus
    {
    }

Unity Project Template

This governance includes Project Structure Best Practices and C# Coding Standards for Unity.

A. Unity — Project Structure Best Practices

Employing an organized project structure is beneficial to your project and your team.

Scope: Folder Structure Folder Naming File Naming

Benefits:

Consistency — The project structure has consistency in presentation regardless of team location, spoken language, or individual programmers. Maintenance — Consistent project structure will aid readability. Readability helps new and existing programmers revisit the code base for fixes and improvements. Communication — Developers more implicitly understand each other in written and verbal communication.

B. Coding Standards

Coding standards define a programming style.

Employing organized coding standards is beneficial to your project and your team.

Scope:

Naming Conventions File Naming and Organization Formatting and Indentation Comments and Documentation Classes, Functions and Interfaces Testing

Benefits:

Code Integration Team Member Integration Maintenance Uniform Problem Solving Minimizes Communication Minimizes Performance Pitfalls

└── Unity
├── Assets
│   ├── 3rdParty
│   │   ├── [VendorName]
│   │   │   ├── readme.txt
│   │   │   └── readme.txt.meta
│   │   └── [VendorName].meta
│   ├── 3rdParty.meta
│   ├── Art
│   │   ├── AnimationClips
│   │   ├── AnimationClips.meta
│   │   ├── Animators
│   │   ├── Animators.meta
│   │   ├── Audio
│   │   │   ├── AudioClips
│   │   │   ├── AudioClips.meta
│   │   │   ├── AudioMixers
│   │   │   └── AudioMixers.meta
│   │   ├── Audio.meta
│   │   ├── Fonts
│   │   ├── Fonts.meta
│   │   ├── Materials
│   │   ├── Materials.meta
│   │   ├── Models
│   │   ├── Models.meta
│   │   ├── Shaders
│   │   ├── Shaders.meta
│   │   ├── Sprites
│   │   ├── Sprites.meta
│   │   ├── Textures
│   │   └── Textures.meta
│   ├── Art.meta
│   ├── Documentation
│   ├── Documentation.meta
│   ├── PhysicMaterials
│   ├── PhysicMaterials.meta
│   ├── Prefabs
│   │   ├── RMC
│   │   │   ├── [MyProject]
│   │   │   └── [MyProject].meta
│   │   └── RMC.meta
│   ├── Prefabs.meta
│   ├── Presets
│   ├── Presets.meta
│   ├── Resources
│   ├── Resources.meta
│   ├── Scenes
│   ├── Scenes.meta
│   ├── ScriptableObjects
│   │   ├── RMC
│   │   │   ├── [MyProject]
│   │   │   └── [MyProject].meta
│   │   └── RMC.meta
│   ├── ScriptableObjects.meta
│   ├── Scripts
│   │   ├── Editor
│   │   │   ├── Editor.asmdef
│   │   │   ├── Editor.asmdef.meta
│   │   │   ├── RMC
│   │   │   │   ├── [MyProject]
│   │   │   │   ├── [MyProject].meta
│   │   │   │   ├── Templates
│   │   │   │   │   ├── TemplateEditorMenuItems.cs
│   │   │   │   │   └── TemplateEditorMenuItems.cs.meta
│   │   │   │   └── Templates.meta
│   │   │   └── RMC.meta
│   │   ├── Editor.meta
│   │   ├── Other.meta
│   │   ├── Runtime
│   │   │   ├── RMC
│   │   │   │   ├── [MyProject]
│   │   │   │   ├── [MyProject].meta
│   │   │   │   ├── Runtime.asmdef
│   │   │   │   ├── Runtime.asmdef.meta
│   │   │   │   ├── Templates
│   │   │   │   │   ├── ITemplateInterface.cs
│   │   │   │   │   ├── ITemplateInterface.cs.meta
│   │   │   │   │   ├── TemplateClass.cs
│   │   │   │   │   ├── TemplateClass.cs.meta
│   │   │   │   │   ├── TemplateComponent.cs
│   │   │   │   │   ├── TemplateComponent.cs.meta
│   │   │   │   │   ├── TemplateScriptableObject.cs
│   │   │   │   │   └── TemplateScriptableObject.cs.meta
│   │   │   │   └── Templates.meta
│   │   │   └── RMC.meta
│   │   ├── Runtime.meta
│   │   ├── Tests
│   │   │   ├── Editor
│   │   │   │   ├── Editor.Tests.asmdef
│   │   │   │   ├── Editor.Tests.asmdef.meta
│   │   │   │   ├── RMC
│   │   │   │   │   ├── [MyProject]
│   │   │   │   │   ├── [MyProject].meta
│   │   │   │   │   ├── Templates
│   │   │   │   │   │   ├── TemplateClassEditModeTest.cs
│   │   │   │   │   │   └── TemplateClassEditModeTest.cs.meta
│   │   │   │   │   └── Templates.meta
│   │   │   │   └── RMC.meta
│   │   │   ├── Editor.meta
│   │   │   ├── Runtime
│   │   │   │   ├── RMC
│   │   │   │   │   ├── [MyProject]
│   │   │   │   │   ├── [MyProject].meta
│   │   │   │   │   ├── Templates
│   │   │   │   │   │   ├── TemplateComponentPlayModeTest.cs
│   │   │   │   │   │   └── TemplateComponentPlayModeTest.cs.meta
│   │   │   │   │   └── Templates.meta
│   │   │   │   ├── RMC.meta
│   │   │   │   ├── Runtime.Tests.asmdef
│   │   │   │   └── Runtime.Tests.asmdef.meta
│   │   │   └── Runtime.meta
│   │   └── Tests.meta
│   └── Scripts.meta
├── Packages
│   ├── manifest.json
│   └── packages-lock.json
└── ProjectSettings
├── AudioManager.asset
├── ClusterInputManager.asset
├── DynamicsManager.asset
├── EditorBuildSettings.asset
├── EditorSettings.asset
├── GraphicsSettings.asset
├── InputManager.asset
├── NavMeshAreas.asset
├── PackageManagerSettings.asset
├── Physics2DSettings.asset
├── PresetManager.asset
├── ProjectSettings.asset
├── ProjectVersion.txt
├── QualitySettings.asset
├── SceneTemplateSettings.json
├── TagManager.asset
├── TimeManager.asset
├── UnityConnectSettings.asset
├── VersionControlSettings.asset
├── VFXManager.asset
└── XRSettings.asset

47 directories, 94 files

Unity3D Coding Standards

  • Use C#-Unity-Format to manage document formatting.
  • Macros are all uppercase.
  • Naming of structures, types, enums use:
    • Lowercase.
    • Underscore to separate words.
    • _t at the end of the name to indicate it is a type.
    • [area]_[noun]_t format.
    • Prepend k4a to public types; i.e. k4a[area]_[noun]_t.
  • Enum element names additionally use:
    • The same [area]_[noun] as the beginning of each element.
    • Underscore to separate words.
    • uppercase.
  • Naming of functions use:
    • Lowercase.
    • Underscores to separate words.
    • [area]_[verb]_[noun] format.
    • k4a_ at the start of public functions; i.e. k4a_[area]_[verb]_[noun].
  • Stop / Free / Destroy functions should not return an error type. If it is not possible to handle all error cases, and there is nothing the user can do to resolve the issue, then it is acceptable to crash. If there is action the user could take (not including an application restart or PC reboot), then returning an error specific to the recovery action is acceptable.
  • Don't use default parameters in public APIs (C++/C#)

An attempt at documenting a composition of coding standards acquired from multiple game developers across the community.

Table of Contents

  1. Code Formatting
  2. Code File Layout
  3. Naming Conventions
  4. Code Documentation
  5. References

Code Formatting

  • Use spaces instead of tabs. Do not mix spaces and tabs;
  • Each indentation level should be 4 spaces wide;
  • Each brace should have its own line;
// Avoid
if(playerWasHit) {
PlaySound(playerHitSound);
Damage(player, damageAmount);
}
// Prefer
if(playerWasHit)
{
PlaySound(playerHitSound);
Damage(player, damageAmount);
}
// Bad
public float Health { get { return health; } }
// Good
public float Health
{
get
{
return health;
}
}
  • It is acceptable to use the expression body definition operator => for property getters and setters for simple, single-statement properties;
public float Health
{
get => health;
set => health = value;
}
  • Every statement after a conditional should be inside braces, even if it is a single statement;
// Bad
if(enemyInRange)
Explode();
// Good
if(enemyInRange)
{
Explode();
}
// Avoid
Debug.Log("Player " + playerId + " took a hit from " + damageSource + " for " + damageAmount + " damage.");
// Avoid
Debug.LogFormat("Player {0} took a hit from {1} for {2} damage.", playerId, damageSource, damageAmount);
// Prefer
Debug.Log($"Player {playerId} took a hit from {damageSource} for {damageAmount} damage.");
  • Switch-case code should be implemented inside braces;
switch(colorId)
{
case PlayerBodyColors.White:
{
playerBody.SetTexture(whiteTexture);
}
break;
case PlayerBodyColors.Red:
{
playerBody.SetTexture(redTexture);
}
break;
default:
{
playerBody.SetTexture(defaultTexture);
}
break;
}
  • Encode the document in UTF-8 if possible;
  • End-Of-Line character should be CRLF;

Code File Layout

  • Library usings should be the first lines of a file, followed by typedef-like usings;
  • Put every class definition inside an appropriate namespace;
  • Prefer defining only one class per file;
  • File name should be the same as the class name.
// File: AiPathfinder.cs
using System.Collections.Generic;
using UnityEngine;

using WaypointMap = Dictionary<Vector3,Waypoint>;

namespace MyGame.AiNavigation
{
public class AiPathfinder
{
...
}
}
  • Usings should be defined in the following order:

    1. System or .NET libraries
    2. Unity libraries
    3. Third-Party plugins (asset store)
    4. Your own utility libraries
    5. Project namespaces
    6. Type name aliases
  • All namespace categories should be blocked together, without separating with spaces or comments.

  • An exception to this is typedef-like usings, which should be separated from library usings with an empty line.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using ExampleCompany;
using OtherCompany.BoostedInspector;
using MyUtilityLib;
using MyUtilityLib.DebugUtilities;
using MyOtherLib.Patterns;
using ThisProject;
using ThisProject.Audio;
using ThisProject.Combat;

using EntityPrefabMap = Dictionary<EntityType,GameObject>;
  • Define a class in the following order:
    1. Nested classes
    2. Constants
    3. Enums
    4. Properties
    5. Fields
    6. Constructors (if applicable)
    7. Unity Messages
    8. Public methods
    9. Private methods
public class MyClass : MonoBehaviour
{
private class MyNestedClass
{
...
}

private const int SOME_CONSTANT = 1;

public enum SomeEnum
{
FirstElement,
SecondElement
}

public int SomeProperty
{
get => someField;
}

private int someField;

private void Start()
{
...
}

public void SomePublicMethod()
{
...
}

private void SomePrivateMethod()
{
...
}
}
  • Prefer defining methods in the following order:
    1. Initialization methods
    2. Core functionality methods
    3. Helper or explanatory methods
// Initialization
private void Initialize()
{
...
}

// Core functionality
private void Move(Vector3 direction)
{
...
}

// Helper
private bool CheckIfPositionIsWalkable(Vector3 position)
{
...
}

Naming Conventions

  • Identifiers for classes, methods, namespaces, enums, properties, attributes and coroutines are PascalCase;
namespace OpenSoulsGame.Debug
public class RichTextFormatter
public string StringToBold(this string inputString)
public float DefaultSpacing
{
...
}
[ConsoleAttribute] private int letterSpacing;
  • Identifiers for fields, local variables, parameters are camelCase;
public  int playerId;
private InputHandler playerInput;
private float health;
var name = GetPlayerName(playerId);
  • Constants are written in UPPER_CASE;
public const int MAX_SCENE_OBJECTS = 256;
  • Acronyms should be treated as words and are written in PascalCase.
public class XmlFormatter
public class AiBehaviour
  • The conventions for casing are unaffected by the modifiers public, private, protected, internal, static or readonly;

  • Namespace identifiers should briefly describe the systems or sets of definitions contained in the namespace.

namespace Utilities.Debug
namespace TowerDefenseGame.Combat
namespace TowerDefenseGame.UI
  • Class identifiers should briefly describe its responsibilities or data. Prefer including the suffix "Base" in abstract classes where applicable.
// A class responsible for performing movement on the player character's transform
class PlayerMotor
// An abstract class for implementing behaviors for AI Agents
abstract class AiBehaviourBase
  • Interfaces should include the prefix "I". The interface name should briefly describe the purpose of its members or the components it interacts with.
interface IMotorTarget
interface IUiElement
  • Method identifiers should describe the effect caused by the method, or the return value if the method has no effect.
// A method that performs movement on the player character
public void Move(Vector3 movement)
{
...
}
// Tipically, the identifier for methods without a return type should be a verb
// A method that converts radians to degrees.
private float RadianToDegrees(float radians)
{
...
}
// The identifier helps to understand how the returned value should be interpreted
// A method to determine if a position in the world can be traversed by the player
private bool IsPositionWalkable(Vector3 position)
  • Coroutines are written with the prefix 'CO_', and the rest of its identifier should follow the same rules as methods.
IEnumerator CO_SpawnPlayer(int playerId)

Code Documentation

  • Write self-documenting code when possible. Avoid overly abbreviated variables which don't have semantic value for the reader.
// Bad:
p = p + v * dt;
// Good:
position = position + velocity * deltaTime;
  • You can also use explanatory variables to avoid writing complicated and unreadable lines:
// Bad:
pos = Vector3.Lerp(targetEnemy.position, player.GetComponent<AutoMovementController>().targetWaypoint.nextPosition, elapsedTime / max);
// Good:
var waypoint = player.GetComponent<AutoMovementController>().targetWaypoint;
var startPosition = targetEnemy.position;
var finalPosition = waypoint.nextPosition;
var lerpPoint = elapsedTime / maxMovementTime;
position = Vector3.Lerp(startPosition, finalPosition, lerpPoint);
  • Write useful comments. Avoid being redundant with what the code is telling the reader. Instead, disclose valuable information that might not be directly perceivable.
// Bad:
// increment player id
playerId++;
// Good:
// We know that a new player has joined, generate a new identifier.
playerId++;
  • Do not comment bad or unreadable code. Prefer rewriting it instead.
// Bad:
// Increase current position by the velocity scaled by deltaTime to perform movement.
p = p + v * dt;
// Good:
position = position + velocity * deltaTime;
  • Do not contradict the code!
// Bad:
// Health value should be between 0 and 100.
private int health;

...

this.health = 150;
// Good:
// Base health values should be between 0 and 100.
private int health;

...

// Apply the temporary health buff from consuming potion.
this.health = 150;

References

· One min read
Byungnam Lee

DocSearch Issues

I Have trouble getting started with Algolia, especially with the pushing the site's index data to Algolia server, which has the following schematics;

local site --> server (where the app is deployed) <-- crawler --> algolia db as indexed objects

and your typical deploy process would be; add or update your local version, build and deploy to the server. The deployed would be different from your local version as the running site and local development are bascially two different things. As Algolia won't care about your local site, the issues of not knowing what is at stake are apparent. They have a Dashboard where you can update and monitor this whole process. If I am not wrong, I felt there are significant time-lapse for the changes to be updated.

And they have detailed instructions and snippets or cli to go with. They support all major documentation platforms for jump-starters. So their doc gets complicated and requires where you are at with your current development and what to choose from their set of tables.

I find it useful to refer to their show-case sites which resemble your development interface and requirements, such as Astromers in my case.

· One min read
Byungnam Lee
Jungil Suk

Github Actions deploy scripts

name: Deploy to GitHub Pages

on:
push:
branches:
- master
# Review gh actions docs if you want to further define triggers, paths, etc
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on

jobs:
deploy:
name: Deploy to GitHub Pages
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
cache: npm

- name: Install dependencies
run: npm install --frozen-lockfile
- name: Build website
run: npm run build

# Popular action to deploy to GitHub Pages:
# Docs: https://github.com/aiegoo/archery
- name: Deploy to GitHub Pages
uses: actions/checkout@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
# Build output to publish to the `gh-pages` branch:
publish_dir: ./build
# The following lines assign commit authorship to the official
# GH-Actions bot for deploys to `gh-pages` branch:
# https://github.com/actions/checkout/issues/13#issuecomment-724415212
# The GH actions bot is used by default if you didn't specify the two fields.
# You can swap them out with your own user credentials.
user_name: aiegoo
user_email: 42961200+github-actions[bot]@users.noreply.github.com

Issues

`The deploy didn't really happen yet even though the process clearly said it's gone through without a glitch. I think 'build' isn't actually add the built files to gh-pages.

· One min read
Byungnam Lee

building skeleton joints for Maya

image

image

maya hotkeys

Common Hotkeys used in Maya
F1 Maya Help
F2 Animation menu
F3 Modeling menu
F4 Surfaces menu
1 Rough NURBS smooth/Actual polygonal preview
2 Medium NURBS smooth/Polygonal smooth + actual cage preview
3 Fine NURBS smooth/Polygonal smooth preview
4 Wireframe mode
5 Shaded mode
6 Hardware texturing
7 Show light simulation
q Select tool
w Move tool
e Rotate tool
r Scale tool
t Show manipulators
y Last tool selected
s Sets a keyframe
f Frame selection in current view
g Repeat last command
ctrl+ g Groups selection
p Parents first selection (or more) to last selected
P (shift + p) Unparents first selection (or more) to last selected v
Snap to point
b Resizes artisan brush
x Snap to grid
z (ctrl+ z) Undo
Z (shift + z) Redo
+ /= Increase manipulator size
- Decrease manipulator size
Spacebar (hold) Show hotbox
Spacebar (tap) When done over a viewport, maximizes/minimizes current window
Insert Key Pivot point edit mode
F2– Animation, F3 – Polygons, and F4 – Surfaces)

image

image

Image

https://user-images.githubusercontent.com/42961200/187316662-0639dd94-ca33-4947-a3cf-163439a56a36.mov

· One min read
Byungnam Lee

Bashing blog

if [ $# -ge $CMDLINEPARAM ]
then
blog=$@
else
echo "Atleast ${CMDLINEPARAM} blog name is required."
exit 1
fi

· One min read
tonylee

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet

· One min read
Byungnam Lee
Jungil Suk

what game is

  1. is it fun
  2. how is it being packaged
  3. is it creative and stand-out
  4. is it doable or is it something wishful
  5. is it clear on the architecture
  6. does it sound appropriate
  7. is it in focus and immersable
  8. does it allow different views
  9. what emotion does it evoke
  10. is it detailed
  11. perfection level