Unity
表示
イントロダクション
[編集]Unity は、直感的な操作性と強力な機能を兼ね備えたクロスプラットフォームのゲーム開発エンジンです。2D・3Dゲームの開発はもちろん、AR(拡張現実)やVR(仮想現実)のアプリケーション開発まで幅広く対応しています。
インストールとセットアップ
[編集]- Unity Hubをダウンロードしてインストール
- Unity Hubを起動し、「インストール」タブから適切なUnityバージョンを選択
- 通常は最新のLTS(Long Term Support)バージョンを推奨
- プロジェクトの要件に応じて特定のバージョンを選択
- 必要なビルドサポート(iOS、Android等)を選択してインストール
エディタの基本構成
[編集]Unity エディタは以下の主要なウィンドウで構成されています:
- シーンビュー:3D空間でゲームオブジェクトを視覚的に配置・編集
- ゲームビュー:実際のゲーム画面をプレビュー
- ヒエラルキーウィンドウ:シーン内のオブジェクトを階層構造で管理
- プロジェクトウィンドウ:アセット(素材)の管理
- インスペクター:選択したオブジェクトのプロパティを詳細に設定
基本操作
[編集]シーン編集の基本
[編集]- オブジェクトの操作
- 移動(W):位置の調整
- 回転(E):向きの変更
- スケール(R):大きさの調整
- 複数の軸を同時に操作する場合は、ギズモの中心をドラッグ
- カメラ操作
- 右クリック+ドラッグ:視点回転
- 右クリック+WASD:視点移動
- マウスホイール:ズームイン/アウト
プレハブシステム
[編集]プレハブ(Prefab)は再利用可能なゲームオブジェクトのテンプレートです。
- プレハブの作成:ヒエラルキーからプロジェクトウィンドウにオブジェクトをドラッグ
- プレハブの配置:プロジェクトウィンドウからシーンにドラッグ
- プレハブの編集:
- 個別のインスタンス編集
- プレハブアセットの直接編集(変更は全インスタンスに反映)
プログラミング基礎
[編集]スクリプティングの基本
[編集]using UnityEngine; public class PlayerController : MonoBehaviour { // インスペクターで設定可能な変数 public float moveSpeed = 5.0f; public float jumpForce = 10.0f; private Rigidbody rb; void Start() { // コンポーネントの取得 rb = GetComponent<Rigidbody>(); } void Update() { // 入力処理 float horizontalInput = Input.GetAxis("Horizontal"); float verticalInput = Input.GetAxis("Vertical"); // 移動処理 Vector3 movement = new Vector3(horizontalInput, 0, verticalInput); transform.Translate(movement * moveSpeed * Time.deltaTime); // ジャンプ処理 if (Input.GetKeyDown(KeyCode.Space)) { rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse); } } }
重要なライフサイクルメソッド
[編集]Awake(): スクリプトのインスタンス化時に一度だけ呼ばれるStart(): 最初のフレーム更新の前に呼ばれるUpdate(): 毎フレーム呼ばれるFixedUpdate(): 物理演算の更新時に呼ばれる(一定時間間隔)LateUpdate(): 全ての Update 処理の後に呼ばれる
物理演算システム
[編集]基本コンポーネント
[編集]- Rigidbody: 物理演算を適用
- 質量、抗力、角度抗力などのプロパティを設定可能
UseGravityで重力の影響を制御
- Collider: 衝突判定用の形状を定義
- Box Collider: 直方体
- Sphere Collider: 球体
- Capsule Collider: カプセル形状
- Mesh Collider: メッシュに沿った形状
衝突判定
[編集]void OnCollisionEnter(Collision collision) { // 衝突開始時の処理 } void OnCollisionStay(Collision collision) { // 衝突中の処理 } void OnCollisionExit(Collision collision) { // 衝突終了時の処理 } void OnTriggerEnter(Collider other) { // トリガー領域進入時の処理 }
アニメーションシステム
[編集]Animator の基本設定
[編集]- アニメーターコンポーネントの追加
- アニメーターコントローラーの作成
- アニメーションクリップの作成・設定
- ステート遷移の設定
スクリプトからのアニメーション制御
[編集]private Animator animator; void Start() { animator = GetComponent<Animator>(); } void Update() { // パラメータの設定 animator.SetBool("IsRunning", Input.GetKey(KeyCode.W)); animator.SetTrigger("Jump"); }
UI システム
[編集]Canvas の基本
[編集]- Screen Space - Overlay: 画面に直接描画
- Screen Space - Camera: カメラからの距離を考慮
- World Space: 3D空間内に配置
レスポンシブ UI の実装
[編集]- Anchor Presets の活用
- Layout Group の使用
- Rect Transform の適切な設定
パフォーマンス最適化
[編集]オブジェクトプーリング
[編集]public class ObjectPool : MonoBehaviour { public GameObject prefab; public int poolSize = 20; private List<GameObject> pool; void Start() { pool = new List<GameObject>(); for (int i = 0; i < poolSize; i++) { GameObject obj = Instantiate(prefab); obj.SetActive(false); pool.Add(obj); } } public GameObject GetPooledObject() { foreach (GameObject obj in pool) { if (!obj.activeInHierarchy) { return obj; } } return null; } }
メモリ最適化のベストプラクティス
[編集]- シーン切り替え時の
Resources.UnloadUnusedAssets()の呼び出し - 適切なガベージコレクション管理
- アセットバンドルの活用
デバッグとプロファイリング
[編集]- プロファイラーの活用
- デバッグログの適切な使用
- エディタ拡張機能の活用
プロジェクト管理のベストプラクティス
[編集]- 命名規則の統一
- フォルダ構造の整理
- バージョン管理システムの活用
- アセットの最適な管理方法
アセット管理とリソースの最適化
[編集]アセットバンドル
[編集]アセットバンドルは、ゲームコンテンツを効率的に配信・管理するための重要な機能です。
public class AssetBundleLoader : MonoBehaviour { public string bundleUrl = "http://example.com/assetbundles/mybundle"; async Task LoadAssetBundleAsync() { using (UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(bundleUrl)) { await request.SendWebRequest(); if (request.result == UnityWebRequest.Result.Success) { AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request); // バンドルからアセットをロード GameObject prefab = bundle.LoadAsset<GameObject>("MyPrefab"); Instantiate(prefab); } } } }
リソース管理のベストプラクティス
[編集]- テクスチャの最適化
- 適切な圧縮形式の選択
- ミップマップの効果的な使用
- テクスチャアトラスの活用
- メッシュの最適化
- LOD(Level of Detail)システムの実装
- メッシュの結合
- 適切な頂点数の管理
マルチプラットフォーム開発
[編集]プラットフォーム固有の機能対応
[編集]public class PlatformSpecificFeatures : MonoBehaviour { void Start() { #if UNITY_ANDROID // Android固有の初期化 SetupAndroidFeatures(); #elif UNITY_IOS // iOS固有の初期化 SetupIOSFeatures(); #endif } void SetupAndroidFeatures() { // Androidの機能セットアップ } void SetupIOSFeatures() { // iOSの機能セットアップ } }
クロスプラットフォームの入力処理
[編集]public class InputManager : MonoBehaviour { void Update() { #if UNITY_EDITOR || UNITY_STANDALONE HandlePCInput(); #elif UNITY_IOS || UNITY_ANDROID HandleMobileInput(); #endif } void HandlePCInput() { if (Input.GetKeyDown(KeyCode.Space)) { // PCでのジャンプ処理 } } void HandleMobileInput() { if (Input.touchCount > 0) { Touch touch = Input.GetTouch(0); if (touch.phase == TouchPhase.Began) { // モバイルでのタップ処理 } } } }
ネットワーク機能の実装
[編集]マルチプレイヤー基礎
[編集]using Unity.Netcode; public class PlayerNetworkBehavior : NetworkBehaviour { private NetworkVariable<Vector3> networkPosition = new NetworkVariable<Vector3>(); public override void OnNetworkSpawn() { if (IsOwner) { // ローカルプレイヤーの初期化 } } void Update() { if (IsOwner) { // 位置の同期 Vector3 moveDir = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); transform.position += moveDir * Time.deltaTime * 5f; UpdatePositionServerRpc(transform.position); } } [ServerRpc] void UpdatePositionServerRpc(Vector3 newPosition) { networkPosition.Value = newPosition; } }
セーブデータの同期
[編集]public class CloudSaveManager : MonoBehaviour { public async Task SaveGameDataAsync(GameData data) { string json = JsonUtility.ToJson(data); // クラウドストレージへの保存処理 try { await UploadToCloud(json); } catch (Exception e) { Debug.LogError($"Cloud save failed: {e.Message}"); // ローカルにフォールバック PlayerPrefs.SetString("SaveData", json); PlayerPrefs.Save(); } } }
シェーダーとビジュアルエフェクト
[編集]カスタムシェーダーの基本
[編集]Shader "Custom/BasicColor" { Properties { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } CGPROGRAM #pragma surface surf Lambert struct Input { float2 uv_MainTex; }; fixed4 _Color; sampler2D _MainTex; void surf (Input IN, inout SurfaceOutput o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }
パーティクルシステムの最適化
[編集]- エミッションレートの適切な設定
- サブエミッターの効果的な使用
- パーティクルの生存時間管理
- GPUインスタンシングの活用
AI と ナビゲーション
[編集]NavMeshAgent の応用
[編集]public class AdvancedAIController : MonoBehaviour { private NavMeshAgent agent; private State currentState; void Start() { agent = GetComponent<NavMeshAgent>(); currentState = State.Patrol; } void Update() { switch (currentState) { case State.Patrol: UpdatePatrol(); break; case State.Chase: UpdateChase(); break; case State.Attack: UpdateAttack(); break; } } void UpdatePatrol() { // パトロール行動の実装 } void UpdateChase() { // 追跡行動の実装 } void UpdateAttack() { // 攻撃行動の実装 } enum State { Patrol, Chase, Attack } }
行動木の実装
[編集]public abstract class BehaviorNode { public enum Status { Success, Failure, Running } public abstract Status Evaluate(); } public class Sequence : BehaviorNode { private List<BehaviorNode> children = new List<BehaviorNode>(); public override Status Evaluate() { foreach (var child in children) { switch (child.Evaluate()) { case Status.Failure: return Status.Failure; case Status.Running: return Status.Running; } } return Status.Success; } }
エディタ拡張
[編集]カスタムインスペクター
[編集]using UnityEditor; [CustomEditor(typeof(MyComponent))] public class MyComponentEditor : Editor { public override void OnInspectorGUI() { MyComponent myTarget = (MyComponent)target; EditorGUI.BeginChangeCheck(); // カスタムフィールドの描画 myTarget.customValue = EditorGUILayout.FloatField("Custom Value", myTarget.customValue); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(target, "Modified MyComponent"); EditorUtility.SetDirty(target); } if (GUILayout.Button("Execute Custom Action")) { myTarget.ExecuteCustomAction(); } } }
エディターウィンドウの作成
[編集]public class CustomEditorWindow : EditorWindow { [MenuItem("Tools/My Custom Window")] public static void ShowWindow() { GetWindow<CustomEditorWindow>("Custom Tool"); } void OnGUI() { GUILayout.Label("Custom Tool Settings", EditorStyles.boldLabel); if (GUILayout.Button("Perform Action")) { // カスタム処理の実行 } } }
これらの機能を適切に組み合わせることで、より高度なゲーム開発が可能になります。必要に応じて、各セクションの詳細な説明や具体的な実装例を追加することができます。