ゼロから始めるゲーム制作5:NaniNovel機能追加 <カスタムコマンドの自作>

ゼロから始めるゲーム制作5:NaniNovel機能追加 <カスタムコマンドの自作>

書いた人 : HAYAO(PG) HAYAO(PG)


 HazeDenki株式会社のプログラマーを担当しているHAYAOと申します。

 良かったらTwitter(X)もフォローしてね。


 前回までの記事は以下から飛べます。


  1. ノベルゲームの基盤を作る。まず何をする?
  2. ノベルゲームエンジンの選定。宴とNaniNovelの特徴について
  3. 開発環境のセットアップ
  4. ノベルゲームエンジンのソースをAIとカスタマイズしていく方法
  5. NaniNovelの機能についての解説数本(今回)


 NaniNovelのインストールと開発方法の手順説明が終わったので、これからは機能追加の手順など、Naninovelに関するTipsを投稿しつつ、作品の事に触れていけるような記事を出していけたらと考えています。


 今回はカスタムコマンドを追加する方法について紹介します。


 前後編で分けて、前編はカスタムコマンドの作り方。後編はそれを利用した"自作画面エフェクト"呼び出しの作り方を説明していこうと思います。

 後編のボリュームがとんでもないことになってしまったので、分割しました。。


 前編はすぐに実装が終わる基礎のカスタムコマンド作成ですが、後編はAIを使用することを前提としたShaderやポストプロセスを使った改修を行う想定ですので、ノベルゲームエンジンのソースをAIとカスタマイズしていく方法を終わらせていることを前提とします。


 では、前編のカスタムコマンドの追加方法について説明していきます。


自作カスタムコマンド作成までの流れ

 簡単なコマンドを作って、それを実行してみましょう。

 まず以下のファイルを作成してください。

using Naninovel;
using UnityEngine;


[CommandAlias("myCommand")]
public class MyCommand : Command
{
    public override UniTask Execute(AsyncToken asyncToken = default)
    {
        Debug.Log("Hello!");
        return UniTask.CompletedTask;
    }
}


 その後、このコマンドを実行するためのシナリオファイルを作成します。

 Projectウインドウ上で「Naninovel Script」を作成してください。名前はなんでも良いです。


 シナリオファイルを作ったら、Naninovel->Configuration->ScriptsからStart Game Scriptに作成したファイルを設定しておいてください。(動作確認用なので、既に作品を作り始めている方は設定不要です。)


 次に、シナリオファイルを開きます。セットアップの回で、VSCode連携とNaninovelプラグインを全てインストールしていることを前提とします。

 ここで"@myCommand"と打ち、それがNaninovelのカスタムコマンドとして認識されていれば実装完了です。


 実行して、ログに"Hello!"と表示されることを確かめてください。


カスタムコマンド用のエイリアスについて

 では、プログラムの内容について詳細に解説します。


using Naninovel;
using UnityEngine;
---①----

② [CommandAlias("myCommand")]

③ public class MyCommand : Command
{
  ④ public override UniTask Execute(AsyncToken asyncToken = default)
    {
        Debug.Log("Hello!");
        return UniTask.CompletedTask;
    }
}


 ①using文

  • using Naninovel; → NaniNovelの基本機能を使えるようにする。今回はCommandクラスを継承するために必須。
  • using UnityEngine; → Debug.Logを使うために必要


 ② CommandAlias属性(コマンドの名前を決める)

  • "myCommand" がnaniスクリプトで使う名前になる
  • この名前が他のコマンドと重複するとエラーになる
例:
[CommandAlias("flash")] → naniで @flash と書く
[CommandAlias("customSave")] → naniで @customSave と書く


 ③クラス宣言(必ずCommandを継承すること)

  • CommandクラスのExecuteメソッドを上書きしてコマンドの内容を定義する。

 

 ④Executeメソッド(処理の本体)

 Commandクラスに定義してあるExecuteのabstractクラスの実装になります。

 ルールとしては

  • 戻り値がUniTask型であること
  • return UniTask.CompletedTask;で締める


 以上が先ほどのサンプルプログラムの説明ですが、一つ応用としてパラメータ付きコマンドもここで説明します。

 次回の"画面エフェクト"呼び出しの応用カスタムコマンドの作成に向けた説明コードなので実装しなくても良いです。

using Naninovel;
using UnityEngine;


[CommandAlias("setActive")]
public class SetActiveCommand : Command
{
    [ParameterAlias("target"), RequiredParameter]
    public StringParameter Target;
    
    [ParameterAlias("active")]
    public BooleanParameter Active;


    public override UniTask Execute(AsyncToken asyncToken = default)
    {
        // パラメータの取得
        string targetName = Target;
        bool isActive = Active ?? true; // デフォルトはtrue
        
        // GameObjectを検索
        GameObject targetObject = GameObject.Find(targetName);
        
        // 見つからなかった場合の処理
        if (targetObject == null)
        {
            Debug.LogWarning($"GameObject '{targetName}' が見つかりませんでした");
            return UniTask.CompletedTask;
        }
        
        // アクティブ状態を変更
        targetObject.SetActive(isActive);
        Debug.Log($"{targetName} を {(isActive ? "アクティブ" : "非アクティブ")} にしました");
        
        return UniTask.CompletedTask;
    }
}

 上記のコードの特徴は、ParameterAliasがあることです。


 ParameterAliasを定義していると、以下のようにカスタムコマンドの引数として値を指定することが出来ます。

@setActive target:Player active:false
; ↑ Playerという名前のGameObjectを非アクティブにする

@setActive target:Enemy active:true
; ↑ Enemyという名前のGameObjectをアクティブにする

 

 変数の型はNaninovel独自の型になっているので、以下を参考にしてください。

 StringParameter,DecimalParameter,BooleanParameterの使用が主になると思います。


 次回の応用カスタムコマンドでは、エフェクトの強度設定にDecimalParameterを、有効無効の切り替えにBooleanParameterを使います。

 

 説明用に整理された自作エフェクト呼び出しを使いたいと考えているのですが、現在実装しているエフェクトは引数がこんな感じになっています・・

@dizzy start:true intensity:0.7 distortion:0.04 distortionSpeed:1 pulse:true pulseFreq:2 pulseAmp:0.3 vignette:0.42 blur:1.4 desaturation:0.28 brightness:0.88 innerRadius:0.3 outerRadius:0.6 falloff:2.5 tint:#FF000066 duration:2 wait:true


 設定項目を欲張りすぎて説明不可になってしまったのでなんとかしておきます。。

 


 次回、エフェクト呼び出しの実装内容を紹介していきます。

 今回は基礎的な内容でしたが、一度自作コマンドを動かす喜びを知っていただけたらと思います。


次の記事出来ました→



 ここまで読んでくださった方、ありがとうございました。

 HazeDenkiをよろしくお願いいたします。

記事一覧へ戻る

コメント (3)

コメントを残す

0/1000
HTF 19日前
This is really cool! Thanks for sharing all this!
HAYAO 1ヶ月前
>mayatang_chan thank you!! Your comments always encourage me!
♡mayatang_chan♡ 1ヶ月前
I have no idea how coding work but it's still an interesting to read how things work I wish the best of luck for you cannot wait for the game I will continue to support yall 🔥🔥🔥