Google

2015年6月15日月曜日

Unrealの使いにくさを再実感

機能比較のためにUnty5とUnreal Engineで同時に小規模なアプリの実装を試みてみた。
デスクトップ用なのでパフォーマンスをさほど気にしなくて良かったのは幸いなのだけど、無駄に遠回りが多かった。
中身は書けないので、概要とか探し方の備忘録記事ってことで。

元々Unrealの使いにくさは以前から感じていたのだけど、Unityで簡単にできる事をやってみようとしたらやっぱり使いにくい事を再実感、、、。
そもそも英語コミュニティにすら質問だけしか挙がってないことが多いのが困りもの。

なので、今までやったことがないことで実現したいことがある場合、以下の方法を取ってみた。

  • Unityでの機能名をそのまま英語にしてUnrealを付けて検索
  • 機能名は表現の違いというか方言があるので、コミュではそのまま検索しても大抵だめ
  • できるだけ公式リファレンスから用語を合致させて検索
  • BluePrintの例があったら動画や画像とにらめっこ

これで大分情報が拾えたのが助かった。
Unityと違って大半のヒントが公式にあって日本語モードがあったのが救いだったかも。

自分用備忘録ってことでUnityとの違いで気づいた点とかを列挙。

  • 単純なClling Mask機能が無い
  • サブカメラは2台目カメラだけじゃダメ。SceneCaptured2Dに写してテクスチャで貼る
  • レベルBluePrint以外からLevel上のActorを参照する時は、All Actors ClassからForeachLoopで目的の型にキャスト
  • カメラ付きマチネを有効化すると実行時にそっちが優先される
  • カメラ付きマチネは編集時にディレクター部分を切らないとエディタカメラと同一化して混乱する
  • C++に慣れてるならそっちで書いてBluePrintに公開する方が簡単
  • BluePrint操作時に、ノードから伸ばして出る一覧と右クリックして出る一覧は内容が違う
  • マチネの自前追加イベントは参照時にBluePrintノードをリロードしないと出てこない
  • 原因不明エラーという酷い内容のエラー時は大抵処理ノードのつなぎ忘れ

とにかく落ちるのは勘弁して欲しい。
リファクタリングして参照が切れた時に固まって落ちるのは何回見たことか、、、、。

うーん、すさまじく抽象的かつ愚痴だらけな記事になってしまった。
ディスってばかりですみません。
環境光等ではやっぱりUnrealが上なのは間違いない模様。
使いやすさではUnityがまだ大分有利かと。

2015年6月9日火曜日

Unity4.6で64bit版の審査

備忘録のおはなし。

Unity4.5.xで安定動作するiOSアプリをバージョンアップ申請したら、大分時間が経ってからリジェクトされてしまった。

確か最後に申請したのが5月下旬ごろ。
リジェクト食らった時点で6月に入ってるから、もう32bit版は受け付けてくれない。
こんなに遅れたのはもしかして、アップル審査チームが64bitへの移行騒ぎでカツカツだったのかも知れない。
が、あータイミング悪すぎ、、、。

本来こういう記事は事前予測の上6月前に書くべきなんだろうけど、古いプロジェクト変換の備忘録のために記事を作っておく事に。

さて、32bit版のUnityプロジェクト(実は自作プラグイン込み)を移行せねば。
Unity5にするのも時間が掛かりそうでお客さんを待たすのも何だったしで、とりあえずUnity4.6.5p1を準備し、プロジェクトを読み込んでみた。
プロジェクト自体の互換性はあるので、ビルドを64bitにすべく設定変更開始。

Unityのプロジェクト設定を開いて、Configrationグループを見つける。
そこからScripting BackendをMono.2.xからIL2CPPに変更。




こうしないと64bitの追加が選択肢に入らない。
同、ArchitectureがあるのでそれをUniversalに。
armv64単体だと古い機種が動作不可能になるので、これは仕方なし。


これでBuildし、XCodeプロジェクトを生成。
予想通り、今までの生成時間より体感で倍近く掛かるようになった。

生成されたXCodeプロジェクトを開いたら設定に移動。
TARGETからUnity-iPhoneを選択し、Build SettingsタブからArchitecturesグループを探す。
既に存在するStandard Architecturesにすればarmv7, arm64のファットバイナリにしてくれる。
後は同グループのBuild Active Architecture OnlyをReleaseだけNOにする。



うちの都合ではあるものの、ターゲットが7.0以降という事情があるので、GeneralタブからDeployment infoグループを探し、Deployment Targetを7.0である事も確認。
Unity側でターゲット設定してあるから今回は特に問題なし。



さあこれで後は実機で動作実験、、、と思ったらこんな問題が待っていた。

 1. 自作プラグインで実装していたauto release廻りの処理が変更に
 2. OnGUIで出す座標が@2xのような等倍での指定になっていた
 3. 自作プラグインで別のUIViewを親子関係付けする際、UnityViewの生成タイミングが変わったらしく、最初に取得して使いまわそうとしたらぬるぽだった(必要時に取るだけでOKだった)

2. はデバッグ出力用なのでどうでも良かったのだけど、1. はUnityの内部でクラッシュしてしまい、一瞬焦ってしまった。
宜しくないコードの修正にもなって良かったといえば良かったんですが。
参考にもならんのでしょうが、4.5からの移行で発生したという事の記録なんで、読みに来た人にはお役に立ちませんがご勘弁を。

後はいつもどおりメニューのProductからArchiveし、OrganizerからValidate、Submitでアップロード完了。

こっちはどうにかなったけど、もしかしたらサードパーティでarmv7にしか対応してないライブラリを使っているプロジェクトとか、大変な思いをしてるんじゃないだろうかと勝手に予測。
XCode側のarm64リンケージでエラーが大量に出るはずだし。

で、今回のオチですが、レガシープロジェクトは安定してる時期に切り替えた方がいいという教訓を学べたということで。

2015年5月7日木曜日

UIScrollViewのキャプチャiOS8版

突発思い出し記事です。

仕事中にUIScrollViewのキャプチャがしたくて探したものの日本語記事が見当たらず。
いや、あるにはあるんですが、iOS8以降の記事がなんかなかったので備忘録として記載します。

そもそも単にUIScrollViewのキャプチャがしたいと思ってやり方忘れてたので検索。
よくあるコンテキストを持ってきて、UIImageに、、、ってやったら画像が途切れてしまってる。
うーん、気づいたらiOS8で仕様が変わってたみたい。
皆さん知ってるんだろうけど何故か記事が、、(探し方が下手?)

で、海外の記事で解決策がちらっとあったんですが、それがこんな方法でした。

・自分でUIViewを作ってその下にスクロールビュー付けてキャプチャすればいい

ただ、サンプルがSwiftだったので、自分でObj-Cにすることに。
ってことで適当に書いてみました。


- (UIImage*)imageFromView:(UIScrollView *)view
{
        // 戻りを準備
        UIImage *capturedImage;
        // 撮影専用のUIViewを準備
        UIView* tmp_view = [[UIView alloc] init];
        // スクロールビューのサイズを準備
        CGRect scr_rect = CGRectMake(0, 0, view.contentSize.width, view.contentSize.height);
        // 撮影用ビューのサイズをスクロールビューと同一に
        tmp_view.frame = scr_rect;
        // 注!ここも大事
        view.frame = scr_rect;

        // あとはよくあるパターンで。撮影用ビューが対象である点に注意。
        UIGraphicsBeginImageContextWithOptions(view.contentSize, NO, 0.0f);
        CGContextRef context = UIGraphicsGetCurrentContext();
        [tmp_view.layer renderInContext:context];
        capturedImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();

        return capturedImage;
}

もしスクロールビューの位置が一番上じゃないのなら、これを入れて強制的に一番上にする必要があります。


        view.contentOffset = CGPointMake(0,0);

最初はこれで行けると思ってたら、やっぱり画像が途切れてしまうはめに。
スクロールビューには2つのサイズが有ることを忘れて、下線の部分が抜けていた訳です。
要は全体サイズと枠サイズがあり、窓でクリッピングされている関係からキャプチャされる画像も窓で切られてしまっていたという事でした。
なのでここでスクロールビューのサイズも全体にすることで、やっとこさ希望する処理になりました。

あとは大事な点として、上記コードでは一時的なUIViewにスクロールビューを子供として紐付けてしまっているため、撮影が成功したら元に戻さなくてはなりません。
窓枠やスクロール位置なども一緒に戻す必要もあります。
autorelease等も必要に応じて入れるのもお忘れなく。


2015年4月17日金曜日

RuntimeSTLLoader ver 1.2.0

再度手前味噌の記事です。

ver1.1.0から間が開いてしまいましたが、本日RuntimeSTLLoader ver1.2.0をリリースいたしました。
変更点はバグ修正以外にURLからのダウンロード機能追加になります。

今までこの機能を入れなかった理由ですが、.netのファイル読み書きライブラリ、例えばSystem.IO.File等がWebPlayerモードではエラーを発生させるという点でした。
これはUnityのせいでもなんでもなくWebモードでファイルアクセスはセキュリティも含めた問題回避等が理由になるので仕方がないですね。

しかしこれはUnityだと変な形でモードに関わってきます。
例えばデモ用のシーンをWebPlayerモードにした状態で実行すると、その瞬間にSystem.IO.Fileが使えませんと文句を言ってきたりします。
これがモードを切り替えた瞬間ではなく実行時でないと出ないとう点が以外な曲者で、気付かずに作業してると突然エラーになってミスの内容を探し直したりとかするわけです。
importの時点でエラーになればいいのにそれ自体はエラーが出ないという仕様ですし。
Unityがたまに起動時に勝手にWebPlayerモードにしてくれるという、良くわからない本体の仕様?かなんかで変えられてると突然エラーになったりして焦ったりもしました。

しかしお客様にはそんな混乱をさせるわけには行きません。
WebPlayerモードでのファイルからの読み込みは、#ifで区切って処理をさせずに終わらせるようにしてあります。
ちなみに以前からそうなっていますので今回でそうした訳ではありません。

逆にURLからのダウンロードは殆どの環境で使用可能なWWWクラスで実装しました。
このクラスにも問題が多々ありますが、、、まあ仕方なく使ってる感はあります。
使い方はファイルの時と似ていて、URLを指定する形なのであんまり変わりません。

// 本体のインスタンスを取得
RuntimeStlLoader loader = RuntimeStlLoader.getInstance();
if (m_stl_instance != null)
{
Destroy(m_stl_instance);
}
loader.loadMeshFromUrl(
m_url, // URL
m_stl_base_prefab, // STLの原型プレハブ
null, // 親(オプション)
OnCompleteLoadUrl); // コールバック関数

ちなみにURLはプロトコルを付けても付けなくてもどちらでも大丈夫です。
博物館から落とせるURLを直接指定するというのも有りです。
もし簡単なサンプルが必要でしたら以下をお使いください。

http://www.angework.co.jp/pub/angework_logo.stl

ファイル版と違う点は、WWWがIEnumratorでコルーチン処理になる関係からコールバックで処理完了を通知するようになっているところ位でしょうか。
これで一応ひと通りの場所からロードできるようにはなりました。

あと、1.1.0の時に出し忘れていたのですが、MeshがUntiyで管理しきれないサイズのSTLをプレハブ化したらどうなるか?の見本を出しときます。

これは馬鹿でかい球体をSTLにしてロードしてみた例です。

シーン見るだけででかいのが想像できるかと思われ
これが表示中のインスタンスです
65kで分割してるのに15個もできてしまいました。
で、これをver1.1.0で追加したプレハブ化をしてみたのが以下です。


プレハブはインスタンスと同じ構造なのがお分かり頂けるかと。

問題はメッシュ。
やっぱりメッシュも分割して15個になってしまいました。
これが各々同じ番号のプレハブに紐付けられる形になってます。


STLの解析が単純なため、近いパーツ単位で分けるという器用な真似はまだ出来ません。
今後はこの辺の頭を賢くしたり、リダクションをしたりというバージョンアップを考えています。
STLのfbx化も、、、やっぱ必要ですかね。

2015年2月19日木曜日

RuntimeSTLLoader ver1.1.0

当商品をバージョンアップしました。
基本的な部分はあまり変化がありませんが、使いやすさと変換機能を搭載しました。
更新内容はこちら。
  1. STL生成先をルートか既存オブジェクトの下から選択可能
  2. デモシーンの大幅変更
  3. お手持ちのSTLをデモシーンで簡単に表示
  4. プロジェクト上のSTLパス抽出機能を追加
  5. Mesh抜き出しとプレハブ化
順を追って説明していきます。


1.STL生成先をルートか既存オブジェクトの下から選択可能

これは本体へのちょっとした修正です。
以下は前回書いた呼び出しの手順。

 public GameObject m_stl_base_prefab;
 void Start() {
  // RuntimeStlLoaderインスタンスの呼び出し
  RuntimeStlLoader loader = RuntimeStlLoader.getInstance();
  // STL生成
  GameObject obj = 
   loader.loadStlToScene(
     loader.getPlatformPath() + "RuntimeStlLoader/Stl/" + "angework_logo.stl",
     m_stl_base_prefab,
     gameObject);
 }

呼び出しの引数の最後の部分、parentを指定すべき部分にnullを入れるとシーンルートに生成を行うようにしました。
これはちょっとした使い勝手向上という感じ。


2.デモシーンの大幅変更

デモシーンを色々と強化して当プラグイン自体にも役立つユーティリティとして使って頂く形にしてみました。


デモシーンを起動すると上のような画面になります。
画面上のボタン構成はこうです。
  • 埋め込んだ弊社ロゴSTLを表示するボタン
  • プロジェクト上のSTLパスを記載してもらうエリア
  • (b)のパスからSTLを読み出すボタン
  • 現在表示中のSTLをMeshとプレハブに吐き出すボタン
  • 現在表示中のSTLをクリアするボタン
これらが機能を持っている訳ですが、説明は順繰りで。


3.お手持ちのSTLをデモシーンで簡単に表示
4プロジェクト上のSTLパス抽出機能を追加

この2つはグループです。
デモシーンは今まで同梱されていた弊社ロゴしか表示しませんでした。
(a)のボタンは1.0.0と同一で、予めデモに埋め込んだ弊社ロゴSTLを出すだけの機能で、それを踏襲しています。
なので押せば単純に前回とほぼ同じ結果になるだけです。

ロゴが出るだけ
ですがデモとしてはそれも不便だったので、プロジェクトに別のSTLを追加してパスを指定して簡単に表示するようにしてみました。
これが(b)と(c)のGUIに関係します。

まずはその辺で拾ってきたSTLファイルをこのPluginが入ったプロジェクトにインポートして下さい。
プロジェクトへのインポートは通常通りD&Dで問題ありません。
インポートしたら必ずUnityEditor上でデモシーンを「実行」する必要があります。
そして、実行状態のままで、そのSTLファイルを右クリックして下さい。

するとこんな風に追加されたメニューがでてきます。
この時、間違った選択をしていると正しく動作しません(エラーにはなりませんが)。
そしてこのメニュー項目を選択すれば、デモ画面の(b)、テキストエリアにそのファイルパスが埋め込まれます。

こんな感じに文字列が入ります。
後はそのテキストエリアの下にある(c)ボタンを押すだけ。
要はこの(c)のボタンは、テキストエリアに指定されたプロジェクト上パスから読み出すというボタンになります。

ご存知の方も多いかとは思いますが、このパスはAssetsから始まる形式です。
当然ながら自力で指定してもいいのですが、それを毎回書くのも嫌だろうと勝手に思い込んで付けた訳です。



5.はサンプルとして同梱したテストシーンに追加した便利機能です。
STLからMeshとプレハブを生成するという代物です。
では実演。


このSSのようにSTLを表示した状態で下から2番目のボタン(d)を押すと、、、

こんなメッセージが出て
プロジェクトにMeshとプレハブが生成されます。
エクスプローラーで見るとこんな感じ
プロジェクトのルートに生成するのですが、その際のファイル名はこういう法則です。

  • StlMesh.asset
  • (インスタンス名).prefab

既に同一名のファイルがあると失敗します。
そして、一旦プレハブ化してしまえば、それはそのままシーンに持っていけるようになります。
ある意味このツール要らずになるのですが。

コンバートしたプレハブのプロパティはこんな感じ
FBXに比べれば自由度は減りますが、Maya等の3Dツールが不要な変換機能が追加されたという事になりますでしょうか。


今回のまとめ

要はこのデモシーンを使って、STLファイルをインポート、パス指定、プレハブ化というシーケンスを簡易に行うツールになるという訳です。
別の見方をすれば、わざわざSTLを表示するツールなのに、プレハブにすることでその存在意義が無くなるというバージョンアップでもありますがw

なお、デモシーン自体はUnityEditor上でしか正しく動作しませんのでご注意を。
本体はWebPlayerを除く大抵の環境で動作します。


宜しければ弊社公式サイトも併せて御覧ください。
http://www.angework.co.jp/products/Unity/RuntimeStlLoader.html

2015年2月3日火曜日

RuntimeStlLoaderの使い方

先日発売した「Runtime STL Loader」ですが、技術寄りの商品なので解説します。
言うまでもなく、実行時にSTLファイルをロードする商品なんですけど、もうちょっと詳しく。

元々作ったきっかけはUnityにSTLを読み込む機能がなかったことでした。
というか3Dプリンタ関係の仕事上必要ではあったのですが、そこまで難しいフォーマットではないし、AssetStoreにもなかったんで作ってしまえばいいかと考えた次第。
で、UnityEditor上で実行前に読み込むという要求がなかったので、実行時にロードするようにしたわけです。

つまり、実行時に関数を呼び出して使って頂くことになります。
さて、実演の前に準備しておくものがこちら。(パッケージには全て同梱してあります)
  1. STLファイル(テキスト・バイナリ問わず)
  2. STLのひな形となるプレハブ
  3. STLインスタンスの親となるGameObjectインスタンス
1.は当然必須ですが、製品パッケージにはサンプルとして弊社ロゴのSTLファイルが同梱されています。
別に大した価値はありませんが、再配布ができないSTLが多いので自作物を入れてみました。

このSTLファイルは実行時にUnityが読み込める場所にあることが前提です。
例えばiOSの場合、審査に引っかからない場所(Documents/)等に配置しなければなりません。
他OSも同様で、STLファイルは起動時に存在してもダウンロードしても関係なくロード可能です。(※現時点ではWebPlayerにだけ対応していません)
Unity側からコールする関係上、ディレクトリ指定は環境別にpersistentDataPath等で正しく指定してください。

続いて2.は動的にGameObjectを生成するための、ほとんど空っぽのプレハブです。
パッケージには同梱されていますが、簡単に自分で作ることもできます。

STL用プレハブの手動作成方法:
  • まずEmptyのGameObjectを生成します(MenuのGameObject→Create Empty)
  • Mesh FilterコンポーネントをAddします(Mesh指定は空っぽでOK)
  • Mesh RendererコンポーネントをAddします
  • お手持ちのMaterialコンポーネントをAddします(シェーダや色はお好みで)
    • 無ければProjectウィンドウのCreateからMaterialで作成して下さい
これでSTL表示用プレハブとして使えます。
ちなみに同梱済のMaterialはDeffuseでカラーはホワイトにしてあります。
将来的にはこの手順も自動化してもいいんですが、大した作業ではないので現時点ではサンプルを添付する形にさせて頂きました。

最後に3.ですが、STLインスタンスの親となるGameObjectインスタンスを何かしら準備してください。用途に応じてですがなんでも結構です。
これはUnityがポリゴン頂点数65k以上に対応していない仕様をどうにかするためのものでして、オーバーする場合は複数のGameObjectに分割して生成するようにしているのが要因です。
なので、1個かどうかに関係なく親を指定してもらい、その下に連ねるという形です。

これらが準備できたら以下のコードをMonoBehaviour派生クラスに書き込んでシーン上に作った管理用GameObject等にアタッチします。
publicメンバのm_stl_prefabに先程のSTLプレハブをアタッチするのをお忘れなく。

 public GameObject m_stl_base_prefab;
 void Start() {
  // RuntimeStlLoaderインスタンスの呼び出し
  RuntimeStlLoader loader = RuntimeStlLoader.getInstance();
  // STL生成
  GameObject obj = 
   loader.loadStlToScene(
     loader.getPlatformPath() + "RuntimeStlLoader/Stl/" + "angework_logo.stl",
     m_stl_base_prefab,
     gameObject);
 }

上記の例ですと、親GameObjectは呼び出している自分自身として生成します。
ディレクトリはパッケージに同梱したサンプルという事になります。

戻りは保存してもしなくてもOKですが、成功すればSTLのメッシュが埋め込まれたGameObjectインスタンスが返ってきます。(失敗時はnullが戻ります)
また、成功すればシーン上にSTLのMeshが表示されます。

こんな感じで表示されます

なお、この製品の用途ですが、STL表示以外の重要な用途も紹介させて頂きます。
  1. STLのMeshを抜き出す
  2. プレハブ化する
  3. リダクションを諦めたSTLを表示する
a.ですが、Meshを抜き出すことで別のGameObjectへ紐付けて生成させることが可能になる、という点がポイントです。
現在手動でやる必要がありますが、次回以降で1タッチ生成ぐらいの手間省きは考えてます。

b.も同様ですが、こちらの場合はプレハブ化してしまうためBlender等で変換をいちいち行う必要すらなくなります。
これもスクリプトを毎回書かなくてよいように、自動化する予定です。

c.はBlender等を使って変換しようにも、リダクションすら有効に機能しないようなモデルを表示するために使えるというメリットです。
限界突破した場合はオブジェクトを分割して作るので、基本クラッシュせずに表示が可能になります。(負荷問題やUVはまた別)

Runtime STL Loader
公式リンク:
http://angework.com/products/Unity/RuntimeStlLoader.html
AssetStore:
https://www.assetstore.unity3d.com/jp/#!/content/28511

再度の手前味噌記事で失礼いたしました。

2015年1月30日金曜日

Runtime STL Loaderを販売開始しました

手前味噌なので恐縮ですが一応ここで宣伝。

Unity AssetStoreで「Runtime STL Loader」というスクリプトを発売させて頂きました。
これは3Dプリンタで使われる「STL」というファイル形式をUnityで読み込めるようにするものです。

NASAのパイオニア号を表示した例
GameObjectとして操作可能です。
弊社のロゴがサンプルでついてきます。

仕事上、どうしても必要だったので自前で作ったものを出しただけです。
自力でなんでも描画できる人には不要かも知れませんが、簡単に済ませたい方にはそこそこ役立つかと。

できることはこんな感じです。

  • 実行時にSTLファイルをシーンに読み込む
  • テキスト、バイナリを自動的に判別しロード
  • GameObject上にSTLのMeshを構築
  • Unityの制限である頂点数65kの問題に対応

何に使うのか?はそれぞれ違うと思いますので、この業務専用とはまでは言いませんが、一応これで仕事になってはいます。

Unity Asset Storeはこちら
サポートページはこちら

出したばかりなので基本的なことしかできません。
ちまちま更新するつもりですが、次バージョン以降で追加する予定はこんな感じ。
(全て行う保証はありませんが)

  • 読み込んだSTLのMeshを保存(Unity Editor上 Only)
  • STLファイルのプレハブ化
    • 一応1,2行追加で書けば今でも可能は可能
  • ミラーコピー
  • マテリアル簡易変更
BlenderではなくこちらでもSTLを表示したりプレハブに変換できるというメリットはあります。
具体的な使い方についてはここで今後書いていく予定。

以上宣伝でした。