N煎ログブログ

n番煎じと言っても過言ではない今更な、でも個人的に躓いたUnityやUE4等での開発についての云々を書いていきます

【Maya】選択中の対象を追従&注視し続けるスクリプトを作りました

目次

はじめに

Mayaで色々作業していると、アニメーションの再生中などにある特定の箇所だけ注視して動作を確認したいなどと言った場面が多々生まれます(ました)。

そこで、注視したいオブジェクトを選択した状態でコマンド実行すれば別ウィンドウで注視カメラを作成するスクリプトを作りました。

Image from Gyazo

複数のウィンドウを作成することもでき、別々のオブジェクトを追従させることもできます。

Image from Gyazo

実際に作ったもの

gist.github.com

上記スクリプトを「シェルフに登録して」実行すると使用できます(スクリプトエディタからだと正常に実行できません)。

注意として、ビューポートが選択されていなければウィンドウが作成されないためオブジェクトを選択し、次にビューポート上でカメラ位置を決定してから実行してください。

なぜこんな仕組みにしたのかというと、作業しているビューポートの表示設定をそのまま維持したまま複製させるために複製するビューを決定するためです。

ちなみに、使用されていないカメラやウィンドウUIは実行時に削除するようにしているため、後片付けをしたい場合はウィンドウを全て閉じて何も選択していない状態で実行すれば全削除されます。使用中のウィンドウが閉じられることはありません。

Image from Gyazo

 

【Maya】animCurveUUにキーを打つ方法

目次

はじめに

とある事情からanimCurveUUに対してキーを打ち込みたいなーと思ってたのですが、普通にショートカットSとかで打てるキーではないのでどうしたものかなーと思い悩んでいたところ、OpenMayaAPIを使えば行けるというのを教えてもらえましたので備忘録として書こうかと思います。

結論

いきなり結論から書くと、以下のように書けばキーを追加することができます。

gist.github.com

 animCurveUUは何者

そもそも「animCurveUU」とはなんぞやというとこからですが、

 

tommy-on.hatenablog.com

この記事を参考に見ると、

animCurveUU・・・・・ドリブンキーのスケールとビジビリティカーブ

ということで、通常のキャラクターの動きを作る時とは違い(とは限りませんが。場合によりけり)、Timeではなくドリブンキー(Double)のカーブを扱うためのanimCurveのようです(ドリブンキーについては割愛します)。

ともかくも、そもそもTimeではないためSでキーが打てないということのようです。なので、別にanimCurveUUに限った話ではなく、animCurveUA, animCurveULなど、「animCurveU*」系のanimCurveがドリブンキーのカーブになります。

 

 

【Maya】全ジョイントのスキンウェイトを閾値で二値化するツール作りました

目次

はじめに

ロボものの3Dモデルにはウェイト値って0か1でいいと思うんですよ(唐突)。

もちろんケーブル類とかは除いて、装甲の類とか、いわゆる変形させる予定のない「硬い」部分に関しての話です。

少なくとも現在私が直面している場面ではそのような事態ですので、上のように考えるわけです。

しかし、パーツ一つ一つを手作業でヌリヌリするのも手間だし、かと言ってスキンバインドで自動で塗らせるのも限度があるし...ということで、

「じゃあスキンバインドである程度塗らせて、いらない部分を消して(0.0)、いる部分は1.0にすればいいんじゃね? あとは余計に1.0になっているちょっとの部分を消せばええんや!」

 と思い立ったのが始まりです。

 

実際に作ったもの

gist.github.com

スキンバインドまでを終わらせた段階で、メッシュ選択状態にして上記コードを実行すれば使用できます。

って言っても既にMayaの機能としてありそうではある...

【Maya】Transformだけを一覧化するツールを作りました

目次

はじめに

八耐で作りました(寝坊して15時位から参加しました)。

daihachitai.connpass.com

Mayaで色々作っていて動作検証やバグの確認等している時に、それぞれのオブジェクトの動き等がぱっと見で全て見れない事に若干わずらわしさを感じていました。

CopyTabすれば複数見ることも出来るし、スプレッドシートを使えば一覧化も出来ます。しかし、CopyTabは複数のウィンドウが生成されてしまうし、そもそも不要な情報もコピーされてしまう。スプレッドシートは1つのウィンドウですがアトリビュート情報の更新が行われない(エディタ側で操作した結果が反映されない)。というのがありました。

※その他の「こういう機能あるよ!」的なものがあれば是非教えてください。

実際に作ったもの

表示させたいものを1つ以上選択した状態で以下コードを実行すると、このウィンドウが開かれます。

f:id:isemito:20190422030513p:plain

下のコードをスクリプトエディタ(MEL)にコピペして実行すれば、選択中のオブジェクトの「移動」「回転」「スケール」のみを一覧化したウィンドウが開きます。中身はCopyTab時のものを流用したものなので、ビューワといってもそこから編集をすることもできます。

gist.github.com

とはいえ、まだ非選択状態の処理とか、pory系ノード以外選択時の処理とかを判別しているわけではないので、そこは要修正ですね。

【UE4】FrameGrabberを用いたキャプチャの実装方法を読み解いてみる

目次

はじめに

この記事は、Unreal Engine 4 (UE4) その2 Advent Calendar 2018の9日目の記事になります。

qiita.com

8日目の記事はfumittuさんの

qiita.com

でした。

この記事について

2018/6/27に、おかず(Twitter: @pafuhana1213)さんが以下のような記事を投稿されました。

pafuhana1213.hatenablog.com

ざっくりまとめると、

今までUE4で画面をキャプチャする際には、SceneCapture2DやSceneCaptureComponent2Dという割と重い処理を実行しなければならなかったのを、FrameGrabberというものを使えば軽負荷で実装できる。

というものです。

しかし、FrameGrabberを用いた実装を行うにはC++でコーディングする必要があり、上記記事でもそのことが述べられています。しかし、コード自体の解説は割愛されていたので、私自身の勉強もかねて、git公開されているコード見ていきながらどんなアルゴリズムなのかを探り探り紐解いていきたいと思います。その為、所々間違った解釈等が発生する可能性がありますが、その際にはコメントなどで指摘いただければ修正致します。

記事内容の割愛要素

  • C++ファイルの作成方法
  • 「BeginStart」や「Tick」等、FrameGrabber関連以外の関数解説
  • コードの初期化処理部分

そもそも何をしてるの?

そもそも、なぜFrameGrabberは他のキャプチャ処理に比べて高速なのでしょうか。それは、FrameGrabberのキャプチャの考え方に秘密があります。

「再レンダリング」ではなく「既レンダリング」のフレームを取っている

「FrameGrabber」という名前から察する方もおられるかと思いますが、「SceneCapture2D」や「SceneCaptureComponent2D」(以降「既存キャプチャ」と呼称)は画面をレンダリングしてキャプチャするのに対して、「FrameGrabber」は既にレンダリングされた過去のフレーム(Frame)を取得(Grab)する。というものです。

例えるならば、既存キャプチャはページを毎度印刷して紙を取得していますが、「FrameGrabber」は既に過去に印刷した紙の束のどっかから抜き取って取得している感じです。再レンダリング(印刷)の必要がないので早いのです。

https://1.bp.blogspot.com/-Cfb0kecZndM/Uyk_NP3oESI/AAAAAAAAeNs/sFxyJrF-Qks/s400/printer_woman.png

再度印刷するよりも...

 

https://1.bp.blogspot.com/-ZqQQsOyX8Xc/VD3SYol2_aI/AAAAAAAAoTM/DFXLZg14l7E/s400/school_print_kubaru.png

既に印刷されている物を取り出す方が早いですよね。(出典:いらすとや)

 

FrameGrabberの中身を深く辿ってみる

コード自体を貼るととんでもない行数になる為、public関数だけまとめます。

関数(publicなもののみ) 概要
void StartCapturingFrames() フレームキャプチャを開始させる
void CaptureThisFrame(FFramePayloadPtr Payload) スレート(計画/予定の意だそうで)からイベントを受信した時に、フレームをキャプチャする
【引数】
・Payload(型:FFramePayloadPtr)
 - フレームデータ情報のポインタ
void StopCapturingFrames() フレームキャプチャを停止させる
void Shutdown() FrameGrabberをシャットダウンし、
スレッド操作が完了したことを確認する
TArray<FCapturedFrameData> GetCapturedFrames() キャプチャしたフレーム群を返す

 FFramePayloadPtr

FFramePayloadPtrについては私もまだまだ分からない事が多いので確信をもって言えませんが、「FFramePayloadPtr」は「TSharedPtr」というシェアードポインタをtypedefして付けられたものです。具体的には以下のように定義されています。

typedef TSharedPtr<IFramePayload, ESPMode::ThreadSafe> FFramePayloadPtr

 シェアードポインタについては公式リファレンスがあります。が、「非侵入型、参照カウントのスマートポインタの特別なタイプ」とは一体...うごごご。
api.unrealengine.com

ついでに、FFramePayloadPtrについてもリファレンスがあります。

FFramePayloadPtr | Unreal Engine

MovieSceneCapture

FrameGrabberのヘッダーファイルを見ると「MOVIESCENECAPTURE_API」というマクロ記述がありますので、「MovieSceneCapture」というモジュールであると予想できます。

そこで、もっと掘り下げて「MovieSceneCapture」を見てみると、どうやらここで色々なキャプチャ関連の仕組みを持っている模様?

MovieSceneCapture | Unreal Engine

つまり「FrameGrabber」は、元々(というより元から?)「MovieSceneCapture」の持つ機能の一つだということなのかもしれません。

実際にサンプルコードを見てみる

では実際に、FrameGrabberのサンプルコードを見ていきます。

(Gistを見ると関数名の後に「.cpp」が付いてますが、こうしないとc++向けの見た目にならないためですのでご承知ください)

StartFrameGrab関数

以下の要素のセッティングを行い、FrameGrabberのキャプチャ開始を行う。

  • ビューポートの取得
  • テクスチャの作成
  • マテリアルへのテクスチャ割り当て

gist.github.com

コメント「Get SceneViewport」下の処理に関してはコメントにも書かれていますが、「FRemoteSessionHost::OnCreateChannels()」内の処理を参考にされています(一部不要な処理は省かれています)。 

StopFrameGrab関数

FrameGrabberの実行の停止を行う。

実際にはReleaseFrameGrabber関数が担っている。

gist.github.com

ReleaseFrameGrabber関数

FrameGrabberによるフレーム取得処理の停止とスレッドの終了を行う。

gist.github.com

Capture関数

実際にキャプチャしたフレーム群の中から最後の物を取得し、その色情報をテクスチャに割り当てる。これはTick内で都度行う。

UE4では色情報は(R, G, B, A)ではなく、(B, G, R, A)という並びで、R・G・Bが逆並びであることに注意しなければならないようです。

gist.github.com

FrameGrabber->CaptureThisFrame(FFramePayloadPtr()); 

 ここで今のフレーム情報を確保している一覧に追加し、

FrameGrabber->GetCapturedFrames() 

 ここで今までにため込んだキャプチャ一覧を取得しているようです。

つまり、毎フレーム「CaptureThisFrame関数」でそのフレーム情報を確保するよう処理を行い、「GetCapturedFrames関数」で今までにため込んできたフレーム情報を取得するという事なのだと思われます。

流れをまとめてみる

こんな感じでしょうか(フローチャートではありません)。

f:id:isemito:20181209190733p:plain

まとめ

FrameGrabberの機能とその仕組みについて掘り下げてみてみました。

まだまだ完全に理解出来ているわけではないですが(シェアードポインタとかスレッドセーフとかFFramePayloadPtrとか)、これをもといいつか何か作りたいですね。

本当はこの記事内でFrameGrabberを用いた何かを作ろうと考えていたのですが、まだ思いついてません...。

探り探りの記事作成でしたので、色々と遠回りしたり脱線したりした箇所が多々見受けられるかと思います。それでも最後まで読んでくださった方、ありがとうございます。

最後に、FrameGrabberの存在について記事投稿されたおかず(@pafuhana1213)さんにはこの場をお借りして感謝致します。

【Unity2018】WebGLで外部ブラウザを新規ウィンドウで開く方法

目次

はじめに

いつからか、UnityC#でjavaScriptの関数を呼び出す「Application.ExternalCall」と「Application.ExternalEval」関数が廃止になりました。

これにより、上記関数を用いたjavaScriptの関数が呼び出せなくなり、別の方法でjavaScript関数を呼び出す必要が出てきました。

私の場合、WebGLでリンクをクリックすると新規ウィンドウでそのリンク先を開いてほしかったのですが、「OpneURL」だと同一ウィンドウ内で開いてしまうし、調べても解決方法が見当たらなかったので、先輩の助言のもと、javaScriptを直接呼び出す方法で実装することにしました。

 

途中の諸々を飛ばしたい方は、目次の「Unity(C#)でjavaScriptの関数を呼ぶ方法」からどうぞ

今まではどう実装できたか?

「Application.External~」が使用できていた時は、

Application.ExternalEval(string.Format("window.open('{0}','_blank')", url));

等といった記述で、新規ウィンドウを開いてリンクを開くことが出来ました。

【参考】

belhb.hateblo.jp

EvalとCallの違いは、リファレンスを読む限り、呼び出す関数に引数を含むか含まないかだと思われます。

docs.unity3d.com

docs.unity3d.com

そもそも引数に記述されている内容の意味は?

Application.ExternalEval(string.Format("window.open('{0}','_blank')", url));

 の引数に、

string.Format("window.open('{0}','_blank')", url)

とあるのですが、「string.Format」は「どのような文字列にするか」を指定できる関数になります。そしてこのプログラムの場合、「{0}」には「url」変数の値が入ります。

他にもいろいろ出来るのですが、詳しくはこちらなどを参考に。

www.sejuku.net

 さて、では「string.Format」に渡された引数をもとに出力した文字列に直すと、

 window.open('url','_blank')

 となります(「url」部分は実際にはURLの文字列が入ります)。

では、この「window.open」とは何なのでしょうか。

「window.open」って?

ずばりこれがjavaScriptです!

「Application.ExternalEval」はこの関数を呼び出していたのです!

具体的には、関数名通りウィンドウを開く関数になります。

引数には、「URL」「開くウィンドウの名前」「ウィンドウオプション」が指定できます。

developer.mozilla.org

プロパティについてはこの記事では省略しますが、こちらのサイトに情報が載っています。

amenti.usamimi.info

この時、open関数の第二引数に

nullもしくは_blank

を渡すと、新規ウィンドウが生成されます!

つまりまとめると、

 window.open('url','_blank')

 は「新規ウィンドウでURLのリンク先を開いてね」という関数だということです。

じゃあ、このプログラムをUnityC#で呼べれば新規ウィンドウを開くことが出来ますね!

Unity(C#)でjavaScriptの関数を呼ぶ方法

この方法に至っては、リファレンスの方で誘導がなされていました。

docs.unity3d.com

このページに記述されているURLに飛ぶと、

docs.unity3d.com

このリファレンスに飛びます。

内容をまとめると、

  1. Plugins サブフォルダーの下に .jslib拡張子のファイルを作成
  2. プラグインファイルの中に構文(プログラム)を記述
  3. C#で呼び出す

になります。 

この「2.」で書くプログラムで「window.open」関数を呼び出せば出来そうですね!

書いてみる

まずは、jslibの方を記述していきます。 

※jslibは必ず「Plugins」フォルダ内に作成しましょう!

gist.github.com

書き方はリファレンスを参考に、

独自に追加したのは

OpenToBlankWindow: function (_url) {
    window.open(Pointer_stringify(_url),'_blank')
}, 

 です。

Pointer_stringify

は受け取った文字列をjavaScript文字列に変換します。

次に呼び出すC#側を記述していきます。

gist.github.com

[DllImport("__Internal")]

は、「この関数は外で定義されていますよ」と知らせるものです。

 これで、C#javaScriptを呼び出すことが出来るようになり、window.openを呼び出して新規ウィンドウでリンクを開くことが出来るようになりました。

まとめ

javaScriptC#で直接呼び出してリンクを新規ウィンドウで開けるようになった!

【Unity2017】フェードイン / アウトをUI含めて1スクリプトで制御する

目次

はじめに

フェードイン / アウトはゲームを制作していく過程で導入するのは少なくないと思います。

しかしゲームを制作するたびにこれらの処理やフラグ管理などを作るのは流石に面倒ですし使いまわすにしてもUI周りで扱いづらくなりそうだなと感じました。

そのため、UI周りやフラグも含めて全ての処理を1スクリプトで制御するスクリプトを制作しました。

以下がそのスクリプトです。

delegate, Action共に初めて使うので2つ実装してみました。

 

[追記(2018/03/13)]

  • 一部変数を削除しました。
  • スクリプトをシングルトンにしました。
  • オブジェクトにアタッチしなくても呼び出すだけで自動でUIだけでなくオブジェクト周りも生成するようになりました。

[追記(2018/04/20)]

  • static変数がメンバ変数コード規約「m_」になっていたのを「s_」に修正しました。
  • よくよく見直してみたらプロパティ内で色々生成なりAddComponentなりしちゃってるので、修正案ができ次第修正します。
  • 修正しました(2018/4/21)。が、なんだかややこしいコードになってしまい可読性や管理性がやや低下してしまっているので引き続き代替案が出次第更新します。

スクリプト(delegate版)

gist.github.com

スクリプト(Action版)

gist.github.com

スクリプト(修正版)

github.com

使い方

任意のオブジェクトにスクリプトを貼っつけて、

[追記(2018/03/13)]

  • 不要になりました

[追記(2018/04/22)]

  • アセット処理の初回実行時の前に「CreateInstance」を呼ばなければならないようになりました。
  1. FadeController.CreateInstance(this)でインスタンスを生成しよう(1度だけでOK)
  2. FadeController.Instanceで取得しましょう
  3. FadeIn, Out(フェード時間)で動作します。
  4. FadeIn, Out(フェード時間, 終了後に呼び出す関数)でフェード後に任意の関数を呼び出すことが出来ます。
  5. IsCompleteプロパティからでも終了フラグを取得することが出来ます。
  6. SetColor(色)でフェード色を変えることも出来ます。
  7. 必要なくなったらFadeController.DestroyInstance()で削除しよう

AssetStoreにリリースしました!

AssetStoreに申請し、無事リリースされました!

是非AssetStoreページの方でご評価、コメント等よろしくおねがいします!