
Unity での C# スクリプティングのための命名とコードスタイルのヒント
このウェブページは、お客様の便宜のために機械翻訳されたものです。翻訳されたコンテンツの正確性や信頼性は保証いたしかねます。翻訳されたコンテンツの正確性について疑問をお持ちの場合は、ウェブページの公式な英語版をご覧ください。
C# コードをフォーマットする正しい方法は 1 つとは限りませんが、チーム全体で一貫したスタイルにすることで、よりクリーンで読みやすく、スケーラブルなコードベースを実現できます。よく整理されたスタイルガイドは、一貫性のある最終製品を生み出すために、不一致を抑えるのに役立ちます。
変数、クラス、メソッドの名前は単なるラベルではありません。それらは重みと意味を持ちます。優れた命名スタイルは、プログラムを読む人が伝えようとしているアイデアを理解する方法に影響を与えます。
このページでは、独自のスタイルガイドを作成する際に、命名規則とコードフォーマットについて留意すべきヒントと主な考慮事項を紹介します。
注:ここで紹介する推奨事項は、Microsoft が提供する推奨事項に基づいています。最適なコードスタイルガイドのルールは、チームのニーズに最も適したルールです。
コード スタイル ガイドの例はこちらから、または完全な e ブック「Use a C# style guide for clean and scalable game code (Unity 6 edition)」をダウンロードしてください。
識別子名
識別子とは、型 (クラス、インタフェース、構造体、デリゲート、列挙型)、メンバー、変数、または名前空間に割り当てる任意の名前です。
C# では特殊文字(バックスラッシュ、記号、Unicode 文字)の使用が許可されていますが、識別子には使用しないでください。これらは、特定の Unity コマンドラインツールと干渉する可能性があります。ほとんどのプラットフォームとの互換性を確保するために、珍しいキャラクターは避けましょう。
ケーシング用語
C# では識別子を区切るためにスペース文字が使用されるため、名前にスペースを含む変数を定義することはできません。ケーシングスキームは、ソースコードで複合名やフレーズを使用しなければならない問題を軽減できます。
よく知られている命名規則とケーシング規則をいくつか紹介します。
キャメルケース(camelCase)
キャメルケースはキャメルキャップとも呼ばれ、スペースや句読点を使わずにフレーズを記述する手法です。単語を大文字 1 文字で区切ります。最初の文字は小文字です。ローカル変数とメソッドのパラメーターはキャメルケースです。例:
examplePlayerController
maxHealthPoints
endOfFile
パスカルケース (PascalCase)
パスカルケースはキャメルケースのバリエーションで、最初の文字を大文字にします。Unity 開発では、クラス名、パブリックフィールド名、メソッド名に使用します。例:
ExamplePlayerController
MaxHealthPoints
EndOfFile
スネークケース (snake_case)
この場合、単語間のスペースはアンダースコア文字に置き換えられます。例:
example_player_controller
max_health_points
end_of_file
ケバブケース (kebab-case)
ここでは、単語間のスペースはダッシュに置き換えられます。ダッシュの「串」に刺さる言葉。例:
example-player-controller
Max-health-points
end-of-file
naming-conventions-methodology
ケバブケースはウェブ技術、特に CSS で広く使用されています。UI Toolkit USS との併用もおすすめです。
ハンガリー記法
変数名や関数名は、多くの場合、その意図や型を示します。例:
int iCounter
string strPlayerName
ハンガリアン記法は古い規則であり、Unity 開発では一般的ではありません。
フィールドと変数
変数とフィールドについては、次の規則を考慮してください。
- 変数名に名詞を使用:変数名は、物や状態を表すため、説明的で明確で一義的である必要があります。そのため、変数が bool 型の場合を除き、名詞を使用して名前を付けます(以下を参照)。
- Booleans には動詞のプレフィックスを付ける:これらの変数は、true または false の値を示します。多くの場合、これらは「プレイヤーが走っているか」などの質問に対する回答です。ゲームは終わりですか?動詞の前に付けると意味がより明確になります。多くの場合、これは説明や条件と組み合わされます (例: isDead、isWalking、hasDamageMultiplier)。
- 意味のある名前を使用してください。省略しない(数学的な場合を除き):変数名は、その意図を明らかにする必要があります。同僚だけでなく、AI ツールを使用する際のコードのコンテキストも提供するなど、発音しやすく、検索しやすい名前を選びましょう。これにより、より正確なコード生成と提案が可能になります。識別子名は読みやすいものを選びましょう。例えば、HorizontalAlignment という名前のプロパティは、AlignmentHorizontal よりも読みやすくなります。ループや数式では 1 文字の変数で問題ありませんが、省略してはいけません。母音をいくつか省略することで節約できる時間よりも、明瞭さが重要です。プロトタイピング時には短い「ジャンク」名を使いたくなるかもしれませんが、後でコードをリファクタリングする必要がある場合は、これでは時間の節約にはなりません。最初から意味のある名前を選びましょう。
- public フィールドにはパスカルケース (MyPropertyName) を使用します。private 変数にはキャメルケース (myPrivateVariable) を使用する: public フィールドの代わりに、public getter で Properties を使用します(上記および後述の Formatting を参照)。
- プレフィックスまたは特殊なエンコーディングの使用を検討してください。一部のガイドでは、private メンバー変数をローカル変数と区別するために、プレフィックスにアンダースコア (_) を付けることが推奨されています。スタイルガイドでは、プライベートメンバー変数 (m_)、定数 (k_)、静的変数 (s_) にプレフィックスを使用して、変数の詳細が一目でわかるようにしています。例えば、moveSpeed は m_ movementSpeed になります。パスカルケースに m_MovementSpeed などのプレフィックスを付けることもできますが、最近の C# では一般的にあまり使われていません。また、コンテキスト内でメンバー変数とローカル変数を区別し、プレフィックスを省略するには、 this キーワードを使用します。public フィールドとプロパティには一般的にプレフィックスがありません。ローカル変数とパラメーターはプレフィックスなしでキャメルケースを使用します。多くの開発者はこれらを避け、代わりにエディターを利用しています。ただし、すべての IDE が強調表示や色分けをサポートしているわけではなく、ツールによってはリッチなコンテキストをまったく表示できないものもあります。
- フィールドは自動的にデフォルト値に初期化されます。int のような数値型のデフォルト値は通常 0 ですが、参照型フィールド(オブジェクトなど)はデフォルトで null に初期化され、bool 型フィールドはデフォルトで false に初期化されます。このことから、一般的にフィールドを明示的にデフォルト値に設定する必要はありません。
- 定数変数にはプレフィックスとして k_ を付け、パスカルケースで名前を付けます。これにより、定数を通常の変数やプロパティーと区別し、コードを読みやすく、保守しやすくなります。
- アクセス レベルの修飾子は、一貫して指定(または省略)してください。アクセス修飾子を省略すると、コンパイラーはアクセスレベルを private と見なします。これはうまく機能しますが、デフォルトのアクセス修飾子の省略方法に一貫性を持たせてください。MSFT ガイドラインでは、アクセスレベルを明確にして曖昧さを避けるために、private を明示的に指定することが推奨されています。他のガイドでは、冗長なアクセス指定子 (型スコープでは「private」を省く) や、同様に冗長な初期化子 (int では「= 0」を省く、参照型では「= null」など) を省くべきだと主張しています。後でこれをサブクラスで使用したい場合は、protected を使用する必要があることに注意してください。しかし、一般的にはアクセスレベルの修飾子を指定するのがよいとされています。
- 簡潔さよりも読みやすさを重視:MSFT ドキュメントのこの例が示すように、プロパティ名 CanScrollHorizontally は ScrollableX(X 軸への不明瞭な参照)よりも優れています。
- 1 行に 1 つの変数宣言を使用する:コンパクトではありませんが、可読性は向上します。
- 冗長な名前を避ける:クラスが Player という名前であれば、PlayerScore や PlayerTarget というメンバー変数を作成する必要はありません。「Score」または「Target」に引き下げます。
- 冗長な初期化子(int では '= 0'、参照型では '= null' など)は削除してください。
- ジョークやダジャレを避ける:今となっては厄介かもしれませんが、infiniteMonkeys や dudeWheresMyChar 変数は数十回読み込んでも意味がありません。さらに重要なことに、コンテキストを明らかにするために命名するという前述の目標に違反しています。
- 可読性が高く、型が明らかな場合は、var キーワードの使用を暗黙的に型指定されたローカル変数に限定する: スタイルガイドで var を使用するタイミングを指定します。例えば、多くの開発者は変数の型が不明瞭な場合や、ループ外のプリミティブ型では var を避けます。

// EXAMPLE: Public and private variables
public float DamageMultiplier = 1.5f;
public float MaxHealth;
public bool IsInvincible;
private bool _isDead;
private float _currentHealth;
// parameters
public void InflictDamage(float damage, bool isSpecialDamage)
{
// local variable
int totalDamage = damage;
// local variable versus public member variable
if (isSpecialDamage)
{
totalDamage *= DamageMultiplier;
}
// local variable versus private member variable
if (totalDamage > _currentHealth)
{
/// ...
}
}
列挙
列挙型は、名前付き定数のセットによって定義される特殊な値型です。デフォルトでは、定数は 0 から数えて整数です。
列挙型の名前と値にはパスカルケースを使用します。クラスの外側に public 列挙型を配置してグローバル化できます。列挙型の名前は、取りうる値のセットから 1 つの値を表すため、名詞は単数形を使用します。プレフィックスやサフィックスは付けないでください。
注:System.FlagsAttribute アトリビュートでマークされたビット単位の列挙型はこの規則の例外です。通常、これらは複数の型を表すため、複数形になります。
// EXAMPLE: Enums use singular nouns …
public enum WeaponType
{
Knife,
Gun,
RocketLauncher,
BFG
}
public enum FireMode
{
None = 0,
Single = 5,
Burst = 7,
Auto = 8,
}
// EXAMPLE: … but a bitwise enum is plural.
[Flags]
public enum AttackModes
{
// Decimal // Binary
None = 0, // 000000
Melee = 1, // 000001
Ranged = 2, // 000010
Special = 4, // 000100
MeleeAndSpecial = Melee | Special // 000101
}
クラスとインターフェース
クラスとインターフェースに名前を付けるときは、以下の標準ルールに従ってください。
- クラス名にパスカル大文字の名詞または名詞句を使用する:これにより、型名と動詞句で命名されたメソッドが区別されます。
- ファイル内に MonoBehaviour がある場合、ソース ファイル名は次のようになります。ファイル内に他の内部クラスが存在する場合もありますが、MonoBehaviour は 1 つのファイルにつき 1 つだけ存在する必要があります。
- インターフェイス名の前に大文字の I:その後に、機能を説明する形容詞を付けます。
// EXAMPLE: Class formatting
public class ExampleClass : MonoBehaviour
{
public int PublicField;
public static int MyStaticField;
private int _packagePrivate;
private int _myPrivate;
private static int _myPrivate;
protected int _myProtected;
public void DoSomething()
{
}
}
// EXAMPLE: Interfaces
public interface IKillable
{
void Kill();
}
public interface IDamageable<T>
{
void Damage(T damageTaken);
}
メソッド
C# では、実行されるすべての命令はメソッドのコンテキストで実行されます。
注:Unity 開発では、「関数」と「メソッド」はしばしば同じ意味で使用されます。しかし、C# のクラスに関数を組み込まないと書けないので、「メソッド」という言葉が使われています。
メソッドはアクションを実行するので、以下の規則を適用して適切な名前を付けます。
- 名前は動詞または動詞句で始めます。必要に応じてコンテキストを追加します(例:GetDirection、FindTarget)。
- パラメーターにキャメルケースを使用する:ローカル変数のようにメソッドに渡されるフォーマットパラメーター。
- ブーリアンを返すメソッドは、次のように質問する必要があります。Boolean 型の変数自体と同様に、真偽の条件を返す場合はメソッドの前に動詞を付けます。これにより、IsGameOver、HasStartedTurn などの質問の形式でフレーズが付けられます。
// EXAMPLE: Methods start with a verb.
public void SetInitialPosition(float x, float y, float z)
{
transform.position = new Vector3(x, y, z);
}
// EXAMPLE: Methods ask a question when they return bool.
public bool IsNewPosition(Vector3 currentPosition)
{
return (transform.position == newPosition);
}
イベントとイベントハンドラー
C# のイベントはオブザーバーパターンを実装します。このソフトウェアデザインパターンは、サブジェクト(またはパブリッシャー)である 1 つのオブジェクトが、オブザーバー(またはサブスクライバー)と呼ばれる依存オブジェクトのリストに通知できる関係を定義します。そのため、サブジェクトは関連するオブジェクトを緊密に結合することなく、ステートの変化をオブザーバーにブロードキャストできます。Unity プロジェクトでのオブザーバーやその他のデザインパターンの使用方法の詳細については、e ブック「Level up your code with design patterns and SOLID」を参照してください。
動詞を使う
イベントには動詞句で名前を付けます。状態の変化を正確に伝える名前を選択します。現在分詞または過去分詞を使って、イベントが「前」であるか「後」であるかを示します。例えば、ドアを開ける前のイベントには「OpeningDoor」、開けた後のイベントには「DoorOpened」を指定します。
System.Action を使用する
ほとんどの場合、Action デリゲートはゲームプレイに必要なイベントを処理できます。戻り値の型が void の場合、型の異なる 0 から 16 の入力パラメーターを渡すことができます。定義済みのデリゲートを使用すると、コードが保存されます。
注:EventHandler デリゲートまたは EventHandler デリゲートを使用することもできます。全員がイベントをどのように実装するかについてチームで合意する。
// EXAMPLE: Events
// using System.Action delegate
public event Action OpeningDoor; // event before
public event Action DoorOpened; // event after
public event Action<int> PointsScored;
public event Action<CustomEventArgs> ThingHappened;
プレフィックスに「On」を付ける
イベントを呼び出すサブジェクトは、通常、「On」というプレフィックスが付いたメソッドから実行します(例:「OnOpeningDoor」または「OnDoorOpened」です。
// raises the Event if you have subscribers
public void OnDoorOpened()
{
DoorOpened?.Invoke();
}
public void OnPointsScored(int points)
{
PointsScored?.Invoke(points);
}
プレフィックスと件名、アンダースコア
サブジェクトの名前が「GameEvents」の場合、オブザーバーには「GameEvents_OpeningDoor」または「GameEvents_DoorOpened」というメソッドを含めることができます。これは「イベント処理メソッド」と呼ばれます。EventHandler デリゲートと混同しないでください。
EventArgs は慎重に使用してください
カスタム EventArgs は必要に応じてのみ作成します。イベントにカスタムデータを渡す必要がある場合は、System.EventArgs またはカスタム構造体から継承された新しいタイプの EventArgs を作成します。
// define an EventArgs if needed
// EXAMPLE: Read-only, custom struct used to pass an ID and Color
public struct CustomEventArgs
{
public int ObjectID { get; }
public Color Color { get; }
public CustomEventArgs(int objectId, Color color)
{
this.ObjectID = objectId;
this.Color = color;
}
}
名前空間
名前空間を使用して、クラス、インターフェース、列挙型などが他の名前空間やグローバル名前空間の既存のものと競合しないようにします。名前空間は、アセットストアのサードパーティ製アセットとの競合を防ぐこともできます。
名前空間を適用する場合:
- パスカルケースは、特殊記号やアンダースコアなしで使用してください。
- 名前空間接頭辞を繰り返し入力しないように、ファイルの先頭に using ディレクティブを追加します。
- サブ名前空間も作成します。ドット(.)演算子を使用して名前レベルを区切り、スクリプトを階層的なカテゴリに整理できます。例えば、MyApplication.GameFlow、MyApplication.AI、MyApplication.UI などを作成して、ゲームのさまざまな論理コンポーネントを保持できます。
- 一般的に、プロジェクトのフォルダー構造を反映する名前空間は、関連するクラスやコンポーネントを論理的にグループ化することで、コードベースの構造を見つけやすく、理解しやすくするものとして、良いプラクティスと考えられています。
namespace Enemy
{
public class Controller1 : MonoBehaviour
{
...
}
public class Controller2 : MonoBehaviour
{
...
}
}
プレフィックス
コードでは、これらのクラスはそれぞれ Enemy.Controller1 および Enemy.Controller2 と呼ばれます。using 行を追加して、プレフィックスの入力を節約します。
using Enemy;
コンパイラーがクラス名 Controller1 および Controller2 を見つけると、Enemy.Controller1 および Enemy.Controller2 のことと解釈します。
スクリプトが異なる名前空間の同じ名前のクラスを参照する必要がある場合は、プレフィックスを使用して区別します。たとえば、Player 名前空間に Controller1 クラスと Controller2 クラスがある場合、Player.Controller1 クラスと Player.Controller2 クラスを記述して競合を回避できます。そうしないと、コンパイラーはエラーを報告します。
using Enemy;
コードスタイルのヒントをさらに得る
一般的なフォーマットの詳細については、こちらをご覧いただくか、e ブック全文をご覧ください。コードスタイルガイドの例もご覧ください。