アニメーション待ちのwaタグでフリーズするケース

はじめに

ティラノスクリプト ver471 の話です。

先日、アニメーション中にフリーズすることがあるという話があり、調査しました。
その結果、アニメーション待ちをするwaタグでフリーズしていました。

ティラノスクリプトのanimタグの動作は以下のようになっています。

  • アニメーション開始で 現在アニメーションしている数が +1
  • アニメーション完了で 現在アニメーションしている数が -1

waタグは「現在アニメーションしている数が 0 になるまで待つ」というタグなのですが、アニメーション完了が呼ばれないケースがあり、現在アニメーションしている数が一生 0 にならないことがあります。

そのため、waタグの待ちがずっと続いてしまい、フリーズしてしまうという現象がおきます。

フリーズした場合、ティラノライダーで確認してもwaコマンド移行が実行されていません。
waタグでストップしている

ケース1

キャラが2人以上表示されており、一人がアニメーションしていなくて、片方がアニメーションしているときに、chara_hide_allをした場合です。
例を下に示します。

1
2
3
4
5
6
[chara_show  name="akane" ]
[chara_show name="yamato" ]
[anim name=akane left="-=30" time=1000 effect=jswing]
[anim name=akane left="+=30" time=1000 effect=jswing]
[chara_hide_all time="0"]
[wa]

ケース2

アニメーション中にfreeimageしても同様にフリーズします。

1
2
3
4
5
[chara_show  name="akane" ]
[anim name=akane left="-=30" time=1000 effect=jswing]
[anim name=akane left="+=30" time=1000 effect=jswing]
[freeimage layer=0]
[wa]

簡単な説明

簡単に言うと、chara_hide_allfreeimageもアニメーション中の対象を削除します。削除するのでアニメーション完了が呼ばれません(chara_hide_allに関してはもう少し特殊ですが)。

chara_hide_allに関してソースコードレベルで該当箇所を知りたい場合はこちら
freeimageの場合はこちら

現状とれる対処

chara_hide_allfreeimageの前でwaを呼び、アニメーション完了を待ってから消す。

ピクチャの色あいを変えるプラグイン

概要

前回、色相を変えるプラグインを作りましたが、今回は色合いを変えます。
色合いを変えると以下の動画のように白い服に対して着色できます。

プラグインコマンド

SetTint arg0 arg1
arg0はピクチャ番号、arg1は色の値。下記2つは同じ

  • 例: SetTint 1 0xFF0000
  • 例: SetTint 1 16711680

引数には変数の制御文字が使えます。

  • 例: SetTint \V[3] \V[4]

RGBそれぞれに値を指定する場合は以下です。
SetTint arg0 arg1 arg2 arg3
arg0はピクチャ番号、arg1、arg2、arg3にはrgbの値を指定

  • 例: SetTint 1 255 0 0

引数には変数の制御文字が使えます。

  • 例: SetTint \V[3] \V[4] \V[5] \V[6]

リセットするには0xFFFFFFを指定します。

  • 例: SetTint 1 0xFFFFFF

ダウンロード

こちら

色相を変えるプラグインと同一です。
色相を変えるプラグインはRotateHue.jsでしたが、今回統合してPictureColorChange.jsになりました。
申し訳ないのですが、RotateHue.jsは削除してこちらに差し替えてください(プラグインコマンドは同じなのでファイル差し替えのみ)。

ピクチャ合成について

ピクチャ合成系のプラグインには対応していません。ピクチャ合成もピクチャを加工するため、色あいを変えて合成すると競合してしまいます。対応するにはピクチャ合成プラグインとこちらのプラグインを両方セットで調整しなければなりません。

ライセンス

完全に自由にどうぞ。
クレジットの表記もいりません。

ピクチャの色相を変えるプラグイン

概要

ピクチャの色相を変えるプラグインを作りました。
デフォルトでは色調を変えることはできますが、色相は変更できません。
色相を変えると以下の動画のように自然な感じで色違いのピクチャを作れます。

以下のような色相環をぐるっと360度回す感じになります。
白や黒、モノクロの画像は色相を変えても色は変化しませんので注意が必要です。

色相環

ちなみに色調はtone、色相はhueです。

プラグインコマンド

RotateHue arg0 arg1
arg0はピクチャ番号、arg1はデフォルトからの色相の回転角度。単位は度

  • 例: RotateHue 1 180

引数には変数の制御文字が使えます。

  • 例: RotateHue \V[3] \V[4]

角度なので0~359が有効な値ですが、-180、360、720などを入力は可能です。
デフォルトからの回転角度なのでRotateHue 1 180を2回呼んでも360にはなりません。

ダウンロード

こちら

色あいを変えるプラグインと同一です。
色相を変えるプラグインはRotateHue.jsでしたが、今回統合してPictureColorChange.jsになりました。
申し訳ないのですが、RotateHue.jsは削除してこちらに差し替えてください(プラグインコマンドは同じなのでファイル差し替えのみ)。

ピクチャ合成について

ピクチャ合成系のプラグインには対応していません。ピクチャ合成もピクチャを加工するため、色相を変えて合成すると競合してしまいます。対応するにはピクチャ合成プラグインとこちらのプラグインを両方セットで調整しなければなりません。

ライセンス

完全に自由にどうぞ。
クレジットの表記もいりません。

技術的な解説

色相を変えるメソッドはデフォルトで実装はされていて、Bitmap.prototype.rotateHue がそのメソッドです。 敵キャラの色相変更で利用されています。
これを呼べば簡単にできるのですが落とし穴があり、Bitmapをそのまま書き換えます。
何が問題になるかというと、キャッシュです。画像はロードするとキャッシュされますが、色相をいじるとキャッシュした画像をそのまま書き換えてしまい、その画像はずっと色相が変わったままになってしまいます。

一つの解決策としてロード時に色相を指定することが挙げられます。
ImageManager.loadNormalBitmap = function(path, hue)とあるようにhueを指定してBitmapをロードできます。実はデフォルトでは色相つきでキャッシュされています。敵キャラの色相の変更がそうなっています。
以下の箇所でキャッシュのキーを生成しているのですが、画像のパスと色相でキーを作っています。この組み合わせのキーでキャッシュを検索して、存在すればキャッシュの画像を使用し、なければロードするということです。

1
2
3
ImageManager._generateCacheKey = function(path, hue){
return path + ':' + hue;
};

一見、hue付きでロードすれば解決するように見えますが、ちらつきの問題があります。
プリロードしようにも画像+色相の組み合わせをプリロードするのは無理があります。
なので今回は、色相を弄る前の画像をコピーして色相を変える方法でこれを回避しています。

BGSを保存・再開するスクリプト(VXAce版)

この記事はVXAce版です。MV版はこちら

概要

BGMと同様にBGSについても保存と再開を可能にするスクリプトです。

スクリプトコマンド

BGSの保存: $game_system.save_bgs
BGSの再開: $game_system.replay_bgs

ダウンロード

ライセンス

完全に自由にどうぞ。
クレジットの表記もいりません。

スプレッドシートからjsonデータを読み込む

概要

結構前にスプレッドシートからデータを読み込むの記事でOAuth2の認証をしてスプレッドシートを読む実装をしました。
ですが、こんなことしなくてもスプレッドシート側でGETのリクエストを受け取ってデータをjsonにして返せば大体事が足ります。
今回はビルド前にスプレッドシートからデータを読み込み、保存するエディタ拡張を作ります。

スプレッドシート側の実装

スプレッドシート側は「Google Spreadsheet を簡易 Webサーバーとして動かして、手軽にWebHookを受け取る方法」の記事を参考にして実装します。
今回は翻訳データを例に、以下のようにGETの処理を実装しました。

1
2
3
4
5
6
7
8
9
10
function doGet(e){
//本当はスプレッドシートからデータを作るけれど、今回は適当にデータを用意
var test = {
bullet : {Ja: "弾丸", En: "Bullets"},
shot: {Ja: "ショット", En: "Shot"}
}
var output = ContentService.createTextOutput(JSON.stringify(test));
output.setMimeType(ContentService.MimeType.JSON);
return output;
}

Unity側でエディタ拡張として実装

以下のようにエディタ拡張として実装します。Editorフォルダを作り、GetWordJson.csとして保存します。
WWWクラスを使用して、レスポンスを受け取ります。
受け取った結果はLitJsonを使用して、クラスに変換します。
このとき、レスポンスはwww.textで受け取れるのですがこれを使用しようとすると、Unsupported encoding: 'UTF-8,text/html'とエンコーディングのエラーが出るのでwww.bytesからUTF8に変換して渡します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System.Text;
using UnityEditor;
using UnityEngine;

public class GetWordJson {
public class Word {
public string Ja;
public string En;
}

//メニューのtest に GetWordJsonを追加
[MenuItem("test/GetWordJson")]
public static void Get() {
WWW www = new WWW("https://script.google.com/macros/s/AKfycby-XVXs5qJl1v26Y1xxxxxxxxxxxxxxxxxxxxxxxxVx8inwe/exec");
while (!www.isDone);
if (www.error != null) Debug.LogError(www.error);
else {
var obj = LitJson.JsonMapper.ToObject<Dictionary<string, Word>>(Encoding.UTF8.GetString(www.bytes));
}
}
}

以下のようにobjに翻訳辞書データが入っているのがわかります。

jsonを受け取り変換した結果

この結果を元にScriptableObjectにしても良いですし、そもそもjsonのまま保存して実行時にパースしても良いです。
jsonのまま保存する場合は以下のようになります。

1
2
3
4
5
var path = Application.dataPath + "/Words.json";
StreamWriter writer = new StreamWriter(path);
writer.WriteLine(Encoding.UTF8.GetString(www.bytes));
writer.Close();
AssetDatabase.Refresh();