フリーのビジュアルノベルアセットFungusを使ってRPGのイベントを作る

この記事はUnity #2 Advent Calendar 201713日目の記事です。

概要

Fungusはフリーで使えるビジュアルノベルアセットです。
簡単な概要についてはフリーのビジュアルノベルアセットのFungusが便利で紹介しています。

今回はこのFungusを使って、シーン切り替えありのRPGのイベント処理を作りたいと思います。
いわゆる、おつかいイベントを実装します。こんなのを作ります。

Flowchart作成

とりあえず、町と人を適当に配置し、操作用にStandard AssetsのFPSControllerを配置したとします。
ToolsメニューからFungusのフローチャートを作成します。
create

ここで、町の人に話しかけたときのイベントを実装します。新しくブロックを作成し、ブロック名を設定します。
flowchart

町の人に話しかけたときにこのブロック名を指定して呼ぶことによって会話を始めます。

block

町の人のイベントトリガーを作成

Flowchartのblock名を保存するだけのクラスを作り、町の人につけます。

1
2
3
public class BlockTrigger : MonoBehaviour {
public string blockName;
}

block

話しかける/調べるを実装

特定のキーを押したらRayを飛ばして、ぶつかったオブジェクトが上記のBlockTriggerを持っていたら、FungusのFlowchartのblockを実行します。
これをFPSのカメラにAddすれば、見ている方向を調べるコマンドが実装できます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class CheckCommand : MonoBehaviour {
[SerializeField]
float rayLength = 3f;
Flowchart flowchart;
void Start() {
flowchart = FindObjectOfType<Flowchart>();
}
// Update is called once per frame
void Update() {
if (Input.GetKeyDown(KeyCode.E)) { //Eキーに調べるコマンドを割り当てる
Ray ray = new Ray(transform.position, transform.forward);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, rayLength)) {
//衝突したものがBlockTriggerを持っているか調べ、持っていたらそのblockを実行する
var trigger = hit.transform.GetComponent<BlockTrigger>();
if (trigger != null) {
flowchart.ExecuteBlock(trigger.blockName);
}
}
}
}
}

こんな感じで町の人を向いてキーを押すことによってFungusのblockを実行できました。

talk

しかし、このままではメッセージが表示されている間もプレイヤーが移動できてしまいます。
Fungusが動いている間は移動できないように制限しましょう。
Flowchartオブジェクトに以下のようなクラスを追加して実現します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class FlowchartExecution : MonoBehaviour {
Flowchart flowchart;
FirstPersonController fpc;
void Start() {
flowchart = GetComponent<Flowchart>();
//Standard AssetsのFPSのコントローラを取得する
fpc = GameObject.FindGameObjectWithTag("Player").GetComponent<FirstPersonController>();
}
void Update() {
//実行中のフローチャートがあるかチェックし、あれば移動を不可にする
if (flowchart.GetExecutingBlocks().Count == 0) {
fpc.enabled = true;
} else {
fpc.enabled = false;
}
}
}

上記コードだと1点問題があり、選択メニューを表示しているときに動けてしまいます。

選択メニュー

選択メニュー表示中はどこのblockも実行していない待ち状態だからです。
また、FPSコントローラを使用しているとマウスのカーソルがロックされているため、メニューを選択できません。
それらを考慮して上記のコードを改良したのが以下です。

1
2
3
4
5
6
7
8
9
10
void Update() {
var menuDialog = GameObject.Find("MenuDialog"); //メニュー表示中か判定用
if (flowchart.GetExecutingBlocks().Count == 0 && menuDialog == null) {
fpc.enabled = true;
fpc.SetCursorLock(true); //マウスをカーソルロック
} else {
fpc.enabled = false;
fpc.SetCursorLock(false); //マウスのカーソルロックを解除
}
}

コマンドについて

Fungusの各ブロックのコマンドですが、これに関しては見たままなのでここでは特に記載することはありません。
例えば、ドアの処理では以下のように、音を出す→フェードアウト→シーン切り替え とやれば自然になります。
このとき、次シーンの開始時にフェードインコマンドを実行する必要はあります。

シーン切替時のコマンド

コマンドで表現できないものはソース書いてスクリプト実行コマンドを使ったりします。
冒頭の動画にあるようなクエスト完了時のカットシーン的なのもFungusでオブジェクトのアクティブを切り変えたり、iTweenコマンドで動かしたりして実装しています。

クエスト成功カットシーン

セーブについて

町の外でフラグを立てて、シーンを切り替えて建物の中でそのフラグを判定します。
flowchartで変数の管理はできます。

変数

しかし、シーン切り替えが入るので、Fungusのflowchartの変数の値をどこかに保存しないといけません。
幸い、変数のセーブ機能はあります。しかし、変数一つ一つにコマンドを実行しないといけないので結構つらさがあります。

セーブ

ロードに関しても同様です。
ロード

また、保存先はPlayerPrefsなので利用シーンによっては改良する必要があります。

まとめ

セーブ周りがちょっとしんどいですが、簡単なイベントを作るにはFungusは便利です。
RPGツクールを触っていた人間からすると、これが一番しっくりきたアセットでした。

使用バージョン

Unity 5.6.4f1
Fungus 3.6.0

Move To View を改良する

Move To View について

シーンで表示している位置にオブジェクトを動かす機能でMove To Viewがあります。メニューのGameObject-> Move To View (Ctrl + Alt + F)です。
たしかにこれを使うとそれっぽい位置にオブジェクトが移動するのですが、だいたい自分の想像していた位置にはいきません。

シーン

例えば、上記の画像のシーンビューで適当なオブジェクトを選択し、Move To Viewをしたとすると、下記のような位置に移動します。
床をすり抜けて、どこか遠くに置かれ、結局自分で位置を調整することになります。

Move To View後

私の求めているものは、シーンビューのカメラからレイを飛ばして、最初に当たった位置あたりにオブジェクトが移動するMove To Viewです。
というわけでそれを作ります。

エディタ拡張で実装

適当なEditorフォルダを作り、MyMoveToView.csを作り、以下のコードを実装します。
これでGameObject-> My Move To View (Ctrl + Alt + Z) が使えます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using UnityEditor;
using UnityEngine;
public class MyMoveToView {
[MenuItem("GameObject/My Move To View %&z")]
static void Do() {
if (Selection.activeGameObject == null) { return; }
var c = SceneView.lastActiveSceneView.camera;
Ray ray = new Ray(c.transform.position, c.transform.forward);
RaycastHit hit;
if (Physics.Raycast(ray, out hit)) {
Selection.activeGameObject.transform.position = hit.point;
} else {
Selection.activeGameObject.transform.position = c.transform.position;
}
}
}

実行すると、想定した位置に移動できました。

Move To View後

確認バージョン

Unity 5.6.4f1

ゲーム画面外演出を考える

この記事はRPGツクールMV Advent Calendar7日目の記事です。

概要

ゲーム画面(ウィンドウ)の外にピクチャを表示したりして、ゲーム画面外で演出をする方法を考えます。
結論から言うと、かなり面倒くさくてつらく、内容は開発者向けです。少なくともhtmlの知識は必要です。
とりあえず、Windows/Mac 向けを考えます。ブラウザ版では別の考え方をします(後述)。
最後に完成版のプロジェクトファイルを用意するので必要であれば参照してみてください。

ゲーム画面外にキャラが表示されると何割か増しでかわいく見える気がする。

※今回はデュアルディスプレイ環境は考慮しません

フルスクリーンを無効化する

少しずつ実装していきましょう。
まず、ゲーム画面外に出すということは、フルスクリーン時には効果ありません。なのでフルスクリーンにする機能をOFFにします。
ツクールの機能にあるF4キーでフルスクリーンにする機能はプラグインでOFFにできるのですが、ウィンドウの端っこにカーソルを持っていったときに表示されるリサイズや右上の最大化ボタンをプラグインからOFFにすることができません。
これを無効化するにはデプロイ後にpackage.jsonというファイルの中身を書き換える必要があります
package.json

packages.jsonの中身のwindowの箇所に "resizable": false, を以下のように追加します。

1
2
3
4
5
6
7
8
"window": {
"resizable": false,
"title": "",
"toolbar": false,
"width": 816,
"height": 624,
"icon": "www/icon/icon.png"
}

これでフルスクリーンをOFFにできます。しかし、これはデプロイする度に該当箇所を書き換えないといけないので、かなりつらいです。

とりあえず表示してみる

ゲーム画面外に影響させるにはもう1個別のウィンドウを作るしかありません。
nw.js の機能を使って実装していきます。
nw.jsのWindowには openというURLやhtmlファイルを開く機能があり、それを使います。
つまり、imgタグを記述したhtmlファイルを用意すれば、画像が表示されるウィンドウが用意できますね。
MVのプロジェクト直下にsubWindowフォルダを作り、そこにwindow.htmlとして以下のようなhtmlを用意しておきます。

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Project1</title>
</head>
<body style="background-color:rgba(0,0,0,0);">
<img src="../img/pictures/p-stella01.png">
</body>
</html>

そしてツクール側からスクリプトコマンドで以下のようにすると、ウィンドウが表示されます

1
2
var gui = window.require('nw.gui');
gui.Window.open("subWindow/window.html");

window open

いらないウィンドウの装飾とか透明じゃないとかあるけど、とりあえず表示できました。
これでわかるように、htmlならなんでもいいのです。ブラウザデプロイしたMV製のゲームでも……。

ウィンドウの表示をちゃんとする

Window.openの引数にマニフェストを渡せるのでこれで制御できます。

1
2
3
4
5
6
7
8
9
var gui = window.require('nw.gui');
gui.Window.open("subWindow/window.html",{
resizable: false, //最大化、リサイズ不可
toolbar: false, //ツールバー非表示
frame: false, //フレーム非表示
show_in_taskbar: false, // タスクバーに表示しない(注意:開発時はtrueにしておいたほうがいい。タスクバーに表示されないとウィンドウが迷子になる)
transparent: true //透明化
});

ちなみに透明化ですが、Vista以降でclassic themeでないことが条件です。

ゲーム画面とサブウィンドウを関連付ける

ゲーム画面を動かしたらそれに追従してサブウィンドウも移動してほしいですし、ゲーム画面を閉じたらサブウィンドウも閉じるべきです。
まずは、閉じる同期をします。

1
2
3
4
5
6
7
8
9
10
11
var gui = window.require('nw.gui');
var win = gui.Window.get(); //ゲーム画面側のウィンドウを取る
var subWin = gui.Window.open("subWindow/window.html",{
//省略
});
//ゲーム画面の閉じるイベント時にサブウィンドウも閉じるようにフック
win.on('closed', function() {
subWin.close();
});

次にウィンドウ移動の追従です。上記ソースコードの流れで

1
2
3
4
5
win.on("move", function(x, y){
subWin.x = x + win.width; //例えば、ゲーム画面の右側に貼り付ける
subWin.y = y;
});

大雑把に断片ごとに書きましたがこんな感じです。

画像をアニメーションさせる

ゲーム画面外の画像をモニタ左端からゲーム画面に近づくというアニメーションを考えます。
恐らく2つ方法があります。

  1. サブウィンドウのx座標をモニタ左端からゲーム画面まで動かしていく
  2. サブウィンドウを大きめに取り、サブウィンドウ内のimgタグを左端からゲーム画面まで動かしていく

1は失敗でした。ウィンドウのx座標を動かすとすごいカクカクするのです。アニメーションするのに耐えられないです。
2で攻めるしかないです。2はツクールとは関係なく、html、css、js使ってアニメーションを実装すればいいので、ここでは割愛。

こんな感じですね。

ブラウザ版を考える

ブラウザ版はnw.js のウィンドウに出力していたものをそのままiframeに出力すれば良いですね。
これで同じスクリプトコマンドで両方対応できます。

プロジェクトファイルのDL先

Windows/Mac版、ブラウザ版両方とも対応したプロジェクトファイルを以下にアップロードしてあります。
一応プラグイン化もしてあるので、参考にしてみてください。

プロジェクトファイル

ライセンス

プロジェクトファイルに含まれる私が作成したプラグインに関してはMIT Licenseです。

技術的な補足

nw.jsのWindowにはsetResizableというメソッドがあり、これでフルスクリーンをOn/Offできそうなのですが、効きませんでした。

manifestで show: false とするとウィンドウを非表示状態でopenできます。
これを利用してwindowがloadされたあと、showすれば描画前のちらつきをなくせる気がするのですが、なぜかtransparentが効いたwindowでやるとちゃんと描画されなかったのであきらめました。

ニコニコっぽいテキストを表示するプラグイン

概要

現代もののゲームをやるとニコニコ動画的な動画サイトが登場することがあります。そこで、ツクールMVでもそういった表現ができるようにするプラグインを作成しました。
プラグインの仕様、雰囲気は下記動画参照です。

使い方

イメージ図

こういう使い方をします。細かい説明は以下で解説します。

ピクチャとリンク

まずはじめに本プラグイン対象となるピクチャを指定する必要があります。
ピクチャ番号が1のときは、スクリプトコマンドで NLTManager.linkPicture(1); と指定します

文字の表示

文字の表示方法ですが、一番シンプルな方法は以下です。
NLTManager.show('こんにちは');
文字位置指定は以下でできます。ニコニコと同様に naka、ue、shitaに対応しています。デフォルトはnakaです
NLTManager.show('こんにちは', 'ue');
文字色指定は以下でできます。色は white、black、red、blue、orange、green、pink、cyan、purple、yellowです。デフォルトはwhiteです
NLTManager.show('こんにちは', 'ue', 'red');
文字サイズ指定は以下でできます。 使えるのはb、m、s です。デフォルトはmです。big medium、small の略です
NLTManager.show('こんにちは', 'ue', 'red', 'b');
基本的に文字のy位置はランダムです。なので実行ごとに違う結果になります。しかし、演出上必ず決まった位置に表示したい場合もあると思います。
そのときは、以下のように指定できます。 0 ≦ y < 1 の間で指定してください。 0.5で真ん中です。
NLTManager.show('こんにちは', 'ue', 'red', 'b', 0.5);

設定する必要がない、デフォルトで構わない項目はnullでも可
NLTManager.show('こんにちは', null, null, null, 0.5);

ディレイ

NLTManager.show('こんにちは');
NLTManager.show('おはよう');
NLTManager.show('こんばんは');
とすると、3個が同じx位置に表示されてしまい、不自然な感じになるので、それぞれの間にデフォルトで10フレームのディレイが設けられています。
このデフォルトを変えたい場合は以下のようにします。
NLTManager.setDelay(5);

アドリブ

何も表示するテキストがない場合にランダムに表示されるテキストを登録します。パラメータはNLTManager.showと同じです
NLTManager.addAdlib('www', 'naka', 'orange', 's');
この追加した文言は場所移動、セーブ、ロードなどをしても保持されます。なので初期化したいときは明示的に以下のスクリプトを実行してください
NLTManager.clearAdlib();

リンク解除

途中でピクチャと本プラグインの関係を絶ちたい場合は以下を実行します
NLTManager.unLink();
また単純にピクチャを消去すればリンクは解除されます

フォントの設定

font/gamefont.css 内に以下のように本プラグインで使用したいフォントを指定します

1
2
3
4
@font-face {
font-family: ForNico;
src: url("noto.otf");
}

そして、プラグインパラメータに Font とあるのでこれの値を上記例だと「ForNico」に設定します

透明ピクチャを活用

マップ画面全体に適用したいとか、ある領域に描画したいとか、そういうときは透明なピクチャを表示してそれにリンクしてください。
マップ画面全体の場合は816x624の透明画像をピクチャとして表示して、それを本プラグインの対象にするという方法です。

ダウンロード

https://raw.githubusercontent.com/kido0617/rpgmakerMV-plugin/master/NiconicoLikeText/NiconicoLikeText.js

制限事項

  1. ツクールで使用できる制御文字については実装していません。変数値、アクター名は実装する価値はあると思っています。制御文字の文字色、文字サイズ、アイコンはニコニコ感がなくなるので実装する予定はありません。
  2. 複数ピクチャに対して同時に本プラグインを適用することはできません。最後にNLTManager.linkPicture(n)を実行したピクチャが対象です。

ライセンス

MIT
自由にご利用ください。

一括入力がしやすいテキストエディタプラグインの紹介

概要

ツクールのメッセージの一括入力用に4行ごとにボーダーが引かれるVisual Studio Codeのプラグインを作りました。
メッセージを一度テキストエディタでどばっと書いて一括入力で流し込むケースがあると思います。
そのとき、4行区切りになっていると便利だというニーズがあったからです。

4行ごとにボーダーが引かれるエディタ

インストール

まず、Visual Studio Codeをダウンロードします。フリーのマイクロソフト製のエディタです。
インストールしたら起動して、プラグインのインストールボタンを押します。

プラグインのインストールボタン

入力欄に rpgmaker と入力すると rpgmaker-text というプラグインが表示されるのでインストールします。
インストールしたら再読込しましょう。これで有効になっているはずです。

rpgmaker-textをインストール

TIPS

機能をOFFにしたいときは、Ctrl + Shift + P で表示されるコマンド欄でrpgmaker-text:Toggleを選択すればON/OFFを切り替えられます。

On/OFFの切り替え