4
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Unity】RPGのレベルシステムの書き方

Last updated at Posted at 2019-09-28

レベルシステム、RPG作っていれば必ず書くと言っていい処理ですが、自分流の書き方を残しておきます。

累計経験値と累計経験値に応じたレベルのテーブルがあれば、そこから現在Lvと次のLvまでの残り経験値を算出できます。
しかし、Lvを取得する度に都度計算していては流石に重たいので、累計経験値が加算される度に現Lvと残り経験値を更新するようにします。

累計経験値に応じたレベルのテーブルを関数の引数にとって外部から参照してますが、これはレベルテーブルは固有な値としてstatic readonlyで修飾して使うことが多いためです。

あるいは、UnityならScriptableObjectから参照する場合もあるでしょう。

いずれにせよ外部またはサブクラス上のstaticな値を汎用的に参照させたいので関数の引数に含めました。

ExpLevelClass.cs
using System.Linq;
using UnityEngine;

[System.Serializable]
public class ExpLevelClass
{
    [SerializeField] int _exp;
    [SerializeField] int _remainExp;
    [SerializeField] int _minLevel;
    [SerializeField] int _level = 1;

    public int Exp => _exp;
    public int RemainExp => _remainExp;
    public int MinLevel => _minLevel;
    public int Level => _level;
    
    // Expを加算してLvを初期化する
    public void AddExp(int exp, int[] expArray)
    {
        //カンストを考慮して加算
        _exp = Mathf.Clamp(_exp + exp, 0, expArray[expArray.Length - 1]);
        // 値の更新
        UpdateLevel(expArray);
        UpdateRemainExp(expArray);
    }

    void UpdateLevel(int[] expArray)
    {
        // 現Exp以下の値の中で最大の値のインデックスを取得
        var maxIdx = expArray.Where(x => x <= _exp).Select((val, idx) => new {V = val, I = idx})
            .Aggregate((max, working) => (max.V > working.V) ? max : working).I;
        _level = maxIdx + 1;
    }

    void UpdateRemainExp(int[] expArray)
    {
        // 現Expより大きい値の中で最小の値のインデックスを取得
        var minIdx = expArray.Where(x => x > _exp).Select((val, idx) => new {V = val, I = idx})
            .Aggregate((min, working) => (min.V < working.V) ? min : working).I;
        _remainExp = expArray[minIdx] - _exp;
    }
}
Player.cs
[System.Serializable]
public class Player
{
    public string Name = "主人公";
    public ExpLevelClass ExpLevel = new ExpLevelClass();
    
    static readonly int[] TOTAL_EXP_ARRAY = {0,100,300,600,1000};

    // 経験値獲得処理
    public void AddExp(int exp)
    {
        ExpLevel.AddExp(exp, TOTAL_EXP_ARRAY);
    }
}

###おまけ
関数でLevelとRemainExpの計算結果を返す

ExpLevelClass.cs
using System.Linq;
using UnityEngine;

[System.Serializable]
public class ExpLevelClass
{
    [SerializeField] int _exp;
    [SerializeField] int _remainExp;
    [SerializeField] int _minLevel;
    [SerializeField] int _level = 1;

    public int Exp => _exp;
    public int RemainExp => _remainExp;
    public int MinLevel => _minLevel;
    public int Level => _level;
    
    // Expを加算してLvを初期化する
    public (int afterLevel, int remainExp) AddExp(int exp, int[] expArray)
    {
        //カンストを考慮して加算
        _exp = Mathf.Clamp(_exp + exp, 0, expArray[expArray.Length - 1]);
        // 値の更新
        UpdateLevel(expArray);
        UpdateRemainExp(expArray);

        return (Level, RemainExp);
    }

    void UpdateLevel(int[] expArray)
    {
        // 現Exp以下の値の中で最大の値のインデックスを取得
        var maxIdx = expArray.Where(x => x <= _exp).Select((val, idx) => new {V = val, I = idx})
            .Aggregate((max, working) => (max.V > working.V) ? max : working).I;
        _level = maxIdx + 1;
    }

    void UpdateRemainExp(int[] expArray)
    {
        // 現Expより大きい値の中で最小の値のインデックスを取得
        var minIdx = expArray.Where(x => x > _exp).Select((val, idx) => new {V = val, I = idx})
            .Aggregate((min, working) => (min.V < working.V) ? min : working).I;
        _remainExp = expArray[minIdx] - _exp;
    }
}
Player.cs
[System.Serializable]
public class Player
{
    public string Name = "主人公";
    public ExpLevelClass ExpLevel = new ExpLevelClass();
    
    static readonly int[] TOTAL_EXP_ARRAY = {0,100,300,600,1000};

    // 経験値獲得処理
    public (int afterLevel, int remainExp) AddExp(int exp)
    {
        return ExpLevel.AddExp(exp, TOTAL_EXP_ARRAY);
    }
}

##参考
Linqで快適な生活を
[LINQ][C#] Aggregateの使い方(畳み込み, fold)
C# 7 の Tuple は戻り値が複数の時に便利

4
9
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
4
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?