Skip to content

Commit ca8d076

Browse files
authored
Update README.md
Updated README.md.
1 parent db6b25e commit ca8d076

1 file changed

Lines changed: 246 additions & 2 deletions

File tree

README.md

Lines changed: 246 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,246 @@
1-
# Unity-Style-Guide
2-
Document style guideline for Unity and C# within our company, so the game developers can follow and create a high quality of code and easily collaborative projects.
1+
# [Coding Guideline for Unity C#](https://www.richardfu.net/coding-guideline-for-unity-c/)
2+
3+
As a programmer, it is very important to follow a coding standard and make sure others can read and easily understand his code. While there’s not majority guideline of coding standard in Unity and C#, [you can/should code whatever you like](http://wiki.c2.com/?UncleBobOnCodingStandards), but in this article I’m going to show you our style and format guideline within the company. We have tried to adopt different styles throughout these years and came out the one we feel most comfortable.
4+
5+
Our **3 golden rules** to forms our style standard:
6+
1. Follow Unity’s style in [Scripting Reference](https://docs.unity3d.com/ScriptReference/)
7+
2. The rest follow Microsoft’s [C# Coding Conventions](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions)
8+
3. Minor tweak where we believe that can make the code clearer
9+
10+
#### Folder Structure
11+
12+
All similar files should be grouped in the root folders:
13+
14+
```
15+
Assets
16+
Animations Animation clips
17+
Editor Editor specified scripts, prefabs, etc
18+
Fonts Fonts used in game
19+
Materials Texture materials
20+
Prefabs In-game prefabs
21+
Resources Unity resources assets
22+
Scenes Scenes
23+
Scripts Code scripts, grouped in sub-folders
24+
Sounds Musics, sounds
25+
SweatyChair Company folder that share across projects
26+
(ModuleName1) Module name, e.g. DailyLogin
27+
(Scripts) Scripts within the module
28+
(Prefabs) Prefabs within the module
29+
... Other assets grouped in folders
30+
... Other modules
31+
Textures Image textures
32+
UI Texture used for UI
33+
Icons App icons
34+
```
35+
36+
> We have a `SweatyChair` folder, which containes a number of well-structure modules and sync across projects using Git [submodules](https://www.git-scm.com/book/en/v2/Git-Tools-Submodules). We we are always reuse the commond code and able to perform rapid prototyping.
37+
38+
#### File Naming
39+
40+
File naming is simple, always use Pascal Case except for images:
41+
42+
- Folders – PascalCase
43+
`FolderName`/
44+
- Images – hyphen-
45+
`image-name-64x64.jpg`
46+
- The rest – PascalCase
47+
`ScriptName.cs`, `PrefabName.prefab`, `SceneName.unity`
48+
49+
> The reason images use hyphen naming is that most images are also used in our website / press-kit. Hyphen naming is the majority naming convention for web image and it’s also [search engine friendly](https://www.natalleblas.com/optimise-images-for-seo/). Using the same name can save us time renaming and easily find the same image switching between Unity and web.
50+
51+
#### Scripts Naming
52+
53+
While each script has its unique purpose and use cases, we follow these naming rules and so we can still roughly know what the script is for by simply reading the filenames:
54+
55+
- `XxxPanel`, `XxxSlot`, `XxxButton`, etc for UI
56+
`MenuPanel`, `AchievementSlot`, `CoinShopButton`
57+
- `XxxManager`, for master scripts that control specific workflow (only ONE instance in the scene)
58+
`DailyMissionManager`, `AchievementManager`
59+
- `XxxController`, for scripts controlling a game object (one or many in the scene)
60+
`PlayerController`, `BossController`, `BackgroundControler`
61+
- `XxxDatabase`, for a database (e.g CSV) which contains a list of data rows
62+
`WeaponDatabase`, `CardDatabase`
63+
- `XxxData`, for data row in a CSV database
64+
`WeaponData`, `CardData`
65+
- `XxxItem`, for in-game item instance
66+
`CardItem`, `CharacterItem`
67+
- `XxxGenerator`, for scripts instantiate GameObjects
68+
`ObjectGenerator`, `LandGenerator`
69+
- `XxxSettings`, for settings scripts inherent Unity’s [`ScriptableObject`](https://docs.unity3d.com/Manual/class-ScriptableObject.html) class
70+
`AchievementSettings`, `DailyLoginSettings`
71+
- `XxxEditor`, for editor-only scripts inherent Unity’s `[Editor](https://docs.unity3d.com/ScriptReference/Editor.html)` class
72+
`TutorialTaskEditor`, `AchievementSettingsEditor`
73+
74+
> Difference between `Manager` and `Controller` is `Manager` should be singleton or static, and it controls a specific game logic that may involve multiple objects and assets, while Controller controls an object and may have multiple instances. For example, there are multiple EnemyController in the scene and each control one enemy. We will discuss more on this in a singleton article.
75+
76+
> Difference between `Data` and `Item` is that `Item` is an instance in-game, and in most cases `Item` contains a `Data`. For example `CardData` has all preset attributes of a card, while `CardItem` has its `CardData` plus attributes that vary for different players, such as card level. We will talk about more this in another data structure article.
77+
78+
#### Variable Naming
79+
80+
Similar to file naming, variable naming allow us to know what the variable is for without reading though all code:
81+
82+
- Use camcelCase, always as of a noun or in a form of (is/has)Abjective
83+
`hasRewarded`, `currentPosition`, `isInitialized`
84+
- Prefix with an underscore for private and protected variables
85+
`_itemCount`, `_controller`, `_titleText`
86+
- All capital letters for const
87+
`SHOW_SUB_MENU_LEVEL`, `MAX_HP_COUNT`, `BASE_DAMAGE`
88+
- All capital letters and PREFS_XXXX for PlayerPref keys
89+
`private const string PREFS_LAST_FREE_DRAW = “LastFreeDraw”;`
90+
`PlayerPrefs.GetInt(PREFS_LAST_FREE_DRAW)`
91+
- Use `xxxGO` for scene GameObject variables
92+
`optionButtonGO`, `backgroundMaskGO`
93+
- Use `xxxPrefab` for scene GameObject variables
94+
`weaponSlotPrefab`, `explosionPrefab`
95+
- Use `xxxTF` for Transform variables
96+
`weaponTF`, `armTF`
97+
- Use `xxxComponent` for all other components, abbreviate if needed
98+
`eyesSpriteRenderer` / `eyesSR`, `runAnimation` / `runAnim`, `attckAnimationClip` / `attackAC`, `victoryAudioClip` / `victoryAC`
99+
- Use xxxxs for arrays
100+
`slotPrefabs = new Prefabs[0]`
101+
`achievementIds = new int [0]`
102+
- Use xxxxList for List and xxxxDict for Dictionary
103+
`weaponTransformList = new List()`
104+
`achievementProgressDict = new Dictionary()`
105+
- Use nounVerbed for callback event
106+
`public static event UnityAction gameStarted`
107+
`public static UnityAction characterDied`
108+
109+
> Unity use prefix `m_` for private/protected variables, and `s_` for static variables (see their [BitBucket](https://bitbucket.org/Unity-Technologies/assetbundlegraphtool/src/0e498d12964d7cd1b86728289ff6f8321d127db4/Runtime/AssetBundleBuildMap.cs)). We found that this makes the code very hard to read, so we leave one underscore for private/protected variables and keep it the same for both static and non-static variables.
110+
111+
> Callback event follow Unity’s event naming convention, e.g. `[SceneManager.activeSceneChanged](https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager-activeSceneChanged.html)`.
112+
113+
#### Functions Naming
114+
115+
- Use PascalCase, start with a verb and followed by a noun if needed
116+
`Reward()`, `StartGame()`, `MoveToCenter()`
117+
- Use `OnXxxxClick`, for UI button clicks
118+
`OnStartClick()`, `OnCancelClick()`
119+
- Use `OnNounVerbed`, for callbacks
120+
`OnChestOpened()`, `OnBuyWeaponConfirmed()`
121+
122+
#### Member Properties
123+
124+
If a function has no input, use member property (aka get/set property) instead, in PacelCase as well:
125+
`bool IsRewarded() { }`
126+
to
127+
`bool IsRewarded {get { return …} }`
128+
Or even in a shortened form as
129+
`bool IsRewarded => ...;`
130+
131+
Also, use member properties where a variable can only set internally but can be accessed publicly:
132+
`public int Id { get; private set; }`
133+
`public Sprite IconSprite { get; private set; }`
134+
135+
#### Variables / Functions orders
136+
137+
Having a consistent order can greatly save our time on looking for a specific variable or function:
138+
139+
```
140+
MyCalss : Monobehavior
141+
{
142+
// Constant variables
143+
public const int CONST_1;
144+
private const string CONST_2;
145+
146+
// Static variables
147+
public static int static1;
148+
private static string _static2;
149+
150+
// Editor-assigned variables
151+
[SerializeField] public Image maskImage;
152+
[SerializeField] private MyClass _anotherComponent;
153+
154+
// Other varaibles
155+
public int primitiveVariables1;
156+
private string _primitiveVariable2;
157+
158+
// Properties
159+
public int Property1 {get; set;}
160+
private string _roperty2 {get; set;}
161+
162+
// Unity functions
163+
Awake()
164+
OnEnable()
165+
Start()
166+
Update()
167+
FixedUpdate()
168+
169+
// Other custom functions
170+
Init()
171+
...
172+
Reset()
173+
174+
// Unity functions
175+
OnDisable()
176+
OnDestroy()
177+
178+
#region UNITY_EDITOR
179+
// Eebug functions that only runs in Editor
180+
[ContextMenu("...")]
181+
private void DebugFunction1()
182+
[MenuItem("Debug/...")]
183+
private static void DebugFunction2()
184+
#endregion
185+
}
186+
```
187+
188+
You can also group valuables and functions in a region in large scripts (but not too large enough to be split into another script):
189+
190+
```
191+
#region Timer
192+
private const int RESET_SECONDS = 180;
193+
private float _secondsLeft;
194+
public float canResetTime => _secondsLeft < 0;
195+
public void ResetTime()
196+
{
197+
_secondsLeft = RESET_SECONDS;
198+
}
199+
#endregion Timer
200+
... // Other regions
201+
```
202+
203+
#### Code Formatting
204+
205+
We use **K&R** style which is already preset in Mac Visual Studio:
206+
207+
![](https://i1.wp.com/www.richardfu.net/wp-content/uploads/2020/10/KR-style-in-Mac-Visual-Studio.jpg?resize=1022%2C691&ssl=1)
208+
209+
While there’s not K&R in Windows (Why, Microsoft?), just a little bit effort to manually set few ticks:
210+
211+
![](https://i2.wp.com/www.richardfu.net/wp-content/uploads/2020/10/Windows-coding-format-1.jpg?resize=1024%2C173&ssl=1)
212+
213+
![](https://i2.wp.com/www.richardfu.net/wp-content/uploads/2020/10/Windows-coding-format-2.jpg?resize=1024%2C492&ssl=1)
214+
215+
![](https://i2.wp.com/www.richardfu.net/wp-content/uploads/2020/10/Windows-coding-format-3.jpg?resize=1024%2C766&ssl=1)
216+
217+
![](https://i0.wp.com/www.richardfu.net/wp-content/uploads/2020/10/Windows-coding-format-4.jpg?resize=1024%2C107&ssl=1)
218+
219+
#### Brackets and Newlines
220+
221+
For single-line conditional statements we do not need any brackets:
222+
223+
```
224+
if (1 == 1)
225+
DoSomethingFancy();
226+
if (1 == 1) return true;
227+
if (1 == 1) {
228+
FirstThing();
229+
LastThing();
230+
}
231+
```
232+
233+
> Many developers, includes Unity, favourite putting newlines after open bracket ( `{` ). It may make the code looks more tidy and symmetric, but also creates a lot of unuseful lines and making script scrolling much more often and longer. Every bit count. If you spend 1 more second on scrolling a day, you probably wasted 5 minutes of valuable time a year.
234+
235+
#### Comments
236+
237+
Single line comments should include a space after the slashes:
238+
`// Notice the space after the two slashes`
239+
Temporarily commenting out code should not include a space after the slashes, to be differentiated from the normal comment:
240+
`//noSpace.Code();`
241+
`TODO` comments should include the space after the slashes and then 2 spaces after the colon following the TODO
242+
`// TODO: Notice the space after the slashes and the 2 spaces after the colon of todo`
243+
244+
----------
245+
246+
That’s all. This may go bigger when you adopt more latest .Net syntax. There are also a few other good [guidelines](https://github.com/justinwasilenko/Unity-Style-Guide) if you want to read [more](http://www.arreverie.com/blogs/unity3d-best-practices-folder-structure-source-control/). Free feel to follow this style if you think it’s reasonable and helpful, so we may create a better game dev world where code is clean and please to read. 😀

0 commit comments

Comments
 (0)