ゲーム開発でプレイヤーを追いかけるカメラを実装しようとすると、様々な計算が必要になります。
「カメラをどうやってプレイヤーに追従させるの?」
「オフセットってどう計算するの?」
「壁を通り抜けないようにするには?」
そんな疑問を抱えている方に向けて、カメラ追従の計算方法について、初心者でも理解できるように解説します。
\読むだけで終わらせない!実際にゲームを作って実力をつけよう/
トレンド×入門に最適
Unity ノンフィールドRPG
+スレスパ風JRPG講座
Unity6対応・スマホ化対応の最新カリキュラム。今もっとも人気のデッキ構築型ゲームをJRPGと組み合わせて実装。初心者が最初に選ぶ一本として最適です。
王道アクションに挑戦
Unity 2Dアクションゲーム
の作り方講座(ロックマン風)
ロックマン風の本格横スクロールACTをスマホ化・広告実装まで対応。7ステージ+ラスボスという市販ゲームに近い本格構成で、リリースまで見据えて作れます。
3D入門に最適
ゼルダ風3Dアクションゲーム
の作り方講座
ゼルダの伝説・モンハン・原神のような3Dアクションをスマホ対応で作れる入門講座。初心者でも全16回でしっかり3D開発の基礎を習得できます。
あなたのオリジナルゲーム、今年こそ完成させませんか?
RPG・アクション・ホラー…Unityで本格ゲームを作りたい人のための学習サイトです。
実際に完成するゲームを題材に、
ソースコード・素材・プロジェクト一式をすべて公開。
仕事や学校の合間の1〜2時間でも、
「写経→改造」で自分のゲームまで作りきれる環境です。
カメラ追従とは何か
カメラ追従とは、プレイヤーやオブジェクトの動きに合わせて、カメラが自動的に移動する技術です。
ゲームでは、プレイヤーが常に画面の中心にいるように、カメラが追いかける仕組みが必要になります。
単純にカメラの位置をプレイヤーの位置に設定するだけでは、カメラがプレイヤーと重なってしまうため、適切な距離と角度を保つ計算が必要なんです。
カメラ追従の基本概念
カメラ追従を実現するには、以下の要素が必要になります。
- 目標位置:カメラが向かうべき位置
- オフセット:目標位置からの相対的な位置
- 補間:滑らかな移動を実現する計算
- 制約:壁との衝突や範囲制限
カメラ追従の種類
ゲームで使われる主なカメラ追従には、以下のようなものがあります。
- 直接追従:カメラの位置を直接目標位置に設定
- 滑らかな追従:補間を使って滑らかに追従
- 予測追従:プレイヤーの動きを予測して追従
- 範囲制限付き追従:カメラの移動範囲を制限
- プレイヤーやオブジェクトを追いかける技術
- 適切な距離と角度を保つ計算が必要
- 補間を使うことで滑らかな動きを実現
- 壁との衝突などを考慮した制約が重要
基本的な追従の計算
最もシンプルなカメラ追従の実装から見ていきましょう。
直接追従
カメラの位置を目標位置に直接設定する方法です。
|
1 2 3 4 5 6 7 8 9 10 |
public Transform target; // 追従対象 void Update() { if (target != null) { transform.position = target.position; } } |
ただし、この方法だとカメラがプレイヤーと完全に重なってしまい、何も見えなくなります。
オフセットを使った追従
オフセット(相対位置)を設定することで、カメラとプレイヤーの間に適切な距離を保てます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public Transform target; public Vector3 offset = new Vector3(0, 5, -10); // カメラの相対位置 void Update() { if (target != null) { // 目標位置 = 対象の位置 + オフセット Vector3 targetPosition = target.position + offset; transform.position = targetPosition; // 対象を見る transform.LookAt(target); } } |
目標位置 = 対象の位置 + オフセットという計算式が基本になります。
オフセットの計算方法
オフセットを計算するには、カメラと対象の初期位置の差を求めます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
void Start() { if (target != null) { // 初期位置の差を計算してオフセットとする offset = transform.position - target.position; } } void Update() { if (target != null) { transform.position = target.position + offset; transform.LookAt(target); } } |
これにより、シーンの初期配置から自動的にオフセットを計算できます。
滑らかな追従の計算
直接追従だとカメラの動きがカクつくため、補間を使って滑らかに追従させる方法を見ていきましょう。
Lerpを使った滑らかな追従
Vector3.Lerpを使って、カメラの位置を滑らかに補間します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public Transform target; public Vector3 offset = new Vector3(0, 5, -10); public float smoothSpeed = 5.0f; // 追従速度 void LateUpdate() { if (target == null) return; // 目標位置を計算 Vector3 desiredPosition = target.position + offset; // 滑らかに移動 transform.position = Vector3.Lerp( transform.position, desiredPosition, smoothSpeed * Time.deltaTime ); // 対象を見る transform.LookAt(target); } |
LateUpdateを使うことで、プレイヤーの移動後にカメラを更新できます。
距離ベースの追従速度
カメラと目標位置の距離に応じて、追従速度を調整することもできます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public float minSmoothSpeed = 3.0f; public float maxSmoothSpeed = 10.0f; public float maxDistance = 20.0f; void LateUpdate() { if (target == null) return; Vector3 desiredPosition = target.position + offset; float distance = Vector3.Distance(transform.position, desiredPosition); // 距離に応じて速度を調整 float normalizedDistance = Mathf.Clamp01(distance / maxDistance); float currentSmoothSpeed = Mathf.Lerp(minSmoothSpeed, maxSmoothSpeed, normalizedDistance); transform.position = Vector3.Lerp( transform.position, desiredPosition, currentSmoothSpeed * Time.deltaTime ); transform.LookAt(target); } |
距離が遠いほど速く追従し、近いほどゆっくり追従するようになります。
予測追従の計算
プレイヤーの速度を考慮して、将来の位置を予測して追従することもできます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
public Transform target; public Vector3 offset = new Vector3(0, 5, -10); public float smoothSpeed = 5.0f; public float predictionAmount = 0.5f; // 予測の強度 private Vector3 previousTargetPosition; private Vector3 targetVelocity; void LateUpdate() { if (target == null) return; // 速度を計算 targetVelocity = (target.position - previousTargetPosition) / Time.deltaTime; previousTargetPosition = target.position; // 予測位置を計算 Vector3 predictedPosition = target.position + targetVelocity * predictionAmount; // 予測位置を基準に目標位置を計算 Vector3 desiredPosition = predictedPosition + offset; // 滑らかに移動 transform.position = Vector3.Lerp( transform.position, desiredPosition, smoothSpeed * Time.deltaTime ); transform.LookAt(predictedPosition); } |
これにより、カメラがプレイヤーの動きを先読みして追従できるようになります。
オフセットの計算と調整
カメラ追従では、オフセットの計算と調整が重要になります。
ローカル座標系でのオフセット
対象のローカル座標系(向きを基準)でオフセットを計算することで、対象が回転しても適切な位置を保てます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public Transform target; public Vector3 localOffset = new Vector3(0, 5, -10); // ローカル座標でのオフセット void LateUpdate() { if (target == null) return; // ローカル座標系でのオフセットをワールド座標に変換 Vector3 worldOffset = target.TransformDirection(localOffset); Vector3 desiredPosition = target.position + worldOffset; transform.position = Vector3.Lerp( transform.position, desiredPosition, smoothSpeed * Time.deltaTime ); transform.LookAt(target); } |
Transform.TransformDirectionを使って、ローカル座標をワールド座標に変換できます。
高さのオフセット調整
カメラの高さを、プレイヤーの状態に応じて動的に調整することもできます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public float baseHeight = 5.0f; // 基本の高さ public float crouchHeightOffset = -2.0f; // しゃがみ時の高さオフセット void LateUpdate() { if (target == null) return; // プレイヤーの状態に応じて高さを調整 bool isCrouching = /* プレイヤーのしゃがみ状態を取得 */; float currentHeight = baseHeight + (isCrouching ? crouchHeightOffset : 0); Vector3 offset = new Vector3(0, currentHeight, -10); Vector3 desiredPosition = target.position + offset; transform.position = Vector3.Lerp( transform.position, desiredPosition, smoothSpeed * Time.deltaTime ); transform.LookAt(target); } |
これにより、プレイヤーがしゃがんだ時など、状況に応じてカメラの高さを調整できます。
オフセットの補間
オフセット自体も滑らかに変化させることができます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
public Vector3 targetOffset = new Vector3(0, 5, -10); public float offsetSmoothSpeed = 2.0f; private Vector3 currentOffset; void LateUpdate() { if (target == null) return; // オフセットを滑らかに変化 currentOffset = Vector3.Lerp( currentOffset, targetOffset, offsetSmoothSpeed * Time.deltaTime ); Vector3 desiredPosition = target.position + currentOffset; transform.position = Vector3.Lerp( transform.position, desiredPosition, smoothSpeed * Time.deltaTime ); transform.LookAt(target); } |
これにより、オフセットの変更も滑らかになります。
壁を通り抜けない追従
カメラが壁を通り抜けてしまうのを防ぐ実装方法を見ていきましょう。
レイキャストによる衝突検出
Physics.Raycastを使って、カメラと対象の間に壁があるかを検出します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public Transform target; public Vector3 offset = new Vector3(0, 5, -10); public float smoothSpeed = 5.0f; public LayerMask wallLayer; // 壁のレイヤー public float minDistance = 2.0f; // 最小距離 void LateUpdate() { if (target == null) return; Vector3 desiredPosition = target.position + offset; Vector3 direction = desiredPosition - target.position; float distance = direction.magnitude; RaycastHit hit; if (Physics.Raycast(target.position, direction.normalized, out hit, distance, wallLayer)) { // 壁にぶつかった場合は、壁の手前に配置 desiredPosition = hit.point - direction.normalized * minDistance; } transform.position = Vector3.Lerp( transform.position, desiredPosition, smoothSpeed * Time.deltaTime ); transform.LookAt(target); } |
これにより、カメラが壁を通り抜けることを防げます。
SphereCastを使った衝突検出
カメラのサイズを考慮する場合は、Physics.SphereCastを使います。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public float cameraRadius = 0.5f; // カメラの半径 void LateUpdate() { if (target == null) return; Vector3 desiredPosition = target.position + offset; Vector3 direction = desiredPosition - target.position; float distance = direction.magnitude; RaycastHit hit; if (Physics.SphereCast(target.position, cameraRadius, direction.normalized, out hit, distance, wallLayer)) { // カメラの半径を考慮して配置 desiredPosition = hit.point - direction.normalized * (minDistance + cameraRadius); } transform.position = Vector3.Lerp( transform.position, desiredPosition, smoothSpeed * Time.deltaTime ); transform.LookAt(target); } |
これにより、カメラのサイズを考慮した衝突検出が可能になります。
Unityでの実装例(C#コード)
Unityでカメラ追従を実装する具体的な例を見ていきましょう。
高度な追従カメラクラス
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
using UnityEngine; public class AdvancedFollowCamera : MonoBehaviour { [Header("追従設定")] public Transform target; public Vector3 offset = new Vector3(0, 5, -10); public float smoothSpeed = 5.0f; [Header("予測追従")] public bool usePrediction = false; public float predictionAmount = 0.5f; [Header("距離ベースの速度調整")] public bool useDistanceBasedSpeed = false; public float minSmoothSpeed = 3.0f; public float maxSmoothSpeed = 10.0f; public float maxDistance = 20.0f; [Header("壁との衝突")] public bool checkWallCollision = true; public LayerMask wallLayer; public float minDistance = 2.0f; public float cameraRadius = 0.5f; [Header("ローカル座標オフセット")] public bool useLocalOffset = false; public Vector3 localOffset = new Vector3(0, 5, -10); private Vector3 previousTargetPosition; private Vector3 targetVelocity; private Vector3 currentOffset; void Start() { if (target != null) { previousTargetPosition = target.position; if (!useLocalOffset) { currentOffset = offset; } else { currentOffset = localOffset; } } } void LateUpdate() { if (target == null) return; // 速度を計算(予測追従用) if (usePrediction) { targetVelocity = (target.position - previousTargetPosition) / Time.deltaTime; previousTargetPosition = target.position; } // 目標位置を計算 Vector3 targetPosition = target.position; if (usePrediction) { targetPosition += targetVelocity * predictionAmount; } // オフセットを計算 Vector3 calculatedOffset; if (useLocalOffset) { calculatedOffset = target.TransformDirection(localOffset); } else { calculatedOffset = offset; } Vector3 desiredPosition = targetPosition + calculatedOffset; // 壁との衝突をチェック if (checkWallCollision) { Vector3 direction = desiredPosition - targetPosition; float distance = direction.magnitude; RaycastHit hit; if (Physics.SphereCast(targetPosition, cameraRadius, direction.normalized, out hit, distance, wallLayer)) { desiredPosition = hit.point - direction.normalized * (minDistance + cameraRadius); } } // 距離ベースの速度調整 float currentSmoothSpeed = smoothSpeed; if (useDistanceBasedSpeed) { float distance = Vector3.Distance(transform.position, desiredPosition); float normalizedDistance = Mathf.Clamp01(distance / maxDistance); currentSmoothSpeed = Mathf.Lerp(minSmoothSpeed, maxSmoothSpeed, normalizedDistance); } // 滑らかに移動 transform.position = Vector3.Lerp( transform.position, desiredPosition, currentSmoothSpeed * Time.deltaTime ); // 対象を見る if (usePrediction) { transform.LookAt(targetPosition); } else { transform.LookAt(target); } } } |
このクラスでは、様々なオプションを組み合わせて、柔軟なカメラ追従が可能になります。
- LateUpdateを使うことで、プレイヤーの移動後にカメラを更新できる
- Time.deltaTimeを掛けることで、フレームレートに依存しない補間になる
- 壁の衝突チェックは、計算コストがかかるため必要に応じて有効化する
- 予測追従は、プレイヤーの動きが予測可能な場合に有効
カメラ追従の実装手順
※この順番を守らずに作り始めると、だいたい後で全部作り直すことになります。
- STEP1基本的な追従を実装
オフセットを使った基本的な追従カメラを実装します。目標位置 = 対象の位置 + オフセットの計算を実装しましょう。
- STEP2滑らかな追従の追加
Lerpを使って、滑らかな追従を追加します。LateUpdateを使い、Time.deltaTimeを掛けて補間しましょう。
- STEP3オフセットの調整
必要に応じて、ローカル座標系でのオフセットや動的なオフセット調整を実装します。 - STEP4壁との衝突検出
レイキャストやSphereCastを使って、壁との衝突を検出します。衝突時は、適切な位置にカメラを配置しましょう。
- STEP5最適化と調整
パラメータを調整して、快適なカメラ追従を実現します。予測追従や距離ベースの速度調整などを追加してもよいでしょう。
よくある問題と解決方法
カメラ追従を実装する際によくある問題と、その解決方法を紹介します。
カメラがプレイヤーと重なる
オフセットを設定していない、またはオフセットが0になっている可能性があります。
|
1 2 3 4 5 6 7 |
// ✅ 正しい実装 public Vector3 offset = new Vector3(0, 5, -10); Vector3 desiredPosition = target.position + offset; // ❌ 間違った実装 transform.position = target.position; // 重なってしまう |
カメラがカクつく
UpdateではなくLateUpdateを使い、Time.deltaTimeを掛ける必要があります。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// ✅ 正しい実装 void LateUpdate() { transform.position = Vector3.Lerp( transform.position, desiredPosition, smoothSpeed * Time.deltaTime // Time.deltaTimeを掛ける ); } // ❌ 間違った実装 void Update() { transform.position = Vector3.Lerp( transform.position, desiredPosition, smoothSpeed // Time.deltaTimeがないとカクつく ); } |
対象が回転するとオフセットがずれる
ローカル座標系でのオフセットを使うか、オフセットを回転させます。
|
1 2 3 4 5 6 |
// ✅ ローカル座標系でのオフセット Vector3 worldOffset = target.TransformDirection(localOffset); // または、オフセットを回転 Vector3 rotatedOffset = target.rotation * offset; |
壁を通り抜ける
レイキャストやSphereCastで衝突を検出し、適切な位置に配置します。
|
1 2 3 4 5 6 |
RaycastHit hit; if (Physics.Raycast(target.position, direction.normalized, out hit, distance, wallLayer)) { desiredPosition = hit.point - direction.normalized * minDistance; } |
- カメラが重なる → オフセットを設定する
- カメラがカクつく → LateUpdateを使い、Time.deltaTimeを掛ける
- オフセットがずれる → ローカル座標系でのオフセットを使う
- 壁を通り抜ける → レイキャストで衝突を検出する
カメラ追従の学習を深めるには
カメラ追従の基礎を理解した後は、さらに深く学んでいくことが大切です。
Unity入門の森では、ゲーム開発に必要な知識を体系的に学べる環境が整っています。
特に、FPSゲーム講座(弓矢3D)では、カメラ制御の実践的な使い方を学べます。
また、永久会員チケットでは、ゲーム開発全般に関する知識を幅広くカバーしているため、カメラ追従以外にも応用できる知識が身につきます。
カメラ追従の基礎から応用まで、実際のコードと紐付けて学べるので、理解が深まりやすいはずです。
- カメラ追従の基本的な概念と計算方法
- オフセットを使った追従の実装
- 滑らかな追従と予測追従の計算
- 壁を通り抜けない追従の実装
- Unityでの実装例(C#コード)
記事を読んで「作ってみたい!」と思ったら!人気ゲームを題材にした講座で実力をつけよう
知識を読むだけで終わらせるのはもったいない。実際に手を動かしてゲームを1本完成させることで、理解が一気に深まります。人気タイトルをモデルにした講座で、ゲーム開発の第一歩を踏み出しましょう。
Unity ノンフィールドRPG+スレスパ風JRPG講座【Unity6対応!トレンドのデッキ構築×JRPGをスマホ向けに作れる!】

- Unity6対応・スマホ化対応で最新環境のゲーム開発が学べる
- Slay the Spire風のデッキ構築システム×JRPGの組み合わせを実装
- 初心者でも取り組みやすい丁寧な解説構成
- ノンフィールドRPGとデッキ構築JRPGの2つを合わせて学ぶのがおすすめ
Unity ノンフィールドRPGの作り方講座+Slay the Spire風デッキ構築JRPGの作り方講座は、今もっともトレンドのデッキ構築型ゲームシステムをJRPGと組み合わせて実装する方法を学べる講座です。
Unity6対応・スマホ化対応の最新カリキュラムで、コラムやTIPSで読んで「なるほど」と思った知識を、実際に動くゲームとして形にする体験ができます。
「Slay the Spireみたいなゲームを自分でも作ってみたい!」という人の最初の一歩として最適な講座です。
Unity6対応・スマホ化対応の最新カリキュラム
トレンドのデッキ構築×JRPGを最速で実装しよう
→ スレスパ風デッキ構築JRPG講座を見てみる
スマホ対応の最新環境で、ゲーム開発の第一歩を踏み出そう!
Unity 2Dアクションゲームの作り方講座(ロックマン風)【全16回!スマホ化・広告実装まで対応した本格横スクロールACTを作れる!】

- ロックマン・マリオ・カービィのような横スクロールACTをゼロから開発
- 7ステージ+ラスボスステージの市販ゲームに近い本格的なゲーム設計
- スマホ化・AdMob広告実装まで対応してリリースまで見据えた構成
- 敵AI15体・多彩なマップギミック・武器システムを完全実装
- 完全オリジナルゲームをアセット不使用で素材提供付きで制作
Unity 2Dアクションゲームの作り方講座(ロックマン風)は、ロックマン・スーパーマリオ・星のカービィのような2D横スクロールアクションゲームを開発できるようになる本格的な講座です。
TIPSやコラムで学んだ当たり判定・物理挙動・敵AIの知識を、実際のゲームコードとして実装する体験が全16回に凝縮されています。スマホ化・広告実装まで対応しているため、作って終わりではなくリリースまで見据えた実践スキルが身につきます。
「読んで理解した知識を、動くゲームとして形にしたい」という人に強くおすすめの一本です。
スマホ化・広告実装まで対応した本格横スクロールACT
ロックマン風の2Dアクションゲームをリリースまで作り上げよう
→ 2Dアクションゲームの作り方講座を見てみる
広告収益まで視野に入れた実践スキルを今すぐ手に入れよう!
ゼルダ風3Dアクションゲームの作り方講座【全16回!初心者でも3Dアクションがスマホ対応で作れる!】

- ゼルダの伝説・モンハン・原神のような3Dアクションをゼロから開発
- 初心者でも取り組みやすい丁寧な解説構成
- スマホ化対応で実機で動かせるゲームが完成
- アセットを使った実践的なゲーム開発手法が身につく
- 画像・動画・全ソースコード公開の充実したサポート
ゼルダ風3Dアクションゲームの作り方講座は、ゼルダの伝説・モンハン・原神のような本格的な3Dアクションゲームを作りたい人におすすめの入門講座です。
コラム・TIPSで「3Dゲームはなんとなく難しそう」と感じていた人でも、全16回の丁寧な解説で確実に完成まで到達できます。スマホ化対応で実機で動かせるため、作った達成感がひときわ大きい講座です。
「3Dゲームの仕組みを理解した次は、実際に自分で作ってみたい」という人の最初の一歩として最適です。
初心者でも3Dアクションがスマホ対応で完成する
ゼルダ風3Dアクションゲームで3D開発の第一歩を踏み出そう
→ ゼルダ風3Dアクションゲームの作り方講座を見てみる
3D開発の壁を一気に突破!スマホで動くオリジナルゲームを完成させよう!
まとめ

この記事では、カメラ追従の計算方法について解説しました。
カメラ追従は、目標位置 = 対象の位置 + オフセットという基本的な計算式から始まります。
補間を使うことで滑らかな動きを実現し、レイキャストで壁との衝突を検出することで、自然なカメラ追従が可能になります。
「カメラ追従って難しそう💧」と感じる方もいるかもしれませんが、基本的な計算式を理解すれば実装できます。
まずはシンプルなオフセットを使った追従から始めて、徐々に高度な機能に挑戦していきましょう。
- カメラ追従は、目標位置 = 対象の位置 + オフセットが基本
- LateUpdateとTime.deltaTimeを使って、滑らかな追従を実現
- ローカル座標系でのオフセットを使うと、回転にも対応できる
- レイキャストで壁との衝突を検出し、適切な位置に配置する
- 予測追従や距離ベースの速度調整で、より自然な動きを実現できる
まずは基本的な実装から始めて、徐々に応用的な機能に挑戦していきましょう。
Unity入門の森では、カメラ追従の基礎から応用まで、実践的な知識を体系的に学べる環境が整っています。
疑問があれば、ぜひ活用してみてください。
あなたのオリジナルゲーム、今年こそ完成させませんか?
RPG・アクション・ホラー…Unityで本格ゲームを作りたい人のための学習サイトです。
実際に完成するゲームを題材に、
ソースコード・素材・プロジェクト一式をすべて公開。
仕事や学校の合間の1〜2時間でも、
「写経→改造」で自分のゲームまで作りきれる環境です。





コメント