VRキーボードのためにキーボードを封印したお話
はじめに
ちょっと前にGOROmanさんがこんなことを言っていました。
目指しているのは キーボード、マウス、ゲームパッド というレガシーインターフェースからの脱却
— GOROman@謙虚 (@GOROman) November 1, 2016
マウスとキーボードは叩き壊す予定です https://t.co/HLCCt7qmFS
— GOROman@謙虚 (@GOROman) November 29, 2016
じゃあ実際にやってみよう!!ってことでやりました。
マウスを封印するお話はいくつか聞いたことがありますが、キーボードを封印するお話は聞いたことがなかったので面白いかなと。
キーボードという概念をぶっ壊すために、とりあえず明日から年内はハードウェアなキーボード、スマホのキーボード、仮想キーボードなどを封印します
— てんちょー (@shop_0761) December 20, 2016
(自分の作ったVRキーボードを除く)
キーボードやめます(とりあえず年内だけ pic.twitter.com/z1sZM9jk0x
— てんちょー (@shop_0761) December 20, 2016
VRキーボードを除いたのはTwitterができない可能性があったので一応保険的な意味です。(結局使わなかった
条件
キーボードと名のつくものを封印します。
例として
- PC向けの普通のキーボード
- スマホで使えるキーボード類
- ATM等の数字を入力する系のキーボード
などを封印しました。基準としては、数字や文字を選択してからEnterで確定するものをキーボードと定義しました。
事前準備
使ってるマイクはこれ
http://www.yodobashi.com/ec/product/100000001001262667/index.html
ATM
(今更だけど ATMからお金下ろせなくなるのでは)
— てんちょー (@shop_0761) December 20, 2016
ビビったのでATMで少し下ろしてきた
— てんちょー (@shop_0761) December 20, 2016
Cortana
cortana 蘇生成功
— てんちょー (@shop_0761) December 20, 2016
ピクチャパスワード
win10 ピクチャパスワードなるものを知ってキー入力を回避できることが分かった
— てんちょー (@shop_0761) December 20, 2016
こういうのを使おうかなとhttps://t.co/UkZ60FHliQhttps://t.co/6SouwWoJ7a
— てんちょー (@shop_0761) December 20, 2016
特に書いてませんが、Siriのセットアップもしました。
だが
— てんちょー (@shop_0761) December 20, 2016
音声認識ツールの使い心地
Cortana
対話式なので、一気にしゃべらないといけない点を除いて多分1番精度がいい。
だができることが少ない。もったいない。後述のwindows音声認識の機能を全てCortanaで出来るようにすればもっといい。
認識精度が良すぎなので、これを作った。なお全て音声認識で記事を書いてます。
スクリプトはさすがにコピペ祭りですが。
windows音声認識
windowsの操作が色々できるので便利っちゃ便利。 CortanaだとEnterができないので、その度にこいつでEnterを入力していました。
一応ここまで出来る。
@shop_0761 pic.twitter.com/PuEr5rZyUR
— てんちょー (@shop_0761) December 20, 2016
未来感ありますね!! ただ非常に面倒。(何回も撮り直しをしている
コマンド一覧はこちらに。
https://support.microsoft.com/ja-jp/help/12427/windows-speech-recognition-commands
多分こいつは教育できるので精度は上がる…はずなんですが、
そういえば昨日隣で他の人が電話してる時に.ウィンドウズ音声認識が全く使えないケースがあって笑った
— てんちょー (@shop_0761) December 28, 2016
と、ほぼ部屋に一人の状態かつ、BGMもかけられない感じでアレです はい。
Siri
Siri自体も簡単なセットアップがあるのですが、なぜかHeySiriで起動しない…
それもあってあまり使っていない…
けど、副産物的に利用できるようになる音声入力がありました。
こいつが意外と使えます。対話式ではないので、多少考えながら発話できます。
ただ、途中で変換予測が変わったりして荒ぶったりすることもありますが。
iPhoneにもAndroidのパターンロックが使えるようになって欲しい…(指紋認証できるけど、ミスると結局キー入力なのでロックを切ってた
使ってみた感想
いいところ
意外と生活できるし、メールも返信できました。
かなり良く無いですか pic.twitter.com/b8BZThRMlv
— てんちょー (@shop_0761) December 22, 2016
ただ時々思ったように変換してくれなくて、不必要な部分をカットしたり、ペーストしてツギハギしたりしてました。
主婦さん(@Somelu01)さんとも普通にDMしたりできました。
てんちょーさんとDMしてたの、全部音声認識で入力されてたって、言われるまで全くきづかなかった。すごい。 pic.twitter.com/UkfY2Bdu6B
— Somelu (@Somelu01) December 22, 2016
そして、手が疲れない!!大事!!
悪いところ
誤認識時の修正が面倒。 固有名詞が認識できない。(これは辞書がないのでしゃーないけど
打ちたい内容がダダ漏れ。 居間とかでTwitterが出来ないし、話しかけたと思われてしまう。
コードが書けない。
不思議なお話
音声認識を使っていて変な違和感が出てきた話をすると、最初はなんとも無いんだけど、段々喋ると認識されてしまうと思うのか、余計なタイミングで喋ってはいけないのではという心持ちにさせられた
— てんちょー (@shop_0761) December 31, 2016
これ、結構不思議な話で、ある程度意識的に口を閉ざしている場面が幾つかあり、なぜか無口になる時がありました。
多分なんですが、音声認識される環境に居続けると余計な発言までも認識されてしまうと思ってしまい不必要な発言を避けてしまうのかも。
これはこれで卒論が書けてしまいそうですね…
まとめ
音声認識 割りといける。Juliusも使ったことがありますが、未調整のと比べるとかなり精度がよくなってきています。
一度Cortanaを封印しないで使ってみては?
コルタナの音声認識の結果をクリップボードに貼り付けるスクリプトを書いてみた
はじめに
キーボードを封印して音声認識だけで生きています
この記事も音声認識だけで書いています
コルタナの音声認識の結果がかなり良いのでそれを利用したいと思いパワーシェルのスクリプトを書いてみました( なおキーボード封印中
今回書いたもの
スクリプト更新しました( 2017年1月4日 簡単なDebug出来るようにしました
追記 2017/01/04
以下のスクリプトをパワーシェルに貼り付ける分には動くっぽいのですが、.ps1にするとアウトっぽいので取り急ぎdropboxのリンクを貼っておきます
時間がある時に修正します…
while(1) { $psArray=[System.Diagnostics.Process]::GetProcesses() $str="" foreach ($ps in $psArray){ if($ps.MainWindowTitle -like "*Microsoft Edge"){ #[System.Console]::WriteLine("Microsoft Edgeを発見 Handle: " + $ps.Handles + " MainWindowTitle: " + $ps.MainWindowTitle) Add-Type -AssemblyName system.Windows.Forms $cp=[Windows.Forms.Clipboard] $ps.MainWindowTitle.foreach{ if($_ -match "(.*)\s[-]\sBing"){ #[System.Console]::WriteLine("Bing検索してるMicrosoft Edgeを発見") $str=$matches[1] if($str -match "コピー終了"){ [System.Console]::WriteLine("終了します") $ps.CloseMainWindow() $ps.Close() exit } $cp::SetText($str) [System.Console]::WriteLine("$str") $ps.CloseMainWindow() $ps.WaitForExit(3000) $ps.Close() break } } } } }
これをパワーシェルのスクリプトで起動します
コルタナは反応に困ったらマイクロソフトエッジのbing検索を使うので、
マイクロソフトエッジのプロセスを監視してそのメインウィンドウのタイトルから正規表現で認識結果を切り取ります
追記ここから
スクリプトを更新しました
これでコピー終了というとスクリプトを停止できます
ダブルクリックで実行できるファイルを作る
このスクリプトをメモ帳などに貼り付けて、.ps1形式で保存した後に、ショートカットを作成します
そのショートカットのプロパティからリンク先の先頭に以下のように追加します
powershell -NoProfile -ExecutionPolicy Unrestricted "ファイル名"
これで適用するとpowershellの部分が勝手にpowershellがある場所のパスに変わりますがおっけーです
実質、powershell~Unrestricted までコピーして、ファイル名の前に貼っ付ければ終わりです
そうするとダブルクリックで起動できます
後はpowerShellが起動するので、コルタナに話しかけてbing検索する際にMicrosoft Edgeが一瞬起動しますが、 勝手に閉じて、クリップボードにその結果が貼り付けられてます。
ログが一応powerShellの方に表示されます。
追記ここまで
まとめ
パワーシェルのスクリプト初めて書きました
人に読ませる文書にするにはちょっと大変だけど音声認識でとりあえずここまできました
これでとりあえず快適にツイッターができます
【UE4】OculusTouchでHapticEffectが使えないとき
PlayHapticEffectが動かない
Touchのコントローラの振動にはPlayHapticEffectを使えとあります。
要約すると、ここからHaptic用アセットを作って適用できるよと。
- Haptic feedback Effect Buffer 数値指定
- Haptic feedback Effect Curve カーブで指定
- Haptic feedback Effect Sound Wave 音声ファイルから生成
と3つあります。
今回は適当にカーブを作りました。
でHapticEffectに入れて終わり。あとは好きなところで。
これで使えるようになります。
しかし、手を抜きたいあまり、Riftのセンサーを片手で塞ぎながら空いてる手でデバッグすると反応しませんでした。
どうやらTouchを持った時に生じる揺れ(人の手は完全に静止しないので)をTriggerにしてるようです(勘)。
なので両方持つか、ちゃんと被るか、足にでもつけるかしないと振動しません。
【UE4】簡単な音声認識をしてみた
はじめに
裏 Unreal Engine 4 (UE4) Advent Calendar 2016 10日目です。
本記事の主役とも言えるほげたつさんのアセットのレビューがされている こちらの記事も合わせてお読みください(何ももらってませんよ)
今回はちょーお手軽に音声認識をしてみようと思います。
というのもmikulusを見てるとUnityは標準で音声認識が出来たり、プラグインを探すと大体英語対応のものばかりで辛い目に遭いました。
なので作りました。
現在作成中のVR内で使えるキーボードに音声認識で入力アシストするのに使っています。
イメージ
音声認識で入力アシストできるようにした #UE4 #VR_keyboard https://t.co/NYLHmjmO1H
— てんちょー (@shop_0761) 2016年11月20日
こちらテスターを募集しているのでOculusTouchがある方はぜひお願いします。@shop_0761にご連絡ください。(圧倒的テスター不足)
方針
色々遠回りしたお話は、あとに書くとして端的に実装方針を説明します。
http通信を用いて実装します。
しかもこれ、ほげたつさんがすでにプラグインを作成して公開しています!!
まぁWebApiプラグインはUE4を触り始めて1週間くらいで作り始めたものだから直すところ沢山なのは仕方ない
— ほげたつ (@HogeTatu) 2016年11月18日
つよい。
ちなみに
@shop_0761 たぶん今後は要望があればバージョンアップ対応だけやって非推奨になると思いますー
— ほげたつ (@HogeTatu) 2016年11月18日
らしいので先日のこちらの記事を参照してゆくゆくは移行しましょう。
http通信については適当にググるか、頭を空っぽにしてそういうものがあるんだなくらいでも動きます。
参考サイトを貼っておくので自作しても構いません。先人は偉大!
参考:
面倒な方は僕がすでに作成したものでも使ってください。実行するだけです。おわり。
ダウンロードするだけで環境が整ってしまいました。
音声認識の精度について
精度的なお話だと、
こちらのほうがいいかもしれません。ただなぜか手元の環境だと、
await contSpeechRecognizer.ContinuousRecognitionSession.StartAsync();
のところで The speech privacy policy was not accepted prior to attempting a speech recognition. と言われてしまい実行できず…
音声認識のプライバシーポリシーってどこで設定するんだ…となってしまったので詳しい方がいればぜひお教えいただけると嬉しいです。
このように認識は外部のツール依存なので、自作してチューニングすればよりよいものになるかと思います。
実装する
と言っても、大したことはしません。
先程のほげたつさんのプラグインにはサンプルプロジェクトWebApiDemoがあるので、それを起動します。
その中にあるWebApiDemo/WebApi/Api 内にあるBP_DemoApiBaseを開きましょう。
そして、継承元の変数を表示するために赤線のところにチェックを入れます。
すると
Domain変数が見えます。
今回はアプリのポートの都合上ここを http://127.0.0.1:50001/ に書き換えます。
あとは、さっきの音声認識のツールを実行後にUE4側で実行しましょう。
SimpleGetを押せば終了!!
音声認識の結果が得られます。
ちなみにこのStringはBP_01_SimpleGet内のResponsebodyに入ってるので後はご自由に。
VRKeyboardの方ではTickで適当にポーリングするBPComponentにしてます。
応用例
普通に音声認識してそのまま使ってもいいのですが、ちょっとあちこち手を加えてこんなことをしてみました。
声が先に聞こえるよ(いっこく堂風) #UE4 https://t.co/r7Po9pnMTD
— てんちょー (@shop_0761) 2016年12月5日
音声認識した結果を使ってLipSync的なことをしています。これをLipSyncさせても面白いかもですね。
[UE4] Grayちゃんと会話 https://t.co/pbFJ5YjaLq
— ほげたつ (@HogeTatu) 2016年11月27日
Docomo雑談APIを使ってGrayちゃんと会話してみた。APIリクエストには開発中のNekoNekoOnlineプラグインを使用。 #UE4
色々できるので遊んでみてください。
辛い目にあったお話
これ以降は今回の記事に至るまでに迷子になった余談なので、気が向いたら読んで下さい。
きっかけはこの辺
ぬああああ!やっとできたww簡単すぎるところで躓きすぎ( ;∀;)ww
— gsk (@gsk39) 2016年10月20日
ヒストリアさんブログみたら一発だったありがとうでした( ;∀;)ww pic.twitter.com/pRW1ecCu39
こんなのあるんだ と思って調べてみたら Pocketsphinxってのがベースらしく
pocketsphinx 多分日本語に対応していないのでsphinxプラグインつらそう
— てんちょー (@shop_0761) 2016年10月20日
と、以外にも日本語の音声認識プラグインが無いことを知りました。
しばらく経って、先程のwin10で動く音声認識のサンプルがあるのを知ったので、これUDP通信で実装するできそうと思ってました。
よく聞くJuliusとかでプラグインでも作ったほうがよさそうかなと思いましたが、あれはデフォのままだとかなりアレな感じなのでガツガツやるにはいいのかもしれません…(DNNベースでもHMMベースでもできます)
じゃあさっそくH社のUDPのサンプルを読みつつ進めていくと、デシリアライズの方法で引っかかりました。
UDP Socket Sender Receiver From One UE4 Instance To Another - Epic Wiki
こことか見てたんですが、日本語stringの場合文字コード周りで死にたくなりましたね…。C++から文字コードを日本語にする方法が見当たらなかったので、 お友達に聞くとpythonをかますか、http通信にしたほうがいいよと言われたので、今回の方法に落ち着きました。
文字コード周りで辛い目に遭っている
— てんちょー (@shop_0761) 2016年11月13日
UnrealC++を読む機会が出来たので、副産物的に前よりは抵抗感がなくなりまし た。
ほげたつさんのコードを読んでUnrealC++を覚えていこうな
— てんちょー (@shop_0761) 2016年11月18日
まとめ
そろそろデフォで音声認識ができてもいいんじゃないかなとは思います。
ただVR_keyboardで日本語の変換周りを扱っていると日本語難しいなと思ったので、当分ないだろうなと思ってしまいました。
明日はprince_ue4さんの「エフェクトネタやります」です。
【UE4】水彩風マテリアルを作ってみた
はじめに
裏 Unreal Engine 4 (UE4) Advent Calendar 2016 8日目です。
我らがおぎまふさんやcom04さんなど、いろいろな方がトゥーン表現に挑戦されています。
最近ではMarketPlaceでもトゥーンなアセットが出てきたりしています。
いろいろ参考サイトをまとめていたのですが、com04さんの記事を見たほうが早いですね…
ですがやっぱり自分好みのものを作りたい…と思って探していたら参考になりそうなところを見つけました。
こちらのサイトではsoftImageですが、なんとかそれっぽくなりました。
マテリアルダメダメなので、練習ついでに作ってみました。
できたもの
水彩風マテリアルがだいたい出来た#UE4Study pic.twitter.com/yUPdarH34r
— てんちょー (@shop_0761) October 18, 2016
ズームアップした pic.twitter.com/pl1rVDxyAh
— てんちょー (@shop_0761) October 20, 2016
つくりかた
ここから先は、先程の参考サイトを見た前提でお話を進めていきますね。(さらっとでおkです)
考え方、手順は参考サイトと同じなので それをどうやって再現したか という感じで進めます。
とりあえず今回は
- BaseColor
- Specular
- Shadow
に当たる部分のマスクを愚直に作って色指定、その境目にNoiseを入れてなじませていきます。コンパイルが重いかも。
ついでに、各色をテクスチャではなく直で色指定しています。モデルによっては細かくマテリアルが分けてる 方が相性がいいです。処理負荷は気にしないことにします。
BaseColorのマスクを作る
BaseTextureを指定できますが、結局Desaturationしてしまうのでそのままでもいいかも。
Blurをかけます。
Blurノード
float4 output = 0; float weightSum = 0; float currentWeight = 1.0; for (int i = 0; i < 10; ++i) { output += Texture2DSample(Material.Texture2D_0, Material.Texture2D_0Sampler, texCoord + i * stride) * currentWeight; weightSum += currentWeight; } output /= weightSum; return output;
参考:
そして、ちょっとNoiseをのせたり。 もちろん、すでにあるNoiseノードでもいいかと思いますが今回はstylized RenderingのT_TexturedPaperを使用しています。
Specularのマスクを作る
こちらはおぎまふさんを見習ってLightVectorを擬似的に用意して、Specularの計算をします。
こうして出来た2つをDesaturationしてそれぞれマスクとしました。
ここまででとりあえず2色分塗ることが出来ました。
ShadowとEdgeのマスクを作る
ここで影色も塗らなきゃなりませんが、このままでは塗れないのでゴリ押しで解決します。
影色になる部分を一旦求めて、今の絵に黒で塗り直します。(いい方法が知りたい)
こうすると後からaddして色を乗せられます。
こちらはおぎまふさんのRimLightの実装をそのまま使ってますので関数の中身は割愛します。
水彩の参考サイトの完成絵を見るとエッジが2段あるように見える(実際は歪めたり、ノイズかけたり)のでRimLight_Rangeにちょっとaddして作ります。
NoiseありとなしのEdgeがあったほうがよかったので、分けて作ってます。
ついでにさっきのshadowマスクを使って、明るい方のEdgeと暗い方のEdgeを作り分けてます。
ここで影色も作ってます。
まとめる
最後にshadow側とBaseColor側をaddして完成です。 お好みでNormalMapも使えるようにswitchをつけたりしました。
こうすることでGraymanの胸のUnrealロゴが出せます。
余談
最初はこのマテリアルをPostProcessで実装していたのですが、マスクできるようになったけど色指定できない…ってなったのでやめました。
その時、最初に作っていた影色を少し淡くするPostProcessが出来たのでついでに載せておきます。
そしてさらにalweiさんのお手軽トゥーンと比較
— てんちょー (@shop_0761) October 8, 2016
影がキツくなくなった感 pic.twitter.com/C4bixB3Ii2
alweiさんのお手軽Toonのマテリアルにちょっと足すだけです。
全体
追加した部分
CustomDepthでマスクを作った結果を使ってなんかごにょごにょしました。
でこの結果を最後にaddして出力してます。
余談2
blurのコードを書いてるときに思いついたのですが、blurベースでedgeが取れそうだったのでやってみました。
このぐらいいけます。
ノードはこれだけ 面倒なSobelフィルタを作らなくても使えるかも。
Blurのコード
float3 output = 0; float ScreenMult_X = GetPostProcessInputSize(0).zw.x; float ScreenMult_Y = GetPostProcessInputSize(0).zw.y; output += 1.0 * SceneTextureLookup(TexCoord + float2(ScreenMult_X * BlurAmount * -1.0, 0.0), SceneTextureID, true); output += 1.0 * SceneTextureLookup(TexCoord + float2(ScreenMult_X * BlurAmount * 1.0, 0.0), SceneTextureID, true); output += 1.0 * SceneTextureLookup(TexCoord + float2(ScreenMult_X * BlurAmount, 0.0), SceneTextureID, true); output += 1.0 * SceneTextureLookup(TexCoord + float2(0.0, ScreenMult_Y * BlurAmount), SceneTextureID, true); output += 1.0 * SceneTextureLookup(TexCoord + float2(0.0, ScreenMult_Y * BlurAmount * -1.0), SceneTextureID, true); output += 1.0 * SceneTextureLookup(TexCoord + float2(0.0, ScreenMult_Y * BlurAmount * 1.0), SceneTextureID, true); output /= 6.0; return output;
SceneTextureIDを引数にすることで、任意のSceneTextureを指定できます。 outputは加算した分だけ割ります。
多分この順番通りでIDが振られてると思います 分からなかったらコードを読めばいいんだよ うん。
まとめ
なんとなくMaterialの演算が分かった気がします。もろもろの計算は試行錯誤の結果なので、「なんでこうなるの?」というより「色々やったらこれがよかった」って感じです。
作りたい絵を目指して、実際に手を動かしてみるとこの意味がわかるかと思います。すごい人になれば頭のなかで完成形をイメージしながらノードを組めるかと思いますが()
まずは作りたい絵を探しましょう!!
わからないこととかあれば、可能な限りお答えするのでTwitter(@shop_0761)等でご連絡ください。
明日は Epic社のおかずさん(@pafuhana1213)の「帰ってきたUE4のマーケットプレイスで購入したアセットを片っ端からレビューするマン」です。
鹿のレビューが懐かしい…
頭の悪いHMDのレビューをしてみる
はじめに
Oculus Rift Advent Calendar 2016の2日目です。
昨日は桜花一門さんのAllumetteが素敵な理由でした。
N回目のVR元年ということで、いろいろHMD(Head Mount Display)が出てきました。
気付いたらうちにもたくさん生えてきました。
ファッションVR勢です pic.twitter.com/KvhdHh6K33
— てんちょー (@shop_0761) October 22, 2016
ということで、これらのHMDのレビューでもしようかと思います。
と言ってもだいたいのレビューはあちこちですでになされているので、別の観点からします。
題して
一番寝心地のいいHMDはどれだ選手権!!
すでに皆さんも一度は被って寝落ちしているかと思いますし、僕自身も手元にあるHMDを被ったまま(意図して)寝たことがあります。 ですが改めて記事になっているものはなかったので、チャンスだと思いました。
注)別に各HMD、コンテンツを批判したいわけではありません。どれもいいものですし、お世話になってます。
事前知識
VRについて全くわからない方はこちらのリンクとかを見てみるといいかもです。一つ目の動画は割りとイメージつかみやすいかも。
評価
評価方法
実際に被って寝(落ち)ます。メガネかけてます。
Rift以外はヘッドホンを使います。
実験時間は寝てから起きるまで。最近あまり長く寝れないことが多いのでだいたい2-3時間です。
(そもそもほんとに眠いときは準備する気になれない)
評価基準
- 起きたときの没入感
- 寝返りのうちやすさ
- コンテンツの寝やすさ
- 被った状態での後頭部へのやさしさ
- 総合評価
をそれぞれ5段階で評価します。かなりアレなやつは☆になります。
結果
Rift
Mikulusの場合
mikulusについてはこちら。
膝枕をしてもらうかのように調整してみました。 他にもたくさんやっている方がいるので、写真は割愛します。
この辺でも覗いてみてください。
起きたときの没入感 ★★★★
目を開けたら目があった。 びっくりした。
寝返りのうちやすさ ★★★★
ヘッドホンが付いているので便利。 しかも軽いのがいいですね。
あまりゴロゴロするとヘッドホンの部分が壊れてしまいそうなので、おとなしくしてました。
コンテンツの寝やすさ ★★★★★
あの これ 呼吸音と心拍音がいい感じに落ち着く感じ非常に良い…
こう看取られてる気分ですね…(看取られたい
被った状態での後頭部へのやさしさ ★★★★★
Riftの後頭部のつくりは以外にもクッションが効いてて、あまり違和感がありませんでした。
後頭部にもセンサーがあるそうなので、これを使ってなにか作れないかなとか思ったり。
総合評価 ★★★★
最初は寝るのにちょうどいいコンテンツを思いつかなくてVirtualDesktopにでもしようかと思ったらMikulusがよさそうだったので選びました。
参考:
目をつぶってしまえば現段階での呼吸音の違和感もなにもなく快適でした。
というか呼吸音と心拍音が聞こえるだけの音声を聞けばいいのではという意見は受け付けません。
目を開けたらそこにいると思えるほうがいいのです。はい。
Riftだとメガネが厳しいHMDなので、そこさえなんとかなれば(というか被ってしまえば)意外とお布団でも使えることがわかりました。
HTC Vive(Pre)
The lab 丘の場合
The labについてはこちら。
丘で横になったときはこんな感じ。鳥が飛んでます。
起きたときの没入感 ★★★
起きて外した時にあれ部屋が狭い…?っと軽く思うくらいには没入していたようです。
まあ曇り空なんですが。
寝返りのうちやすさ ★★
ちょっと重いので頭が持って行かれます。出来なくはないですね。イヤホンにしたらもっといいかも。
コンテンツの寝やすさ ☆
Thelabの丘で寝ると上で鳥が飛んでいます。いい感じに環境音があって快適…かと思いきやタイミングやら位置やらが悪かったのか例のロボット犬が周囲で暴れまくっています。
いやあの、ほんと戯れる分にはいいんですよ… 寝るのにはうるs…(めっちゃギュインギュインしてた
ロボット犬 On/Offできると嬉しい。
被った状態での後頭部へのやさしさ ★★★★
Viveだと後頭部からまっすぐコードが伸びてます。
このためコードのことを思うと頭の下にそのままコードがくることになると思います。このためちょっと違和感があるかなという感じでした。
工夫次第でよくなるかもって感じです。
総合評価 ★★★
ぱっと思いついたコンテンツがコレだったのですが、犬が…犬が…という思いで完全に失敗しました。
といっても、他にこういうのが思いつかなかったのでオススメが知りたいです。
Viveは以前VirtualDesktopをしながら寝ていたこともあるのですが、如何せん重い…首が疲れます。
寝ているとそれは多少軽減されるのですが、ちょっとでも動くとぐいっと持っていかれる感じがします。
PSVR
サマーレッスンのひかりちゃんの部屋のベッドの場合
サマーレッスンについてはこちら。
ベッドの上に座った感じ
ベッドに寝っ転がった
起きたときの没入感 ★
そもそも寝れなかった 頭痛すぎ。
寝返りのうちやすさ ★
プレイエリアの外に出ると目を開けた時に気が散ってしまうので、なかなか動けません。 ヘッドホンをしているとさらに動けないです。イヤホンにしたらいいかも。
しかも全体的に大きめなので壊しそうであまり動けない。
コンテンツの寝やすさ ★★
まあ確かに誰かがいる部屋で寝てる感は出てるっぽいので、ぼちぼち。
どのタイミングで寝るかに迷うかも。(教えてる時、ハンコを押す前、押した後)
今回はハンコを押した後にしましたが、突然話しかけてきたりしてビビります。
教えてるときはBGMがかかってしまうのでやめました。ので、ハンコを押す前がいいかも。
場所を調整するのがかなり難しかったです。 なかなかベッドの位置に移動出来ないし(当たり前)、低すぎると暗転してしまいます。
被った状態での後頭部へのやさしさ ☆
良くない これは頭が痛い 後頭部のパーツが痛すぎる。
他のは薄めのバンドだったのにこれだけやたらしっかりしてるせいで、 寝っ転がった時にこの後頭部のパーツにばかり力がかかって痛い。
そのせいではずした後に頭が痛くなってしまった。
総合評価 ★
PSVRは寝るのに挑戦したのは3回ほどあります。一度だけ座椅子にもたれかかって寝ることに成功しましたが、 今回のように布団や床で寝ることを想定すると後頭部の出来のよさが仇になってしまっています。
後1回はAmazonPrimeVideoでアニメを見ていました。結局後頭部の痛みが気になり寝るにねれない状況でした。 よっぽど疲れている、眠い状況であれば寝付けるかもしれませんが、数時間でこのダメージなので ちょっと怖いですね…
番外編 GearVR + GalaxyS6 edge
niconicoVRの場合
起きたときの没入感 ★★★
まあ単に動画を見ていただけなので、特にやべえコレ みたいなことにはなりませんでした。
寝返りのうちやすさ ★★★★★
これは超いい ほんとにいい モバイルの良さを思い知らされました。
なにより軽い。余計なコードがない。寝返りがうてる。こんなに違うものかと…
思わずゴロゴロ転がってしまいました。
コンテンツの寝やすさ ★★★
眠くなる動画とか見ればいいのでは 終了。
被った状態での後頭部へのやさしさ ★★★★★
こいつもやわらかバンドなので違和感は無いに等しい。 頭が痛くないのはいいことですね。
総合評価 ★★★
手元にあってすぐ試せるniconicoVRにしてみましたが、割りとパフォーマンスがいいのか 3時間くらい持ちそうです。一回も落ちてないっぽい。2時間半くらいで100%→28%だった。
正直GearVRなので寝ろと言わんばかりに熱くなっておしまいかと思ったら 長持ちしてびっくりしました。
余談ですが、起きてからGear VR Cooler!(物理)と題して、雪を詰めた袋をくっつけるだけの 記事を書こうかと思いましたが5秒でやめました。
考察
ということで、今回はRiftが一番良さそうという結果になりました。 ヘッドホンよりイヤホンがいいかもと思ったので完全に選択ミスですね。動けない。
一応どのHMDでも(AmazonPrimeVideoのような)映像を見るだけのものが出来ますが、せっかくなら いいところでお昼寝したいです。欲を言えば寝ても覚めても被って生活したいです。
UE4で言えばKiteDemoのマップは寝心地よさそうな気がします。
参考: www.youtube.com
また今回は扱わなかったハコスコなどのモバイル系は一晩も使えないのがネックですね。
ダンボールだと固定できないので、どうしてもという場合のみアロンアルファで顔にくっつけてください。
参考
http://www.hashiyansoft.com/contents/dc/death.html
これからはVR Nevangelist(寝バンジェリスト)とでも名乗ってみようかな!!
ぜひこの記事を参考に寝心地のいいHMDを購入してみてはいかがでしょうか。
明日はnoshipuさんの「VRアプリ作って思った事とか書きます」です。
おまけ
ちなみにSAOのキリトくんが被っているナーブギア
ヘルメット系は詳しくないのですが、これとても首を痛めそうな気がします。
調べてみると、やっぱり何人かの方がヘルメットを被って寝たことがある模様。特に寝心地レビューみたいのが見当たらず残念。
アミュスフィアはこんな感じ
HoloLensに近い気がしますが、やはりPSVRの例から後頭部に優しくないのではと思ってしまいます。
なのでメディキュボイド型が最強なのでは!?!?
点滴してもらえそうだし。
やっぱりこっちのメガネも捨てきれませんね(もはやVRではない
こちらは確か作中では寝る時に外していたような気もします。
おまけ2
ちょっと調べてみるとこんなものがあったのを思い出しました。
確かに寝る分にはいいかもしれませんが、VR空間で寝たいのでうーんという思い。
【UE4】SaveとLoad時のUserIndexについて
はじめに
時々SaveとLoadに苦戦するのでよくお世話になっているほげたつさんのサイトです。
ここには
セーブデータにはスロット名とユーザーインデックスが指定できます。 スロット名はセーブデータの名前、ユーザーインデックスはその中でのIDみたいなものですね。 ドラクエの冒険の書1とか冒険の書2とかそんなイメージです。
とあります。
もちろんこちらにも。
For some platforms, master user index to identify the user doing the saving.
ただ実際に実装してみると、なにやら動作がおかしいので調べてみました。
ソースコード
ということで、Engineのソースコードを追います。UE4.13です。 ctrl+FとかでUserIndexをハイライトしておくと、見やすいかもしれません。
Runtime/Engine/Private/GameplayStatics.cpp
USaveGame* UGameplayStatics::LoadGameFromSlot(const FString& SlotName, const int32 UserIndex) { USaveGame* OutSaveGameObject = NULL; ISaveGameSystem* SaveSystem = IPlatformFeaturesModule::Get().GetSaveGameSystem(); // If we have a save system and a valid name.. if(SaveSystem && (SlotName.Len() > 0)) { // Load raw data from slot TArray<uint8> ObjectBytes; bool bSuccess = SaveSystem->LoadGame(false, *SlotName, UserIndex, ObjectBytes); if(bSuccess) { (省略)
bool UGameplayStatics::SaveGameToSlot(USaveGame* SaveGameObject, const FString& SlotName, const int32 UserIndex) { ISaveGameSystem* SaveSystem = IPlatformFeaturesModule::Get().GetSaveGameSystem(); // If we have a system and an object to save and a save name... if(SaveSystem && SaveGameObject && (SlotName.Len() > 0)) { (省略) // Stuff that data into the save system with the desired file name return SaveSystem->SaveGame(false, *SlotName, UserIndex, ObjectBytes); } return false; }
とSaveもLoadもUserIndexに関わる処理はSaveGame、LoadGameを呼び出しているのでそちらへ。
Runtime/Engine/Public/SaveGameSystem.h
virtual bool SaveGame(bool bAttemptToUseUI, const TCHAR* Name, const int32 UserIndex, const TArray<uint8>& Data) override { #if PLATFORM_HTML5_BROWSER return UE_SaveGame(TCHAR_TO_ANSI(Name),UserIndex,(char*)Data.GetData(),Data.Num()); #elif PLATFORM_HTML5_WIN32 FILE *fp; fp=fopen("c:\\test.sav", "wb"); fwrite((char*)Data.GetData(), sizeof(char), Data.Num(), fp); fclose(fp); return true; #else return FFileHelper::SaveArrayToFile(Data, *GetSaveGamePath(Name)); #endif }
virtual bool LoadGame(bool bAttemptToUseUI, const TCHAR* Name, const int32 UserIndex, TArray<uint8>& Data) override { #if PLATFORM_HTML5_BROWSER char* OutData; int Size; bool Result = UE_LoadGame(TCHAR_TO_ANSI(Name),UserIndex,&OutData,&Size); if (!Result) return false; Data.Append((uint8*)OutData,Size); ::free (OutData); return true; #elif PLATFORM_HTML5_WIN32 FILE *fp; fp=fopen("c:\\test.sav","rb"); if (!fp) return false; // obtain file size: fseek (fp, 0 , SEEK_END); int size = ftell (fp); fseek (fp, 0 , SEEK_SET); Data.AddUninitialized(size); int result = fread (Data.GetData(),1,size,fp); fclose(fp); return true; #else return FFileHelper::LoadFileToArray(Data, *GetSaveGamePath(Name)); #endif }
えーっとPlatformがHTML5のブラウザだけUserIndexを使っているように思います。
そしてこのUE_SaveGameとUE_LoadGameはこちらに。
Runtime/HTML5/HTML5JS/Private/HTML5JavaScriptFx.js
UE_SaveGame: function (name, userIndex, indata, insize) { // user index is not used. var _name = Pointer_stringify(name); var gamedata = Module.HEAPU8.subarray(indata, indata + insize); // local storage only takes strings, we need to convert string to base64 before storing. var b64encoded = base64EncArr(gamedata); $.jStorage.set(_name, b64encoded); return true; }, UE_LoadGame: function (name, userIndex, outdataptr, outsizeptr) { var _name = Pointer_stringify(name); // local storage only takes strings, we need to convert string to base64 before storing. var b64encoded = $.jStorage.get(_name); if (b64encoded === null) return false; var decodedArray = base64DecToArr(b64encoded); // copy back the decoded array. var outdata = Module._malloc(decodedArray.length); // view the allocated data as a HEAP8. var dest = Module.HEAPU8.subarray(outdata, outdata + decodedArray.length); // copy back. for (var i = 0; i < decodedArray.length; ++i) { dest[i] = decodedArray[i]; } Module.HEAP32[outsizeptr >> 2] = decodedArray.length; Module.HEAP32[outdataptr >> 2] = outdata; return true; },
いやあのこれ、UserIndex出番なくないですか…(引数として呼ばれているだけで未使用)
まとめ
現状だとUserIndexは出番がないようです。ちゃんと(?)設定していないはずのUserIndexでLoadしてもエラーが出ませんでした。
Forum等も漁りましたが、良さげな解答が見つからなかったので追ってみました。
どこか間違ってたり、新たに何か分かった時にはぜひ@shop_0761までお知らせください(更新します)