【Maya】選択中の対象を追従&注視し続けるスクリプトを作りました
目次
はじめに
Mayaで色々作業していると、アニメーションの再生中などにある特定の箇所だけ注視して動作を確認したいなどと言った場面が多々生まれます(ました)。
そこで、注視したいオブジェクトを選択した状態でコマンド実行すれば別ウィンドウで注視カメラを作成するスクリプトを作りました。
複数のウィンドウを作成することもでき、別々のオブジェクトを追従させることもできます。
実際に作ったもの
上記スクリプトを「シェルフに登録して」実行すると使用できます(スクリプトエディタからだと正常に実行できません)。
注意として、ビューポートが選択されていなければウィンドウが作成されないためオブジェクトを選択し、次にビューポート上でカメラ位置を決定してから実行してください。
なぜこんな仕組みにしたのかというと、作業しているビューポートの表示設定をそのまま維持したまま複製させるために複製するビューを決定するためです。
ちなみに、使用されていないカメラやウィンドウUIは実行時に削除するようにしているため、後片付けをしたい場合はウィンドウを全て閉じて何も選択していない状態で実行すれば全削除されます。使用中のウィンドウが閉じられることはありません。
【Maya】animCurveUUにキーを打つ方法
目次
はじめに
とある事情からanimCurveUUに対してキーを打ち込みたいなーと思ってたのですが、普通にショートカットSとかで打てるキーではないのでどうしたものかなーと思い悩んでいたところ、OpenMayaAPIを使えば行けるというのを教えてもらえましたので備忘録として書こうかと思います。
結論
いきなり結論から書くと、以下のように書けばキーを追加することができます。
animCurveUUは何者
そもそも「animCurveUU」とはなんぞやというとこからですが、
この記事を参考に見ると、
animCurveUU・・・・・ドリブンキーのスケールとビジビリティカーブ
ということで、通常のキャラクターの動きを作る時とは違い(とは限りませんが。場合によりけり)、Timeではなくドリブンキー(Double)のカーブを扱うためのanimCurveのようです(ドリブンキーについては割愛します)。
ともかくも、そもそもTimeではないためSでキーが打てないということのようです。なので、別にanimCurveUUに限った話ではなく、animCurveUA, animCurveULなど、「animCurveU*」系のanimCurveがドリブンキーのカーブになります。
【Maya】全ジョイントのスキンウェイトを閾値で二値化するツール作りました
目次
はじめに
ロボものの3Dモデルにはウェイト値って0か1でいいと思うんですよ(唐突)。
もちろんケーブル類とかは除いて、装甲の類とか、いわゆる変形させる予定のない「硬い」部分に関しての話です。
少なくとも現在私が直面している場面ではそのような事態ですので、上のように考えるわけです。
しかし、パーツ一つ一つを手作業でヌリヌリするのも手間だし、かと言ってスキンバインドで自動で塗らせるのも限度があるし...ということで、
「じゃあスキンバインドである程度塗らせて、いらない部分を消して(0.0)、いる部分は1.0にすればいいんじゃね? あとは余計に1.0になっているちょっとの部分を消せばええんや!」
と思い立ったのが始まりです。
うーん...ロボものだからウェイトペイントは0か1でいいんだけど(少なくとも今は)、一つ一つぬりぬりしていくの面倒だなぁ...せやっ雑にボクセルペイントさせた後閾値0.5より上か下かで0か1にウェイト値自動で書き換えさせればええんや
— イセミト (@isemito_niko) May 5, 2019
実際に作ったもの
スキンバインドまでを終わらせた段階で、メッシュ選択状態にして上記コードを実行すれば使用できます。
って言っても既にMayaの機能としてありそうではある...
【Maya】Transformだけを一覧化するツールを作りました
目次
はじめに
八耐で作りました(寝坊して15時位から参加しました)。
Mayaで色々作っていて動作検証やバグの確認等している時に、それぞれのオブジェクトの動き等がぱっと見で全て見れない事に若干わずらわしさを感じていました。
CopyTabすれば複数見ることも出来るし、スプレッドシートを使えば一覧化も出来ます。しかし、CopyTabは複数のウィンドウが生成されてしまうし、そもそも不要な情報もコピーされてしまう。スプレッドシートは1つのウィンドウですがアトリビュート情報の更新が行われない(エディタ側で操作した結果が反映されない)。というのがありました。
※その他の「こういう機能あるよ!」的なものがあれば是非教えてください。
実際に作ったもの
表示させたいものを1つ以上選択した状態で以下コードを実行すると、このウィンドウが開かれます。
下のコードをスクリプトエディタ(MEL)にコピペして実行すれば、選択中のオブジェクトの「移動」「回転」「スケール」のみを一覧化したウィンドウが開きます。中身はCopyTab時のものを流用したものなので、ビューワといってもそこから編集をすることもできます。
とはいえ、まだ非選択状態の処理とか、pory系ノード以外選択時の処理とかを判別しているわけではないので、そこは要修正ですね。
【UE4】FrameGrabberを用いたキャプチャの実装方法を読み解いてみる
目次
はじめに
この記事は、Unreal Engine 4 (UE4) その2 Advent Calendar 2018の9日目の記事になります。
8日目の記事はfumittuさんの
でした。
この記事について
2018/6/27に、おかず(Twitter: @pafuhana1213)さんが以下のような記事を投稿されました。
ざっくりまとめると、
今までUE4で画面をキャプチャする際には、SceneCapture2DやSceneCaptureComponent2Dという割と重い処理を実行しなければならなかったのを、FrameGrabberというものを使えば軽負荷で実装できる。
というものです。
しかし、FrameGrabberを用いた実装を行うにはC++でコーディングする必要があり、上記記事でもそのことが述べられています。しかし、コード自体の解説は割愛されていたので、私自身の勉強もかねて、git公開されているコード見ていきながらどんなアルゴリズムなのかを探り探り紐解いていきたいと思います。その為、所々間違った解釈等が発生する可能性がありますが、その際にはコメントなどで指摘いただければ修正致します。
記事内容の割愛要素
- C++ファイルの作成方法
- 「BeginStart」や「Tick」等、FrameGrabber関連以外の関数解説
- コードの初期化処理部分
そもそも何をしてるの?
そもそも、なぜFrameGrabberは他のキャプチャ処理に比べて高速なのでしょうか。それは、FrameGrabberのキャプチャの考え方に秘密があります。
「再レンダリング」ではなく「既レンダリング」のフレームを取っている
「FrameGrabber」という名前から察する方もおられるかと思いますが、「SceneCapture2D」や「SceneCaptureComponent2D」(以降「既存キャプチャ」と呼称)は画面を再レンダリングしてキャプチャするのに対して、「FrameGrabber」は既にレンダリングされた過去のフレーム(Frame)を取得(Grab)する。というものです。
例えるならば、既存キャプチャはページを毎度印刷して紙を取得していますが、「FrameGrabber」は既に過去に印刷した紙の束のどっかから抜き取って取得している感じです。再レンダリング(印刷)の必要がないので早いのです。
再度印刷するよりも...
既に印刷されている物を取り出す方が早いですよね。(出典:いらすとや)
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のキャプチャ開始を行う。
- ビューポートの取得
- テクスチャの作成
- マテリアルへのテクスチャ割り当て
コメント「Get SceneViewport」下の処理に関してはコメントにも書かれていますが、「FRemoteSessionHost::OnCreateChannels()」内の処理を参考にされています(一部不要な処理は省かれています)。
StopFrameGrab関数
FrameGrabberの実行の停止を行う。
実際にはReleaseFrameGrabber関数が担っている。
ReleaseFrameGrabber関数
FrameGrabberによるフレーム取得処理の停止とスレッドの終了を行う。
Capture関数
実際にキャプチャしたフレーム群の中から最後の物を取得し、その色情報をテクスチャに割り当てる。これはTick内で都度行う。
UE4では色情報は(R, G, B, A)ではなく、(B, G, R, A)という並びで、R・G・Bが逆並びであることに注意しなければならないようです。
FrameGrabber->CaptureThisFrame(FFramePayloadPtr());
ここで今のフレーム情報を確保している一覧に追加し、
FrameGrabber->GetCapturedFrames()
ここで今までにため込んだキャプチャ一覧を取得しているようです。
つまり、毎フレーム「CaptureThisFrame関数」でそのフレーム情報を確保するよう処理を行い、「GetCapturedFrames関数」で今までにため込んできたフレーム情報を取得するという事なのだと思われます。
流れをまとめてみる
こんな感じでしょうか(フローチャートではありません)。
まとめ
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));
等といった記述で、新規ウィンドウを開いてリンクを開くことが出来ました。
【参考】
EvalとCallの違いは、リファレンスを読む限り、呼び出す関数に引数を含むか含まないかだと思われます。
そもそも引数に記述されている内容の意味は?
Application.ExternalEval(string.Format("window.open('{0}','_blank')", url));
の引数に、
string.Format("window.open('{0}','_blank')", url)
とあるのですが、「string.Format」は「どのような文字列にするか」を指定できる関数になります。そしてこのプログラムの場合、「{0}」には「url」変数の値が入ります。
他にもいろいろ出来るのですが、詳しくはこちらなどを参考に。
さて、では「string.Format」に渡された引数をもとに出力した文字列に直すと、
window.open('url','_blank')
となります(「url」部分は実際にはURLの文字列が入ります)。
では、この「window.open」とは何なのでしょうか。
「window.open」って?
ずばりこれがjavaScriptです!
「Application.ExternalEval」はこの関数を呼び出していたのです!
具体的には、関数名通りウィンドウを開く関数になります。
引数には、「URL」「開くウィンドウの名前」「ウィンドウオプション」が指定できます。
プロパティについてはこの記事では省略しますが、こちらのサイトに情報が載っています。
この時、open関数の第二引数に
nullもしくは_blank
を渡すと、新規ウィンドウが生成されます!
つまりまとめると、
window.open('url','_blank')
は「新規ウィンドウでURLのリンク先を開いてね」という関数だということです。
じゃあ、このプログラムをUnityC#で呼べれば新規ウィンドウを開くことが出来ますね!
Unity(C#)でjavaScriptの関数を呼ぶ方法
この方法に至っては、リファレンスの方で誘導がなされていました。
このページに記述されているURLに飛ぶと、
このリファレンスに飛びます。
内容をまとめると、
になります。
この「2.」で書くプログラムで「window.open」関数を呼び出せば出来そうですね!
書いてみる
まずは、jslibの方を記述していきます。
※jslibは必ず「Plugins」フォルダ内に作成しましょう!
書き方はリファレンスを参考に、
独自に追加したのは
OpenToBlankWindow: function (_url) {
window.open(Pointer_stringify(_url),'_blank')
},
です。
Pointer_stringify
は受け取った文字列をjavaScript文字列に変換します。
次に呼び出すC#側を記述していきます。
[DllImport("__Internal")]
は、「この関数は外で定義されていますよ」と知らせるものです。
これで、C#でjavaScriptを呼び出すことが出来るようになり、window.openを呼び出して新規ウィンドウでリンクを開くことが出来るようになりました。
まとめ
javaScriptをC#で直接呼び出してリンクを新規ウィンドウで開けるようになった!
【Unity2017】フェードイン / アウトをUI含めて1スクリプトで制御する
目次
はじめに
フェードイン / アウトはゲームを制作していく過程で導入するのは少なくないと思います。
しかしゲームを制作するたびにこれらの処理やフラグ管理などを作るのは流石に面倒ですし使いまわすにしてもUI周りで扱いづらくなりそうだなと感じました。
そのため、UI周りやフラグも含めて全ての処理を1スクリプトで制御するスクリプトを制作しました。
以下がそのスクリプトです。
delegate, Action共に初めて使うので2つ実装してみました。
[追記(2018/03/13)]
- 一部変数を削除しました。
- 各スクリプトをシングルトンにしました。
- オブジェクトにアタッチしなくても呼び出すだけで自動でUIだけでなくオブジェクト周りも生成するようになりました。
[追記(2018/04/20)]
- static変数がメンバ変数コード規約「m_」になっていたのを「s_」に修正しました。
- よくよく見直してみたらプロパティ内で色々生成なりAddComponentなりしちゃってるので、修正案ができ次第修正します。
- 修正しました(2018/4/21)。が、なんだかややこしいコードになってしまい可読性や管理性がやや低下してしまっているので引き続き代替案が出次第更新します。
スクリプト(delegate版)
スクリプト(Action版)
スクリプト(修正版)
使い方
任意のオブジェクトにスクリプトを貼っつけて、
[追記(2018/03/13)]
- 不要になりました
[追記(2018/04/22)]
- アセット処理の初回実行時の前に「CreateInstance」を呼ばなければならないようになりました。
- FadeController.CreateInstance(this)でインスタンスを生成しよう(1度だけでOK)
- FadeController.Instanceで取得しましょう
- FadeIn, Out(フェード時間)で動作します。
- FadeIn, Out(フェード時間, 終了後に呼び出す関数)でフェード後に任意の関数を呼び出すことが出来ます。
- IsCompleteプロパティからでも終了フラグを取得することが出来ます。
- SetColor(色)でフェード色を変えることも出来ます。
- 必要なくなったらFadeController.DestroyInstance()で削除しよう
AssetStoreにリリースしました!
AssetStoreに申請し、無事リリースされました!
是非AssetStoreページの方でご評価、コメント等よろしくおねがいします!