1. ゲームエンジン選択(せんたく)ガイド
2026年のゲーム開発はかつてないほど**選択肢(せんたくし)が豊富(ほうふ)**である。Unityはインディーモバイルと中級(ちゅうきゅう)PCで依然(いぜん)強(つよ)く、Unreal Engine 5はAAA級(きゅう)の視覚的(しかくてき)品質(ひんしつ)を全(すべ)てに提供(ていきょう)し、Godot 4はオープンソース陣営(じんえい)で急速(きゅうそく)に成長(せいちょう)している。
1.1 エンジン比較(ひかく)
| 項目(こうもく) | Unity | Unreal Engine 5 | Godot 4 |
|---|---|---|---|
| ライセンス | 売上(うりあげ)ベース | 売上5%ロイヤリティ($1M以降) | 完全(かんぜん)無料(むりょう) |
| 主要言語 | C# | C++ / Blueprint | GDScript / C# |
| 学習曲線(きょくせん) | 中級 | 急峻(きゅうしゅん) | 容易(ようい) |
| グラフィック | URP/HDRP | Lumen, Nanite | OpenGL/Vulkan |
| モバイル最適化 | 非常(ひじょう)に良い | 良い | 良い |
| コンソール対応 | 全コンソール | 全コンソール | 限定的 |
| インディー推奨 | 良い | 良い | 非常に良い |
| AAA推奨 | 可能 | 標準(ひょうじゅん) | 不向(ふむ)き |
1.2 どのエンジンを選(えら)ぶか?
Unity: モバイルゲーム、2Dゲーム、迅速(じんそく)なプロトタイピング、大(おお)きなコミュニティ、AR/VRマルチプラットフォーム
Unreal: 視覚的忠実度(ちゅうじつど)が最優先(さいゆうせん)、オープンワールド、写実的(しゃじつてき)グラフィック、シネマティックカットシーン
Godot: インディープロジェクト、学習目的、ライセンス費用ゼロ、小規模(しょうきぼ)ゲーム、軽量(けいりょう)エンジン
2. Unity Deep Dive
2.1 MonoBehaviour vs DOTS/ECS
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField] private float speed = 5f;
[SerializeField] private float jumpForce = 10f;
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(horizontal, 0, vertical) * speed * Time.deltaTime;
transform.Translate(movement);
if (Input.GetKeyDown(KeyCode.Space) && IsGrounded())
{
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
}
bool IsGrounded()
{
return Physics.Raycast(transform.position, Vector3.down, 1.1f);
}
}
using Unity.Entities;
using Unity.Mathematics;
using Unity.Burst;
public struct PlayerInput : IComponentData
{
public float2 Move;
public bool Jump;
}
public struct Velocity : IComponentData
{
public float3 Value;
}
public struct PlayerSpeed : IComponentData
{
public float Value;
}
[BurstCompile]
public partial struct PlayerMovementSystem : ISystem
{
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
float deltaTime = SystemAPI.Time.DeltaTime;
foreach (var (input, velocity, speed, transform)
in SystemAPI.Query<RefRO<PlayerInput>, RefRW<Velocity>, RefRO<PlayerSpeed>, RefRW<LocalTransform>>())
{
float3 movement = new float3(input.ValueRO.Move.x, 0, input.ValueRO.Move.y) * speed.ValueRO.Value;
velocity.ValueRW.Value = movement;
transform.ValueRW.Position += movement * deltaTime;
}
}
}
2.2 Job SystemとBurst Compiler
using Unity.Collections;
using Unity.Jobs;
using Unity.Burst;
using Unity.Mathematics;
[BurstCompile]
public struct ParallelMovementJob : IJobParallelFor
{
public NativeArray<float3> Positions;
[ReadOnly] public NativeArray<float3> Velocities;
public float DeltaTime;
public void Execute(int index)
{
Positions[index] += Velocities[index] * DeltaTime;
}
}
public class JobScheduler : MonoBehaviour
{
public void UpdatePositions()
{
var positions = new NativeArray<float3>(10000, Allocator.TempJob);
var velocities = new NativeArray<float3>(10000, Allocator.TempJob);
var job = new ParallelMovementJob
{
Positions = positions,
Velocities = velocities,
DeltaTime = Time.deltaTime
};
JobHandle handle = job.Schedule(positions.Length, 64);
handle.Complete();
positions.Dispose();
velocities.Dispose();
}
}
2.3 Addressables - 非同期(ひどうき)アセット管理(かんり)
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class AddressableLoader : MonoBehaviour
{
[SerializeField] private AssetReferenceGameObject playerPrefab;
async void Start()
{
AsyncOperationHandle<GameObject> handle = playerPrefab.InstantiateAsync();
await handle.Task;
if (handle.Status == AsyncOperationStatus.Succeeded)
{
GameObject player = handle.Result;
Debug.Log($"Loaded: {player.name}");
}
}
void OnDestroy()
{
Addressables.Release(playerPrefab);
}
}
2.4 URP vs HDRP
| 特徴(とくちょう) | URP | HDRP |
|---|---|---|
| 対象(たいしょう) | モバイル、VR、コンソール | 高(こう)スペックPC、コンソール |
| 品質 | 良い | 映画(えいが)級 |
| 性能 | 非常に良い | 重(おも)い |
| 用途(ようと) | インディー、モバイル | AAA、シミュレータ |
3. Unreal Engine 5 Deep Dive
3.1 Blueprint vs C++
Unrealは2つのワークフローを提供する。Blueprintは視覚的(しかくてき)ノードベースで迅速(じんそく)なプロトタイピングに適(てき)し、C++は性能と複雑(ふくざつ)なロジックに適する。
#include "MyCharacter.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/SpringArmComponent.h"
AMyCharacter::AMyCharacter()
{
PrimaryActorTick.bCanEverTick = true;
SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
SpringArm->SetupAttachment(RootComponent);
SpringArm->TargetArmLength = 400.0f;
SpringArm->bUsePawnControlRotation = true;
Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
Camera->SetupAttachment(SpringArm, USpringArmComponent::SocketName);
GetCharacterMovement()->bOrientRotationToMovement = true;
GetCharacterMovement()->RotationRate = FRotator(0.0f, 540.0f, 0.0f);
GetCharacterMovement()->JumpZVelocity = 600.0f;
GetCharacterMovement()->AirControl = 0.2f;
}
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
PlayerInputComponent->BindAxis("MoveForward", this, &AMyCharacter::MoveForward);
PlayerInputComponent->BindAxis("MoveRight", this, &AMyCharacter::MoveRight);
PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
}
void AMyCharacter::MoveForward(float Value)
{
if (Value != 0.0f)
{
const FRotator Rotation = Controller->GetControlRotation();
const FRotator YawRotation(0, Rotation.Yaw, 0);
const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
AddMovementInput(Direction, Value);
}
}
3.2 Lumen - 動的(どうてき)グローバルイルミネーション
LumenはUnreal Engine 5の中核(ちゅうかく)機能の1つで、ベイクなしでリアルタイム間接照明と反射(はんしゃ)を処理する。
APostProcessVolume* PPV = ...;
PPV->Settings.bOverride_DynamicGlobalIlluminationMethod = true;
PPV->Settings.DynamicGlobalIlluminationMethod = EDynamicGlobalIlluminationMethod::Lumen;
3.3 Nanite - 仮想化ジオメトリ
Naniteは数十億ポリゴンメッシュを自動的(じどうてき)にLOD処理する。モデラーは手動(しゅどう)でLODを作(つく)る必要(ひつよう)がない。
UStaticMesh* Mesh = ...;
Mesh->NaniteSettings.bEnabled = true;
Mesh->NaniteSettings.PercentTriangles = 1.0f;
3.4 World Partition
巨大(きょだい)なオープンワールドを自動的にグリッドセルに分割(ぶんかつ)し、必要時のみロード。
4. Godot 4 Deep Dive
4.1 GDScript
extends CharacterBody3D
const SPEED = 5.0
const JUMP_VELOCITY = 4.5
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
func _physics_process(delta):
if not is_on_floor():
velocity.y -= gravity * delta
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = JUMP_VELOCITY
var input_dir = Input.get_vector("move_left", "move_right", "move_forward", "move_back")
var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if direction:
velocity.x = direction.x * SPEED
velocity.z = direction.z * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
velocity.z = move_toward(velocity.z, 0, SPEED)
move_and_slide()
4.2 SceneシステムとSignal
extends Node
signal player_died(score)
signal score_changed(new_score)
var score = 0:
set(value):
score = value
score_changed.emit(score)
func _ready():
var player = $Player
player.died.connect(_on_player_died)
func _on_player_died():
player_died.emit(score)
get_tree().reload_current_scene()
func add_score(amount: int):
score += amount
4.3 C#サポート
using Godot;
public partial class PlayerController : CharacterBody3D
{
public const float Speed = 5.0f;
public const float JumpVelocity = 4.5f;
public float Gravity = ProjectSettings.GetSetting("physics/3d/default_gravity").AsSingle();
public override void _PhysicsProcess(double delta)
{
Vector3 velocity = Velocity;
if (!IsOnFloor())
velocity.Y -= Gravity * (float)delta;
if (Input.IsActionJustPressed("jump") && IsOnFloor())
velocity.Y = JumpVelocity;
Vector2 inputDir = Input.GetVector("move_left", "move_right", "move_forward", "move_back");
Vector3 direction = (Transform.Basis * new Vector3(inputDir.X, 0, inputDir.Y)).Normalized();
if (direction != Vector3.Zero)
{
velocity.X = direction.X * Speed;
velocity.Z = direction.Z * Speed;
}
else
{
velocity.X = Mathf.MoveToward(Velocity.X, 0, Speed);
velocity.Z = Mathf.MoveToward(Velocity.Z, 0, Speed);
}
Velocity = velocity;
MoveAndSlide();
}
}
5. ゲームループの基礎(きそ)
while (gameRunning)
{
ProcessInput();
Update(deltaTime);
Render();
SyncFrameRate();
}
5.1 Fixed vs Variable Timestep
public class Player : MonoBehaviour
{
void Update()
{
ProcessInput();
}
void FixedUpdate()
{
ApplyPhysics();
}
}
6. 物理(ぶつり)エンジン
6.1 PhysX vs Chaos vs Bullet vs Box2D
| エンジン | 使用先(しようさき) | 特徴 |
|---|---|---|
| PhysX | Unity, 旧Unreal | 安定、GPU加速 |
| Chaos | Unreal Engine 5+ | Epic自社製、破壊シミュレーション |
| Bullet | Blender, Godot一部 | オープンソース |
| Box2D | 2Dゲーム | 軽量、正確 |
public class BallController : MonoBehaviour
{
private Rigidbody rb;
public float bounciness = 0.8f;
void Start()
{
rb = GetComponent<Rigidbody>();
var material = new PhysicMaterial
{
bounciness = bounciness,
dynamicFriction = 0.6f,
staticFriction = 0.6f
};
GetComponent<Collider>().material = material;
}
void OnCollisionEnter(Collision collision)
{
Debug.Log($"Hit: {collision.gameObject.name}");
}
}
7. マルチプレイヤーアーキテクチャ
7.1 ネットワークモデル比較
| モデル | 長所(ちょうしょ) | 短所(たんしょ) | 適(てき)するゲーム |
|---|---|---|---|
| P2P | サーバー費用ゼロ | NAT問題、チート | 協力(きょうりょく)インディー |
| Client-Server | 権威的、安定 | サーバー費用 | 競争(きょうそう)マルチ |
| Dedicated Server | 最高の安定性 | 最高(さいこう)に高価(こうか) | AAA FPS、MOBA |
| Listen Server | ホストがサーバー | ホスト退出(たいしゅつ)で終了 | カジュアル協力 |
7.2 Unity Netcode for GameObjects
using Unity.Netcode;
using UnityEngine;
public class NetworkPlayer : NetworkBehaviour
{
[SerializeField] private float moveSpeed = 5f;
private NetworkVariable<int> health = new NetworkVariable<int>(100,
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Server);
public override void OnNetworkSpawn()
{
if (IsOwner)
{
Camera.main.GetComponent<CameraFollow>().target = transform;
}
health.OnValueChanged += OnHealthChanged;
}
void Update()
{
if (!IsOwner) return;
Vector3 input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
if (input.magnitude > 0.1f)
{
MoveServerRpc(input * moveSpeed * Time.deltaTime);
}
if (Input.GetKeyDown(KeyCode.Space))
{
ShootServerRpc();
}
}
[ServerRpc]
void MoveServerRpc(Vector3 movement)
{
transform.position += movement;
}
[ServerRpc]
void ShootServerRpc()
{
var bullet = Instantiate(bulletPrefab, transform.position, transform.rotation);
bullet.GetComponent<NetworkObject>().Spawn();
}
[ClientRpc]
void TakeDamageClientRpc(int damage)
{
if (IsOwner)
{
ShowDamageUI(damage);
}
}
void OnHealthChanged(int previous, int current)
{
UpdateHealthBar(current);
}
}
7.3 Mirror Networking
using Mirror;
using UnityEngine;
public class MirrorPlayer : NetworkBehaviour
{
[SyncVar(hook = nameof(OnHealthChanged))]
public int health = 100;
void OnHealthChanged(int oldHealth, int newHealth)
{
Debug.Log($"Health: {oldHealth} to {newHealth}");
}
void Update()
{
if (!isLocalPlayer) return;
if (Input.GetKeyDown(KeyCode.Space))
{
CmdShoot();
}
}
[Command]
void CmdShoot()
{
RpcPlayShootEffect();
}
[ClientRpc]
void RpcPlayShootEffect()
{
Instantiate(muzzleFlash, transform.position, transform.rotation);
}
}
7.4 Photon vs Steamworks
- Photon: クラウドベース、使いやすい、部分(ぶぶん)無料
- Steamworks: Steam P2P、フレンド統合、Steamゲームの標準
8. 性能最適化
8.1 Draw Call最適化
public class StaticOptimizer : MonoBehaviour
{
void Start()
{
StaticBatchingUtility.Combine(gameObject);
}
}
public class InstancedRenderer : MonoBehaviour
{
public Mesh mesh;
public Material material;
public int count = 10000;
private Matrix4x4[] matrices;
void Start()
{
matrices = new Matrix4x4[count];
for (int i = 0; i < count; i++)
{
matrices[i] = Matrix4x4.TRS(
Random.insideUnitSphere * 100,
Quaternion.identity,
Vector3.one
);
}
}
void Update()
{
Graphics.DrawMeshInstanced(mesh, 0, material, matrices, count);
}
}
8.2 LOD
public class LODSetup : MonoBehaviour
{
void Start()
{
LODGroup group = gameObject.AddComponent<LODGroup>();
LOD[] lods = new LOD[3];
lods[0] = new LOD(0.6f, GetRenderers(0));
lods[1] = new LOD(0.3f, GetRenderers(1));
lods[2] = new LOD(0.1f, GetRenderers(2));
group.SetLODs(lods);
group.RecalculateBounds();
}
Renderer[] GetRenderers(int level)
{
return new Renderer[] { transform.GetChild(level).GetComponent<Renderer>() };
}
}
8.3 Occlusion Culling
壁(かべ)の後(うし)ろの見(み)えないオブジェクトを描画(びょうが)しない。Unityは自動ベイク、UnrealはVisibility Systemを使用。
8.4 テクスチャ最適化
| 形式(けいしき) | モバイル | PC | コンソール |
|---|---|---|---|
| ASTC | iOS、最新Android | 部分 | 部分 |
| ETC2 | Android | 非対応 | 非対応 |
| BC7 | 非対応 | PC標準 | PS5、Xbox |
9. アセットパイプライン
9.1 モデルインポートのベストプラクティス
- ポリゴン数: キャラクター5k-50k、環境1k-10k
- テクスチャ: 2のべき乗(512、1024、2048)
- UV: 単一(たんいつ)チャネル、0-1範囲(はんい)内
- ボーン: キャラクター50個以下(モバイル30個以下)
9.2 アニメーション
- Unity: Animator State Machine、Animation Rigging
- Unreal: Animation Blueprint、Control Rig、Live Link
- Godot: AnimationPlayer、AnimationTree
10. オーディオ: FMOD vs Wwise
| 項目 | FMOD | Wwise |
|---|---|---|
| 価格 | インディー無料($150k以下) | インディー無料($200k以下) |
| 統合(とうごう) | Unity、Unreal対応 | Unity、Unreal対応 |
| UI | シンプル | 複雑(ふくざつ)、強力 |
| 用途 | インディー、中規模 | AAA |
11. プラットフォーム配信(はいしん)
11.1 モバイル (iOS / Android)
- iOS: Xcodeビルド、App Store Connect、IDFA準拠(じゅんきょ)
- Android: Google Play Console、App Bundle (.aab) 必須
11.2 PC (Steam / Epic / GOG)
- Steam: Steamworks SDK、Steam Pipe、Workshop
- Epic: Epic Online Services、Epic Games Store
11.3 コンソール (PS5 / Xbox / Switch)
- 開発者(かいはつしゃ)登録(とうろく)必須
- TRC/XR/Lotcheck認証(にんしょう)通過必要
- ビルドにはdev kitが必要
12. インディー vs AAAワークフロー
| 項目 | インディー | AAA |
|---|---|---|
| エンジン | Godot, Unity, Unreal | Unreal、自社製 |
| ワークフロー | 多才(たさい)、迅速(じんそく)反復(はんぷく) | 分業(ぶんぎょう)、専門化(せんもんか) |
| アセット | Asset Store、外注(がいちゅう) | 社内(しゃない)制作 |
| マーケティング | SNS、インフルエンサー | TV、トレーラー、イベント |
13. クイズ
Q1. ECSの核心(かくしん)的な利点(りてん)は?
A1. データ指向設計でキャッシュ効率を最大化(さいだいか)。コンポーネントがメモリに連続(れんぞく)配置(はいち)され、SIMDとマルチスレッドが効果的(こうかてき)。数万から数十万のエンティティを60fpsで処理可能。
Q2. Unreal Engine 5のLumenとNaniteの違い(ちがい)は?
A2. Lumenは動的グローバルイルミネーションシステムでリアルタイム間接照明と反射を処理。Naniteは仮想化ジオメトリシステムで数十億ポリゴンメッシュを自動LOD処理。Lumenは光、Naniteはメッシュ。
Q3. Draw Callが多(おお)いとなぜ性能が低下(ていか)するか?
A3. 各draw callはCPUからGPUへの命令(めいれい)送信(そうしん)オーバーヘッドがある。多すぎるとCPUバウンドになりGPUが遊(あそ)ぶ。バッチング、インスタンシング、テクスチャアトラスで削減(さくげん)する必要がある。
Q4. Server-authoritativeモデルの利点は?
A4. サーバーが全権威(ぜんけんい)を持(も)つため、クライアントのメモリ改変(かいへん)がゲーム状態に影響(えいきょう)を与(あた)えない。チート防止(ぼうし)に強いが遅延(ちえん)が増加(ぞうか)するためclient-side predictionが必要。
Q5. Static batchingとdynamic batchingの違いは?
A5. Static batchingはビルド時または開始時に動かないオブジェクトを単一(たんいつ)メッシュに統合(とうごう)。メモリは多く使うが実行(じっこう)時コストはゼロ。Dynamic batchingは毎フレーム小さな動的オブジェクトを統合する仕組(しく)みでCPUコストがある。
14. 参考資料
- Unity Documentation: https://docs.unity3d.com
- Unity DOTS: https://unity.com/dots
- Unity Learn: https://learn.unity.com
- Unreal Engine 5 Documentation: https://docs.unrealengine.com
- Unreal Engine - Lumen Technical Details: https://docs.unrealengine.com/5.3/en-US/lumen-global-illumination-and-reflections-in-unreal-engine
- Unreal Engine - Nanite Virtualized Geometry: https://docs.unrealengine.com/5.3/en-US/nanite-virtualized-geometry-in-unreal-engine
- Godot Documentation: https://docs.godotengine.org
- Godot 4 Tutorials: https://godotengine.org/learn
- Mirror Networking: https://mirror-networking.com
- Photon Engine: https://www.photonengine.com
- Game Programming Patterns: https://gameprogrammingpatterns.com
- GDC Vault: https://www.gdcvault.com
- Brackeys YouTube: https://www.youtube.com/@Brackeys
- Sebastian Lague YouTube: https://www.youtube.com/@SebastianLague
15. おわりに
ゲーム開発は技術と芸術(げいじゅつ)が出会(であ)う領域(りょういき)である。どのエンジンを選んでも、核心は**「プレイヤーが楽(たの)しい体験(たいけん)」**を作ることにある。Unityは多才(たさい)さと大きなコミュニティで依然インディーの標準であり、Unreal Engine 5は視覚的忠実度の新しい基準(きじゅん)を確立(かくりつ)し、Godot 4はオープンソース精神(せいしん)と軽量さで急速に成長している。
エンジンは道具(どうぐ)に過ぎない。ゲームデザイン、ゲームプレイループ、プレイヤー心理(しんり)の理解(りかい)がより重要である。小さなプロジェクトから始(はじ)めて、リリースまで完成(かんせい)する経験(けいけん)を積(つ)むことが最大の資産(しさん)である。
현재 단락 (1/484)
2026年のゲーム開発はかつてないほど**選択肢(せんたくし)が豊富(ほうふ)**である。Unityはインディーモバイルと中級(ちゅうきゅう)PCで依然(いぜん)強(つよ)く、Unreal Engin...