ぱぴブログ

さんたろのブログ

ゲーム開発が好きな人のひとりごと

UnityRPG制作記① ~戦闘システム~

はじめに

みなさんこんにちは。ゲーム制作大好きさんたろーです。
よくあるRPGのようなゲームをUnityを使って開発しています。

papyrustaro.hatenablog.jp

LOCAL学生部という北海道の情報系コミュニティに所属しているわけですが、 総大会という1泊2日のイベントに参加してきました。

今回は総大会でのRPGの戦闘システムの作成話をしていこうと思います。

実装したことを淡々と書いていくだけなので、コード見るのが速いと思いますが笑

github.com

スキルの発動

前回はキャラクターの量産をするために頑張りました。
キャラクターが発動できるスキルなども同様にInspector上で量産したいな、というわけで...
実装自体はただ、Inspectorで入力したパラメータに沿ってよしなにしているだけなので省略します。

f:id:papyrustaro:20200119120039p:plain
BattleActiveSkillクラス

f:id:papyrustaro:20200119120103p:plain
列挙型の値を変えるだけで、スキルの挙動を変えられる

上の画像のようにパラメータを入力するだけで、基本的なスキルは動きます。
特殊なスキルを実装したい場合は、EffectTypeをその他にし、OtherBattleActiveSkillsFuncクラスを継承したクラスの中で、処理を書き、アタッチすることで実現可能です。

f:id:papyrustaro:20200119132526p:plain
その他の効果のスキルの実装(Inspector)

コードは下のように

public class BattleActiveSkill : MonoBehaviour{
  //省略
  public void OtherFunc(BattleCharacter invoker, List<BattleCharacter> target)
    {
        GetComponent<OtherBattleActiveSkillsFunc>().SkillFunc(invoker, target, this);
    }
}

public abstract class OtherBattleActiveSkillsFunc : MonoBehaviour
{
    public virtual void SkillFunc(BattleCharacter invoker, List<BattleCharacter> target, BattleActiveSkill skill)
    {
    }
}

public class SampleSkillFunc : OtherBattleActiveSkillsFunc
{
    public override void SkillFunc(BattleCharacter invoker, List<BattleCharacter> target, BattleActiveSkill skill)
    {
        Debug.Log(invoker.CharaClass.CharaName + "のその他のスキル発動");
        Debug.Log("スキルの説明:" + skill.Description);
    }
}

スキルの各パラメータの軽い説明

EffectType

効果の種類です。これによって行う処理が変わります。
HP回復ならvalue分対象のHPを回復。攻撃ならatk*rateで対象に攻撃。といった具合です。

RateOrValue

スキルの倍率または威力です。どちらの意味になるかはEffectTypeで決まります。
EffectTypeがAtkバフで、RateOrValueが1.2ならAtk1.2倍バフになります。

EffectTurn

バフなどの効果ターン

Description

スキルの説明です。入力しない場合、他のパラメータから自動で作成されます。

TargetElement

ターゲットの属性です。火属性の敵全体、などが対象のスキル用。
デフォルトは全属性。

TargetType

列挙型からターゲットタイプを選択します。
この値を読み取って適切なターゲットで処理をしてくれます。
このためプレイヤーはどのタイミングでも、ターゲットする敵を変更することができます。
このタイプがOneAllyつまり味方ひとりのときのみ、発動後にプレイヤーにターゲットの入力を促します。

ID

スキルの固有ID。スキル名の役割も担っています。

NeedSkillPoint

必要なスキルポイント。この値より所持スキルポイントが低いと発動できません。

敵の基本AIの実装

ここまで総大会に来るまでのお話です。
総大会にきて、まず実装したのが敵のAIでした。
しかし、これはそこまで難しくなかったですね。
すでにプレイヤーのスキル発動の呼び出し側も実装していたので、敵もプレイヤーのようにスキルを発動させればいいだけです。
対象と発動するスキルをランダムに(スキルポイントが足りない場合は除外)。
これもTargetTypeというパラメータがあってこそできること。

現時点では敵の基本AIは通常攻撃と発動可能なスキルからランダムでひとつの行動をとります。
しかし、体力最大の敵に回復などが起こるかもしれないので、そこはもう少し改変したいですね。
また、BattleEnemyCharacterのパラメータHaveSpecialAIがtrueのときに、特殊な処理を読み込み行動させることができるようにもしました。

問題発覚「アイテムの実装でスキルとほぼ同じじゃね」

続いて実装したのがプレイヤーのアイテムの使用。
大きく分けて3つの実装がありました。
⓪呼び出され側の実装
①呼び出し側の実装
②プレイヤーの行動選択

まず⓪からやっていこうと考えて気づくのです。
「アイテムってやることほとんどスキルと変わらないな」

スキルはスキルポイント、アイテムは個数という違い程度で、結局ほとんど処理は同じだろう、と。

そこで今まで実装していたスキルの処理を1段階抽象化する作業をしました。
当然最初はエラーの嵐ですが、無視無視。

BattleActiveSkillクラスを呼び出していたところを、BattleAcitveEffectクラスとして呼び出します。
BattleActiveEffectクラスを継承させてBattleActiveSkillクラスとBattleActiveItemクラスを作ります。
簡単にいえば、それだけですね。
アイテムもスキルと実装は大差ないので。
呼び出し側も、同じようにBattleAcitveEffectとして呼べば基本大丈夫です。

そして残るは②のプレイヤーの行動選択
今自分がどの状態にいるのか列挙型で保存することで、処理の分岐をおこないました。

メインの処理はこんな感じです。
ここはまだまだ修正する必要がありそうですね。

private void PlayerSelect()
    {
        switch (this.currentSituation)
        {
            case E_BattleSituation.PlayerSelectAction:
                InputPlayerAction();
                break;
            case E_BattleSituation.PlayerSelectActiveSkill:
                InputActuateSkill();
                break;
            case E_BattleSituation.PlayerSelectActiveItem:
                InputActuateItem();
                break;
            case E_BattleSituation.PlayerSelectSkillTarget:
                if(!this.inputTargetWaiting) InputActuateSkill();
                break;
            case E_BattleSituation.PlayerSelectItemTarget:
                if(!this.inputTargetWaiting) InputActuateItem();
                break;
            case E_BattleSituation.WaitFinishAction:
                break;
        }
    }

まとめ

総大会でやったのは敵の行動AIの作成とアイテムの使用の実装です
いい感じに抽象化できたので大満足です^^
これで、キャラクター、スキル、アイテムの量産は簡単にできるようになりました。

総大会自体も、なかなか会えないLOCAL学生部の方たちと精進しあえて最高に楽しかったです。
想像以上に精進もできました(当社比)

あとは「防御」の行動選択の実装と、リファクタリングや調整などをして、戦闘システムは完成しそうです。
戦闘システムが完成したら、ダンジョンシステムの作成です。
まだまだやらなきゃいけないことは多いですが、精進していきます。