🕌

【4アプローチ】C# Queue<T>を用いたUnityタスクキューシステム実装法

2025/03/05に公開

閲覧いただきありがとうございます。はじめまして、ゲーム開発所RYURYUの「りゅうや」と申します。

❏ ゲーム開発ランキング【 1位 】実績多数 (ココナラ)
❏ ココナラ総販売【 220件超 】
❏ GC甲子園2022・東京ゲームショウ2023など出展経験あり

■ Unityを使ったゲーム・VRの受託開発についてのお問い合わせは、Xからお気軽にどうぞ。
https://x.com/RYURYU_GAME_MFG

■ 記事に関するご質問やご意見は、Discordサーバーまでお寄せください。
https://discord.gg/5FwuKCacNy

【4アプローチ】C# Queue<T>を用いたUnityタスクキューシステム実装法

Unityにおけるタスク管理は、ゲームやアプリケーションのパフォーマンス最適化において非常に重要な要素です。特に複数のタスクを効率的に処理するためには、適切なデータ構造の選択が鍵となります。本記事では、C#のQueue<T>を活用したUnityタスクキューシステムの実装方法を4つのアプローチから詳しく解説します。各アプローチの特徴や実装例を通じて、最適な方法を見つけ出す手助けをします。

1. 基本的なQueue<T>によるタスク管理

まずは、C#のQueue<T>クラスを用いた基本的なタスク管理方法について説明します。このアプローチはシンプルかつ直感的で、初心者にも理解しやすい方法です。

Queue<T>の基本操作

Queue<T>はFIFO(First-In-First-Out)方式でデータを管理します。タスクを順番に処理するには最適なデータ構造です。

TaskQueue.cs
using System.Collections.Generic;
using UnityEngine;

public class TaskQueue
{
    private Queue<System.Action> taskQueue = new Queue<System.Action>();

    public void EnqueueTask(System.Action task)
    {
        taskQueue.Enqueue(task);
    }

    public void ExecuteNextTask()
    {
        if (taskQueue.Count > 0)
        {
            var task = taskQueue.Dequeue();
            task.Invoke();
        }
    }

    public bool HasTasks()
    {
        return taskQueue.Count > 0;
    }
}

実装のポイント

  • Enqueue: タスクをキューに追加します。
  • Dequeue: キューからタスクを取り出し、実行します。
  • HasTasks: キューにタスクが残っているかを確認します。

メリット・デメリット

  • メリット
    • 実装が簡単で直感的
    • 順序通りにタスクを処理可能
  • デメリット
    • 複雑なタスク管理には向かない
    • 並列処理や優先度管理が困難

リファレンスリンク

Unity公式ドキュメント - Queue<T>クラス

詳細な実装例を見る

詳しいコード例や実装ステップについては、UnityでのTaskシステムの実装の動画を参照してください。

2. スレッドセーフなタスクキューの実装

マルチスレッド環境での安定したタスク処理を実現するために、スレッドセーフなQueue<T>の実装方法を紹介します。これにより、複数のスレッドから安全にタスクを追加・実行できます。

スレッドセーフなQueue<T>の実装

ThreadSafeTaskQueue.cs
using System.Collections.Generic;
using System.Threading;
using UnityEngine;

public class ThreadSafeTaskQueue
{
    private Queue<System.Action> taskQueue = new Queue<System.Action>();
    private readonly object lockObj = new object();

    public void EnqueueTask(System.Action task)
    {
        lock (lockObj)
        {
            taskQueue.Enqueue(task);
        }
    }

    public void ExecuteNextTask()
    {
        System.Action task = null;
        lock (lockObj)
        {
            if (taskQueue.Count > 0)
            {
                task = taskQueue.Dequeue();
            }
        }
        task?.Invoke();
    }

    public bool HasTasks()
    {
        lock (lockObj)
        {
            return taskQueue.Count > 0;
        }
    }
}

実装上の注意点

  • ロック機構の導入: lockを使用して、複数のスレッドからのアクセスを制御します。
  • パフォーマンスの考慮: 過度なロックはパフォーマンス低下を招くため、最小限に留めます。

メリット・デメリット

  • メリット
    • マルチスレッド環境での安全なタスク管理
    • データ競合の防止
  • デメリット
    • 実装が複雑
    • パフォーマンスに影響を与える可能性

参考資料

資料名 概要 URL
Microsoft Docs - Queue<T>クラス Queue<T>の公式リファレンス Microsoft Docs
Unityタスクキューの実装例 タスクキューシステムのクラス図とシーケンス図 Unity公式

3. 優先度付きタスクキューの実装

すべてのタスクが同じ優先度ではない場合、優先度付きのタスクキューを導入することで、重要なタスクを先に処理することが可能です。以下にその実装方法を示します。

優先度付きQueue<T>の実装

PriorityTaskQueue.cs
using System;
using System.Collections.Generic;
using UnityEngine;

public class PriorityTaskQueue
{
    private SortedDictionary<int, Queue<System.Action>> priorityQueues = new SortedDictionary<int, Queue<System.Action>>();

    public void EnqueueTask(System.Action task, int priority)
    {
        if (!priorityQueues.ContainsKey(priority))
        {
            priorityQueues[priority] = new Queue<System.Action>();
        }
        priorityQueues[priority].Enqueue(task);
    }

    public void ExecuteNextTask()
    {
        foreach (var key in priorityQueues.Keys)
        {
            if (priorityQueues[key].Count > 0)
            {
                var task = priorityQueues[key].Dequeue();
                task.Invoke();
                if (priorityQueues[key].Count == 0)
                {
                    priorityQueues.Remove(key);
                }
                break;
            }
        }
    }

    public bool HasTasks()
    {
        foreach (var queue in priorityQueues.Values)
        {
            if (queue.Count > 0)
                return true;
        }
        return false;
    }
}

実装のポイント

  • SortedDictionaryの使用: キーに優先度を設定し、自動的にソートされるようにします。
  • 複数のQueue<T>: 各優先度ごとに別々のキューを管理します。

メリット・デメリット

  • メリット
    • タスクに優先度を設定可能
    • 重要なタスクを先に処理できる
  • デメリット
    • 実装が複雑
    • 優先度の管理が必要

実装例と参考資料

ExampleUsage.cs
public class ExampleUsage : MonoBehaviour
{
    private PriorityTaskQueue taskQueue = new PriorityTaskQueue();

    void Start()
    {
        taskQueue.EnqueueTask(() => Debug.Log("Low priority task"), 2);
        taskQueue.EnqueueTask(() => Debug.Log("High priority task"), 1);
    }

    void Update()
    {
        if (taskQueue.HasTasks())
        {
            taskQueue.ExecuteNextTask();
        }
    }
}

PriorityTaskQueueの詳細な実装ガイド

4. 非同期処理との統合

最近のゲーム開発では、非同期処理を効果的に取り入れることがパフォーマンス向上につながります。Queue<T>を非同期処理と組み合わせたタスクキューシステムの実装方法を紹介します。

非同期とQueue<T>の統合

AsyncTaskQueue.cs
using System.Collections.Concurrent;
using System.Threading.Tasks;
using UnityEngine;

public class AsyncTaskQueue
{
    private ConcurrentQueue<System.Func<Task>> taskQueue = new ConcurrentQueue<System.Func<Task>>();
    private bool isProcessing = false;

    public void EnqueueTask(System.Func<Task> task)
    {
        taskQueue.Enqueue(task);
        if (!isProcessing)
        {
            isProcessing = true;
            ProcessQueue();
        }
    }

    private async void ProcessQueue()
    {
        while (taskQueue.TryDequeue(out var task))
        {
            await task.Invoke();
        }
        isProcessing = false;
    }

    public bool HasTasks()
    {
        return !taskQueue.IsEmpty;
    }
}

非同期タスクの実行

非同期タスクを効率的に処理するために、asyncawaitを活用します。これにより、メインスレッドをブロックすることなくタスクを実行できます。

注意点

  • エラーハンドリング: 非同期タスク内での例外処理を適切に行う必要があります。
  • タスクの管理: タスクの順序や依存関係を慎重に管理します。

メリット・デメリット

  • メリット
    • 非同期タスクの効率的な処理
    • メインスレッドの負荷軽減
  • デメリット
    • 実装が複雑
    • デバッグが困難になる場合がある

参考資料と実装例

UnityでのTaskシステムの実装

AsyncExampleUsage.cs
public class AsyncExampleUsage : MonoBehaviour
{
    private AsyncTaskQueue asyncTaskQueue = new AsyncTaskQueue();

    void Start()
    {
        asyncTaskQueue.EnqueueTask(async () => {
            await Task.Delay(1000);
            Debug.Log("Async task completed");
        });
    }

    void Update()
    {
        // 必要に応じてタスクの状態を確認
    }
}

まとめ

本記事では、C#のQueue<T>を用いたUnityタスクキューシステムの実装方法を4つのアプローチから解説しました。基本的なキュー操作からスレッドセーフな実装、優先度付きキュー、そして非同期処理との統合まで、様々なニーズに応じた方法を紹介しました。以下に各アプローチの概要をまとめたテーブルを示します。

アプローチ 特徴 メリット デメリット
基本的なQueue<T> シンプルなFIFO管理 実装が簡単 複雑な管理が困難
スレッドセーフなQueue<T> マルチスレッド対応 安全なタスク管理 実装が複雑
優先度付きQueue<T> タスクに優先度設定 重要タスクを先に処理 管理が必要
非同期統合Queue<T> 非同期処理との連携 メインスレッドの負荷軽減 デバッグが難しい

参考リンク


タスクキューシステムの実装は、ゲームやアプリケーションのパフォーマンスとユーザー体験を大きく左右します。今回紹介した4つのアプローチを参考に、自身のプロジェクトに最適なタスク管理方法を選択し、より効率的な開発を目指してください。

Unityをもっと極めたい"あなた"へ ― 今すぐスキルアップのチャンス!

1. どこでもUnity教室「無料プラン」

❏ 毎日の質問で即解決|Unityに関する疑問や悩みは、専用Discordでプロの仲間とシェア!

  • 月額0円 で、テキストで気軽に質問・進捗共有が可能
  • 実績多数のコミュニティで、参加するだけで具体的な課題解決のヒントが手に入る

まずは無料で参加して、あなたのUnity学習を加速させましょう! 無料でDiscordに参加する]
https://discord.gg/5FwuKCacNy

2. Unity超入門書【1,000円】

Unityスキルを5日間でマスター|「実践×即戦力」を手に入れる!

  • 130,000文字超の詳細な解説と実例で、初心者でもすぐにUnityの基礎が身につく
  • 実際の成果例:5日間でシンプルな3D FPSゲームを完成
  • 専属講師サポートのオプション付きで、疑問を即解消しながら学習を進められる

まずはこの教材でUnity開発の第一歩を体験してください! 教材を今すぐ購入する
https://zenn.dev/ryuryu_game/books/fd28de9d8e963a/viewer/0570af

3. Unity超入門完全支援プラン【単発24,800円】

Unityの全てをプロがバックアップ|教材で学んだ内容を実践サポート!

  • 専属講師による24時間テキスト質問サポート(毎日17:00~21:00の回答)
  • 月2回×60分 または 月1回×120分のビデオチャットで、学習進捗やプロジェクトの具体的な課題を徹底サポート
  • 教材と連携し、実践の現場での疑問や課題をそのまま解決!
  • 限定:1度に最大10名様のみ受付!早期申込で安心のサポート体制を

教材で学んだ知識をさらに深め、実践に活かすならこのプランがおすすめです! 今すぐ詳細を確認する
https://ryuryu.memberpay.jp/service/item/yjo1sst

4. Unityプロジェクト完全支援プラン【月額48,000円】

Unityプロジェクトを本格サポート|個人の趣味からプロの現場まで幅広く対応!

  • 専属講師による24時間テキスト質問サポート(毎日17:00~21:00の回答)
  • 月2回×60分のビデオチャットで、プロジェクトの進行状況を細かくサポート
  • Unity開発の一部を代行するサービスが常に20%割引で利用可能
  • 基本操作からエラー対応、プロジェクト設計のアドバイスまで幅広くサポート
  • 専用Discordサーバーでのサポート体制(ご購入後に招待リンクを送付)

個人プロジェクトを着実に進め、より高い成果を求めるあなたに最適なプランです! 今すぐプロジェクト支援プランを確認する
https://ryuryu.memberpay.jp/plan/item/epeiywt

※ Unity超入門書で学んだ内容を、さらに深く実践に活かしたい方は、完全支援プランとプロジェクト支援プランの併用がおすすめです!

Discussion