はじめに
Unity上でLWFを再生するにあたって
実際にあれこれと試してみたことについて書いていきます。
環境
system | version |
---|---|
Mac OS X | 10.9 |
Unity | 4.3.1 |
LWF | 1.0.2 |
LWFS | 20131119-1217 |
Adobe Flash CS6 | 12.0.2.529 |
TexturePacker | 3.2.1 |
準備する
LWF
本体。これがないと始まらない。
ダウンロード
https://github.com/gree/lwf
ここから git clone
もしくはZIPファイルで取得する。
ビルド
ソースコードのままでも問題ないけど
私は dll にしたものを使用しているのでビルドします。
$ cd lwf/csharp/unity/build
$ ls
Packager
Rakefile
$ rake
$ ls
Packager
Rakefile
lwf.dll
lwf.dll.mdb
lwf_editor.dll
lwf_editor.dll.mdb
Unityプロジェクトにセット
lwf.dll
lwf_editor.dll
lwf/csharp/unity/shaders
をそれぞれ下記のように配置する。
Assets/
Editor/
lwf_editor.dll
Plugins/
lwf.dll
Resources/
shaders/*.shader
以前のバージョンでは
lwf.dll -> lwf_editor.dll の順番でimportしないとUnityがクラッシュしていたが
今は大丈夫そう。
ソースコードのまま使用する場合は下記にある unitypackage を利用するとインポートが楽。
lwf/csharp/unity/dist/lwf.unitypackage
LWFS
LWFへの変換と確認を簡単にしてくれるツール。
ダウンロード
http://code.google.com/p/lwfs/downloads/list
ここから環境にあったものを取得する
私はMacを使用しているので LWFS-osx-20131119-1217.zip を選択。
インストール
Applicationディレクトリに置くだけ。
$ unzip LWFS-osx-20131119-1217.zip
$ mv LWFS /Applications/
README に書かれていますが
OS X Marvericks を使用している場合は下記を実行する必要があるようです。
$ xattr -d -r com.apple.quarantine /Applications/LWFS
これをしないと壊れている的なメッセージが出ました。
起動
start.app
をダブルクリック。もしくは下記コマンドを実行する。
open /Applications/LWFS/start.app
デスクトップに変換元と変換後の出力ディレクトリが作成される。
~/Desktop/LWFS_work # 変換元ファイル置き場
~/Desktop/LWFS_work_output # LWF変換後の出力先
また、起動と同時にLWF用のパブリッシュが可能な
Publish for LWF
コマンドがFlashにインストールされる。
インストール先
~/Library/Application\ Support/Adobe/Flash\ CS6/ja_JP/Configuration/Commands/Publish\ for\ LWF.jsfl
アニメーションデータ作成
Flashムービー作成
下記点に気をつけながら作成する。
- Flashのパブリッシュターゲットは Flash Player 7 にする
Publish for LWF が調整してくれるようです!
-
シェイプは使えないので画像ファイルにする
-
ムービークリップの回転はできるがムービークリップ内の画像を回転させるとLWF変換時にエラーとなる
現在の swf2lwf.rb では改善されているようです!
- ActionScriptは使用不可(stop,playなどの簡単なアクションは使用可能)
- 但し
mc.gotoAndStop()
のようにムービークリップを指定した操作はできない
- 但し
tellTarget()
が使えるそうです!これで代替可能ですね。
tellTarget("mc") {
gotoAndStop();
}
tellTarget("..") {
gotoAndStop();
}
* トゥイーンはクラシックトゥイーンのみ使用可能
* マスクは使用できない
* ビットマッププロパティの圧縮は「劣化なし」にする
* 「劣化なし」でない場合 ERROR: Bitmap is as JPEG. Bitmap should be as 'Loss-less' となる
> *Publish for LWF* が調整してくれるようです!
* ムービークリップへの着色はできない。明度の設定は可能。
* 詳細カラー設定の乗算値によって代用はできるかもしれない。但し、加算値は'0'としておくこと
* 使用できるようにする方法はある
### パブリッシュ
コマンド -> `Publish for LWF`
* パブリッシュ前
test/
└─ test.fla
* パブリッシュ後
test/
├─ test.fla
├─ test.swf
└─ test.bitmap/*.png
## FlashをLWFに変換
### LWFSを使用する場合
swfやbitmapが入ったディレクトリを `~/Desktop/LWFS_work` に置くと
`~/Desktop/LWFS_work_output/unity` にLWFデータが出力される。
```sh
$ mv test ~/Desktop/LWFS_work
$ ls ~/Desktop/LWFS_work_output/unity
test
手動で行う場合
現バージョンでは ruby 1.9.3 以降が必要。
要求rubyバージョンは今後変わる可能性が高いので rbenv かなんかで
複数バージョン扱えるようにしておくと良いかも。
# LWFに変換
$ ruby lwf/tools/swf2lwf/swf2lwf.rb test.swf
# 不要なファイルを削除(情報としては有用)
$ cd test.lwfdata/
$ ls |grep -v -E "\.lwf|\.png" |xargs rm
# 拡張子変更
$ mv test.lwf test.bytes
# Publish時に作成された画像ファイルをもってくる
$ mv ../test.bitmap/*.png ./
LWFデータをUnityプロジェクトにインポートする
下記のように Resources の中に入れる。
管理しやすいように LwfData を用意したがResources直下でも可。
Assets/
Resources/
LwfData/
test/
動かしてみる
Unity上で動かす
LWFObjectを継承したクラスを用意する。
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
public class LwfSampleObject : LWFObject {
void Start() {
string dir = System.IO.Path.GetDirectoryName(lwfName);
if (dir.Length > 0) {
dir += "/";
}
if (Application.isEditor) {
UseDrawMeshRenderer();
}
Load(lwfName, dir);
}
}
空のGameObjectを作成し上記スクリプトを Add Component
する。
Lwf Name パラメータにbytesファイル名 LwfData/test/test
を拡張子なしでセット。
再生用のスクリプトを用意し、GameObjectに Add Component
すると再生されます。
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
public class Play : MonoBehaviour {
public LwfSampleObject lwfObject;
void Start() {
lwfObject.GotoAndPlayMovie("_root", 1, true);
}
}
Unity上での表示位置について
Flashのステージサイズを640x960とした場合、GameObjectのx,yはそれぞれ半分の-320,480とするとカメラの中心に表示される
Unity側からムービークリップを操作する
- フレーム番号で指定
this.GotoAndPlayMovie("_root", 1, true);
- ラベルで指定
this.GotoAndPlayMovie("_root", "label", true);
Flash側の組み方として
_root には1フレームにアニメーションの1シーンを置く形の方が扱いやすいので
下記のような呼び方をよく使用しています。
public void PlayScene() {
this.GotoAndPlayMovie("_root", "scene1", true);
this.GotoAndPlayMovie("scene1", "part1", true);
}
ムービークリップからUnityに通知する
アニメーションの特定の位置でUnity側に処理をさせたい場合
例えば指定の位置で音を鳴らす等
その場合、ムービークリップ内に fscommand()
を入れることで通知できます。
// "event”は固定。第二引数にイベント通知名を入れる。
fscommand("event", "sendMessage");
Unity側でイベント通知を受けるには SetEventHandler()
を使い
第一引数に受信したいイベント通知名を入れる。
void Start() {
// …
Load(lwfName, dir);
SetEventHandler("sendMessage", (movie, button) => {
// ここにイベント通知された時に行いたい処理を書く
});
SetEventHandler("animationEndMessage", (movie, button) => {
// 受信したいイベントが複数ある場合はその分定義する。
});
}
これらイベント通知機能とラベルによるフレーム移動があれば大抵のことは実現できると思います。
テクスチャ入れ替え
Unity側からLWFのテクスチャを入れ替えるために LwfSampleObject に
ChangeTexture メソッドを追加する。
public void ChangeTexture(Texture2D newTexture, string targetTextureName) {
var cache = LWF.UnityRenderer.ResourceCache.SharedInstance().textureCache;
if (cache != null) {
if (cache.ContainsKey(targetTextureName)) {
var cache_item = cache[targetTextureName];
var tex_context = cache_item.Entity();
tex_context.material.mainTexture = newTexture;
}
}
}
使い方: sample.png を別のテクスチャに入れ替える場合
ChangeTexture(newTexture, "test/LwfData/test/sample");
第二引数: LWF名 + テクスチャファイルパス(拡張子なし)
テクスチャ入れ替え時の注意点
同じLWFを複数箇所で同時に再生している場合
テクスチャを入れ替えるとすべてのLWFのテクスチャが入れ替わります。
特定のLWFのテクスチャのみ入れ替えたい場合はFlash側で予めテクスチャを分けておいてあげる必要があります。
画像をTexturePackerでまとめる
1. パブリッシュ
コマンド -> Publish for LWF
2. テクスチャアトラス作成
TexturePacker で画像をまとめてjson形式で出力する。
コマンドラインでやる場合は下記
/Applications/TexturePacker.app/Contents/MacOS/TexturePacker --scale 0.93750 --format json --data test.json --sheet "texture.png" test/test.bitmap/*.png
scale については各自調整してください。
3. LWFデータ作成
jsonファイルを指定して変換処理を行う。
# LWFに変換
$ ruby lwf/tools/swf2lwf/swf2lwf.rb test.swf test.json
後の処理は以前と同じです。
複数テクスチャアトラスを使用する
1枚に収まりきらなかった場合は複数のjsonを指定することで可能。
# LWFに変換
$ ruby lwf/tools/swf2lwf/swf2lwf.rb test.swf test1.json test2.json
テクスチャアトラス使用時のテクスチャ入れ替え
テクスチャアトラスを使用すると以前のやり方でのテクスチャ入れ替えができないため
入れ替えを行うテクスチャだけアトラスとは別に個別で持たせました。
その場合特に何か処理をする必要はなく
jsonに含まれていないテクスチャは勝手に個別扱いにしてくれます。
入れ替え用テクスチャについて
そのまま使用はしないため何も描かれていない画像を使用。
さらに無駄を省くため下記もかけています。
pngquant --ext .png --force 256 ./*.png
加算合成が使いたい
アニメーションのクオリティを上げるためにやっぱり加算合成がしたい!
と言われたのでデフォルトでは使えない加算合成をできるようにしてみます。
とはいっても、LWFには元々加算合成の機能が組み込まれているのでそれを利用するだけですが!
(速度が遅くなるためデフォルトではオフになっているそうです。)
加算合成機能を有効にする
機能を有効にしたdllに作り直す。
$ cd lwf/csharp/unity/build
$ vim Rakefile
$ rake
Rakefileの変更箇所
desc "build"
task :build do
puts "lwf.dll:"
- system "#{MONO_BIN}/gmcs #{LIBS} #{MONO_OPTS} -out:lwf.dll #{SRCS.join(' ')}"
+ system "#{MONO_BIN}/gmcs #{LIBS} #{MONO_OPTS} -out:lwf.dll #{SRCS.join(' ')} -define:LWF_USE_ADDITIONALCOLOR"
puts "lwf_editor.dll:"
- system "#{MONO_BIN}/gmcs #{EDITOR_LIBS} #{MONO_OPTS} -out:lwf_editor.dll #{EDITOR_SRCS.join(' ')}"
+ system "#{MONO_BIN}/gmcs #{EDITOR_LIBS} #{MONO_OPTS} -out:lwf_editor.dll #{EDITOR_SRCS.join(' ')} -define:LWF_USE_ADDITIONALCOLOR"
end
加算合成用にシェーダーを書き換える
既存のシェーダーでは加算値は反映されないので
LWFPreMultipliedAlpha.shader をいじります。
Shader "LWF/PreMultipliedAlpha" {
Properties {
+ _AdditionalColor ("AdditionalColor", Color) = (0, 0, 0, 0)
_Color ("Color", Color) = (1, 1, 1, 1)
_MainTex ("Texture", 2D) = "white" {}
}
SubShader {
Tags {
"Queue" = "Transparent"
"IgnoreProjector" = "True"
}
Cull Off
ZWrite Off
Blend One OneMinusSrcAlpha
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
uniform half4 _MainTex_ST;
fixed4 _Color;
+ fixed4 _AdditionalColor;
struct v2f {
float4 pos: SV_POSITION;
float2 uv: TEXCOORD0;
fixed4 color: COLOR;
};
v2f vert(appdata_full v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
o.color = v.color * _Color;
return o;
}
fixed4 frag(v2f i): COLOR0
{
+ fixed4 color_result = tex2D(_MainTex, i.uv.xy) * i.color;
+ if (color_result[0] != 0) {
+ color_result += _AdditionalColor;
+ }
+ return color_result;
- return tex2D(_MainTex, i.uv.xy) * i.color;
}
ENDCG
}
}
}
おわりに
LWFは簡単にアニメーションを複数プラットフォームで動かすことができる良いツールだと思います。
ただ情報がまだまだ少なくて結構大変でした。
この記事が少しでもこれから使う方への参考になれば嬉しいです。
ちなみにどこかおかしい点等あればご指摘頂けると助かります!
色々試しながら使っていたので使い方が違うものもあるかもしれません。。
謝辞
@splhack さんにアドバイス頂きました。ありがとうございます!
https://gist.github.com/splhack/8006982