ゲーム化!tomo_manaのブログ

ゲーム化!tomo-manaのブログ

Unityでゲームを作る方法について紹介しています

Unity学習#23-1 (Unity 2019.4.1f1) 最大・最小値を加味したパラメータへの加算

今回は、アイテムでステータスを更新する処理(第23回)に関連して、最大・最小値を加味したパラメータへの加算を実装します。

<目次>

最大・最小を超えない範囲で値を加減算する

インターフェース

最大・最小を持つパラメータ値Aに、値Bを加算する処理を、以下のインターフェースにします。

実際の加算量B = 値の加算(最大・最小を持つパラメータ値A、値B);

最大・最小を持つパラメータの構造

パラメータ値Aは、以下の構造で表します。

class 最大・最小を持つパラメータ値A {
  値
  最大値
  最小値
}

コード

最大・最小(ParamRange.cs)

public class ParamRange
{
    public int val;
    public int max;
    public int min;
}

加算処理(今回はPartyCharacterStatus.cs内)

// パラメータへの加算(加算量を返す)
int CulcParam(ParamRange range, int val)
{
    int a, b, a_old, b_old, lim;
    
    // a: 足される数, b:足す数
    a_old = a = range.val;
    b_old = b = val;
    
    if( b > 0 ){
        // 加算
        lim = range.max;
        if( a + b > lim ){
            b = lim - a;
        }
        a += b;
    } else 
    if( b < 0 ){
        // 減算
        lim = range.min;
        if( a + b < lim ){
            b = lim - a;
        }
        a += b;
    }
    
    if ( b ) {
        // 加算量の確認
        // 例:90/100 (20) -> 100/100 : 10
        Debug.Log( a_old + "/" + range.max + " (" + b_old + ") -> " + a + "/" + range.max + " : " + b );
    }
    return b;
}

パラメータ名から最大・最小値を自動で判別する

実際は、パラメータ毎に最大・最小値は一意に決まるので、毎回最大値・最小値を渡さないで、パラメータ名だけを指定できる方が楽です。そのため、上記の計算式をラッピングする以下のインターフェースを考えます。

パラメータ名(enum、配列)

enum パラメータ名 {
    パラメータ名1,
    パラメータ名2,
    :
    PARAM_MAX   // パラメータの個数
};

List<short> パラメータ;

インターフェース

実際の加算量 = パラメータへの加算(パラメータ名、加算量);

コード

using UnityEngine;  // Debug.Log
using System.Collections;
using System.Collections.Generic;

// パラメータ名
public enum CharacterStatusParams
{
    LIFE = 0,   // 生命力(削る対象)
    LIFEMAX,    // 生命力の最大値
    ATTACK,     // 攻撃力(削る力)
    SPEED,      // 速度(削る速さ)
    PARAM_MAX    // パラメータの個数
};

public class PartyCharacterStatus
{
    // パラメータ値
    private List<short> param;
    
    // コンストラクタ
    public PartyCharacterStatus(short life, short lifeMax, short attack, short speed){
        param = new List<short>();
        param.Add( life );
        param.Add( lifeMax );
        param.Add( attack );
        param.Add( speed );
    }
    
    // パラメータへの加算
    public int SumValue( CharacterStatusParams id, int val )
    {
        ParamRange r = new ParamRange();
        
        r.val = param[(int)id];
        
        if( id == (int)CharacterStatusParams.LIFE ){
            r.max = param[(int)CharacterStatusParams.LIFEMAX];
            r.min = 0;
        } else {
            r.max = 255;
            r.min = 0;
        }
        return CulcParam( r, val );
    }

    // 先ほどの計算処理もとりあえずここに追加(そのうちにファイル分割する)
    int CulcParam(ParamRange range, int val)
    {
        // 略
    }
}    

出力テスト

ステータス値とアイテム効果の値を境界値付近に設定して、加算しようとする値がステータス値の最大・最小でクリップされるか確認します。

60/100 + 2080/100 : 20
90/100 + 20100/100 : 10
60/100 - 2040/100 : -20
10/100 - 200/100 : -10
100/100 + 20100/100 : 0
0/100 + 2020/100

アイテムを使用した時の例

QueryUseWindow.cs

public void OnSubmit(BaseEventData eventData)
{
    // 中略
    
    // アイテムの作用と表示
    if( context.itemContext.itemOperation == (int)ItemUsage.USE ){
        Efficacy efficacy = context.itemContext.itembag[ context.itemContext.itemId ].efficacy;
        if( efficacy != null ){
            if( efficacy.value != 0 ){
                string showEffect = null;
                
                int effect = context.party.member[0].status.SumValue( efficacy.status, efficacy.value );
                if( effect == 0 ){
                    showEffect = "Nothing Happened";
                } else {
                    if( effect > 0 ){
                        if( efficacy.status == CharacterStatusParams.LIFE ){
                            showEffect = "Cured: " + effect;
                        } else {
                            showEffect = "Increased: " + effect;
                        }
                    } else {
                        showEffect = "Decreased: " + -(effect);
                    }
                }
                Debug.Log( showEffect );
            }
        }
    }
    // 以下略
}

次回

第22回で作成したテキスト出力画面を一工夫して、複数行の出力に対応します。