0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Unityでつくる2DRPG ~⑯戦闘システムの構築(エンカウント処理編)

Last updated at Posted at 2025-12-24

はじめに

前回は、UI系の作成をしました。

今回は、エンカウント処理を実装します。

スクリプトの作成

新しく「MapEncounter」という名前のスクリプトを作成し、以下をコピペしてください。

// MapEncounter.cs
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(MapChunk))]
public class MapEncounter : MonoBehaviour
{
    [Header("Encounter settings")]
    [Range(0f, 1f)]
    [Tooltip("プレイヤーが1歩進むごとにこの確率でエンカウント判定を行う(典型は 0.05 = 5%)。")]
    public float encounterRate = 0.10f; 
    [Tooltip("最大で一度に出現する敵数(RollEnemies 呼び出しのデフォルト値に使う)")]
    public int defaultMaxEnemies = 3;
    [Tooltip("同種の敵を複数体出現させることを許可するなら true。\nfalse にすると同一 EnemyData は1回しか選ばれなくなる。")]
    public bool allowDuplicates = true;
    [System.Serializable]
    public struct Entry
    {
        public EnemyData enemy;
        [Range(0f, 1f)]
        public float weight; 
    }
    [Header("Enemy pool (assign EnemyData and weight)")]
    public List<Entry> enemyPool = new List<Entry>();
    public List<EnemyData> RollEnemies(int maxCount = -1)
    {
        var result = new List<EnemyData>();
        if (enemyPool == null || enemyPool.Count == 0) return result;
        int actualMax = (maxCount <= 0) ? Mathf.Max(1, defaultMaxEnemies) : maxCount;
        var candidates = new List<Entry>(enemyPool);
        float total = 0f;
        foreach (var e in candidates) total += Mathf.Max(0f, e.weight);
        if (total <= Mathf.Epsilon)
        {
            var nonNullList = new List<EnemyData>();
            foreach (var e in candidates)
            {
                if (e.enemy != null) nonNullList.Add(e.enemy);
            }
            if (nonNullList.Count == 0) return result;
            int count = Random.Range(1, actualMax + 1);
            for (int i = 0; i < count; i++)
            {
                var pick = nonNullList[Random.Range(0, nonNullList.Count)];
                result.Add(pick);
                if (!allowDuplicates) nonNullList.Remove(pick);
                if (nonNullList.Count == 0) break;
            }
            return result;
        }
        int pickCount = Random.Range(1, actualMax + 1);
        for (int p = 0; p < pickCount; p++)
        {
            float r = Random.value * total;
            float acc = 0f;
            EnemyData chosen = null;
            for (int i = 0; i < candidates.Count; i++)
            {
                var e = candidates[i];
                float w = Mathf.Max(0f, e.weight);
                acc += w;
                if (r <= acc)
                {
                    chosen = e.enemy;
                    if (!allowDuplicates)
                    {
                        total -= w;
                        candidates.RemoveAt(i);
                    }
                    break;
                }
            }
            if (chosen == null)
            {
                for (int i = 0; i < candidates.Count; i++)
                {
                    if (candidates[i].enemy != null)
                    {
                        chosen = candidates[i].enemy;
                        if (!allowDuplicates)
                        {
                            total -= Mathf.Max(0f, candidates[i].weight);
                            candidates.RemoveAt(i);
                        }
                        break;
                    }
                }
            }
            if (chosen != null)
                result.Add(chosen);
            if (candidates.Count == 0) break; // no more candidates
        }
        return result;
    }
}

スクリプトができたら、これを 全てのチャンクプレハブにアタッチ してください。

インスペクターの調整

このような見た目になっていると思います。
image.png

このうち、EnemyPoolで出現する敵を調整することができます。

Enemyという欄には、以前作成したEnemyDataを入れてください。
その下のWeightをいじることで、各敵の出現率を変えることができます。

実際の動き

ここまできちんと実装できていれば、プレイヤーが移動した際、エンカウント処理が発生するはずです。

また、その後の戦闘処理もうまくいくと思います。

おわり

今回をもって、本シリーズは終了です。
面倒くさい工程もありましたが、ここまで作業していただき、本当にありがとうございました。

このシリーズを通して、Unityのことがより好きになっていただけたら嬉しいです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?