archive

こんにちは。
ユニトラストの筒井です。

ちょっと前にFacebookより販売されたVRヘッドセット、Oculus Questを購入していました。
しばらく遊んだのち、自分もアプリを開発できないかさっそく調べたところ、
その方法がとてもシンプルかつユニークだったため、その内容を書きたいと思います。

VRって何?

VRはVirtual Realityの略称です。日本語では「仮想現実」と訳されることが多いです。
簡単に言うとヘッドセットを使い、人の手によって作られた空間を、現実世界により近い形の感覚で提供するための技術となります。
詳細な解説は、Wikipediaにお譲りいたします。

Oculus Quest とは

Oculus社(Facebookに吸収合併されました)によって製造された、家庭向けスタンドアロンVRヘッドセットの第二弾となります。
第一弾として2018年5月にOculus Goが販売されておりますが、それから下記のような強化がありました。

個人的にOculus Goの性能や操作性では、動画系のVRコンテンツを楽しむのが精いっぱいかな?と思っていたので、
性能やコントローラー等、様々な側面で強化されたOculus Questには高い期待がありました。

実際、操作系がPC用のVRと統一されたことやもともとOculusブランドだったため、Oculus Questが販売された時点で、
Robo RecallやBeat Saber、VRChatなど、多くのPC向けタイトルが既に移植されており、すぐに楽しめました。
(新規タイトルはそこまで多くはありませんでしたが、公式チュートリアルのFirst Step等はとても素晴らしかったです。)

Oculus Questがどのくらい楽しいのかは、動画を見たり、ぜひ持っているお友達に借りたりしてみてください。
家電量販店などでは、PC向けVRが体験できる場所が用意されていることもあるので、そちらも是非。

開発者向けセットアップ

早速Oculus Questでアプリを作るための環境をセットアップします。
必要なツールは下記の通りです。

関連機能のインストールが充実しているため、今回はUnity 2019.1を使ってセットアップします。

Unity Hubをこちらよりダウンロードし、インストールしてください。
起動後、下記画面の右上から「インストール」を押します。

Unity 2019.1 を選択します(マイナーバージョンはアクセスした時期によって更新されている場合があります。)

モジュール選択で「Android Build Support」およびその中の「Android SDK & NDK Tools」を選択します。

いくつかの規約事項の確認後、下記のように自動的にダウンロード・インストールが開始されます。

ちょっと長いです。その間に Oculus Quest側の開発者設定をオンにします。

Oculus Questとペアリングした端末で「その他の設定」から「開発者モード」をオンにすることで設定できます。
また、アカウントが開発者登録をしていない場合は、その過程で https://dashboard.oculus.com/ での登録を促されるため、
端末のアカウントで開発者登録をします。

 

Unity 2019のインストールが完了したら、Unity Hubにて「プロジェクト」から「新規作成」をし、
下記のように3Dプロジェクトとして作成します。

ひとまず起動することを目標とするため、いくつかのアセットをインストールするステップをいったん省略します。
まず「File」→「Build Settings」→「Android」→「Switch Platform」と順に選択します。
少し待った後、「Player Settings」→「XR Settings」と選択していき、「Virtual Reality SDKs」に「Oculus」を追加します。(ここも多少の待ち時間があります。)

「Other Settings」を開き、Graphics APIsからVulkanがあればそれを削除します。
下記の画像のように「OpenGLES3」になっていれば問題ありません。

そのまま下にスクロールし、「Package Name」を適当なものに変更し「Minimum API Level」をAndroid 4.4 ‘KitKat’ に変更します。

これでビルドできるようになったので試します。
Oculus QuestをPCにつないでおきます。
「開発者モード」をオンにして最初につないだ場合、以下のようなダイアログがHMD内に表示されることがありますので、
コントローラを使って許可します。

無邪気に「Cube」を配置し、「Build Settings」を開きなおし「Build and Run」をします。

ビルドが行われ、接続されているOculus Questに自動的にインストールされます。
インストール完了後、アプリが自動起動するので、HMDを装着し、無邪気に配置したCubeが立体視で見れることを確認できます。

(上記画面は、Chrome拡張機能である「Vysor」を使い、HMD内の映像をPC上に表示しています。)

以上でUnityアプリをOculus Quest用にビルドするための手順は完了になります。
以降は、変更を加えて再ビルドを行うか、下記のようにOculus内にインストール済みのビルドの再実行ができます。

とりあえず何か作ってみる。

Unityの初期状態の青空空間ではさすがにもったいないので、先ほどスキップした、Oculus Integration アセットをプロジェクトに追加して、ボタンの操作を取得してみました。

Oculus Touchの6DoF情報や、ボタンの入力などがしっかり取得できています。

また、ここから、ちょっとしたゲームを作ってみました。
スティックで自機を移動し、Oculus Touchの向きに弾を飛ばす、いわゆるシューティングのようなものです。

サウンドやエフェクト、レベルデザイン、UI/UX等を洗練させていければ、
ゲームとしての完成度も上がっていくと思います。

記事の内容は以上です。
今後もOculus Questを弄りながら、あわよくばOculus Storeの審査の提出を狙ってみようと思います。

ユニトラストでは、これまでIT未経験者の新人採用を学校における最終学年の方としていました。
毎年たくさんの学生さんにお会いでき、その中からユニトラストの仲間に加わってくれる人が増えて続けているのはとても嬉しいです。

一方で、昨今は新人においても採用ルートが多様化し、インターンシップやダイレクトリクルーティング、リファーラル採用など、学生さんとの出会い方が変化してきています。

ユーザやお客様により喜んでいただき、働く仲間がより幸せに感じ、会社としてより成長していくためには、新しい採用に挑戦し、様々な強みをもった仲間を迎えていく必要があると考えています。

そこで、2021年度春入社の新人採用において、インターンシップをはじめることにしました。
2年後に卒業見込の学生さんを中心に夏休み中の実施を想定しています。

インターンシップをはじめるにあたっては、私たちユニトラストとしてどのようなプログラムにすべきかを考えました。
大事な学生生活の夏休みの時間を使ってお越しいただくので、表面的な情報提供や単なる就業体験をするに留まらず、以下のような生涯役に立つものを得ていっていただきたいと思っています。

■社会について
インターンシップに参加いただいた学生さんが卒業後に全員私達の会社へ入社していただけたらとても嬉しいですが、それはなかなか難しいことです。
他の会社や業界に進まれる方もいらっしゃると思いますので、就活時や社会に出てからも活かせる普遍的な考え方をお伝えできたらと思います。
また「社会の一員となり働くことはワクワクすることなんだ」という仕事の面白さ、楽しさもお伝えしたいです。

■ITについて
現在ではプログラムは一部の職人だけが扱える特殊技術ではなく、誰もが気楽に楽しめる表現方法の1つになっています。
ITを使う側から作る側になった楽しさ、自分の書いたプログラムが動いた時の感動やその先に広がる可能性を感じていただきたいです。
また、作って終わりではなく、プログラム(スマホアプリ)をご自身のスマホ入れて持ち帰っていただき、家族や友人たちに感動を共有していただきたいです。

インターンシップでは、ユニトラストの様々な世代のエンジニアたちが参加する予定です。もちろん役員たちも全員参加します。
長く同じ時間を過ごすことでお互いに気づくことが多いと思いますので、最終日には学生さんに先輩からの熱いメッセージを個別に伝えたいと思っています。

インターンシップの開催は8月と9月に予定をしています。
どんな学生さんに会えるか、今から楽しみです!

実施要項は下記をご覧ください。
株式会社ユニトラスト2021年度インターンシップ(外部サイト)

こんにちは。
ユニトラストの中山です。

以前Webサービスで中々解決しない問題がありました。
その時実施したインシデント解消にいたる施策やツールのご紹介です。

ミドルウェアのバージョンは記憶が曖昧で申し訳ありませんが以下の通りです。

DB:Microsoft SQL Server 2014
アプリケーションサーバ:Tomcat
Webサーバ:Apache
フレームワーク:Spring、MyBatis

インシデント

システムエラー画面になって動かなくなる。
必ず発生するわけではなく、1ヵ月~2ヵ月毎に発生する。
1人、2人ではなく複数の使用者に同じことが起こっている。
さらに時間をあけてもう一度同じ操作をしても同じ事象が発生する。

原因を探る

まずインシデントが発生した場合、インシデントの解決が優先になります。
本番運用されている場合は業務が止まってしまうのが一番問題です。
これはサーバ再起動で解決しました。
ただ本インシデントは度々発生するため、その度に再起動するのは現実的ではありません。
ここから問題解決を実施していきます。

ログを確認する

まずはアプリケーションログを確認します。
ログを確認するとDBからタイムアウトエラーが飛んできてました。
DB側でタイムアウト起こすような原因がありそうです。
DB側でタイムアウトが起きるのは、別に悪いことではありません。
※システム利用者にとっては使い勝手が悪いですが。

必ず起きるわけではないとこから、使用人数が多くなるときにDB負荷が大きくなり発生すると想定しました。
ただ時間をあけて実施しても同じことが起きていることから、トリガーは使用人数が多いときかもしれませんが、
それが起因でなにかが起きていそうです。

ロックされているテーブルを見つける

タイムアウトが起きているということで、ロック待ちでタイムアウトしているんじゃないかと想定。
インシデント発生時に、現在のロック状況がわかるクエリを投げてもらい、ロックしているテーブルから原因を突き止めようと試みます。

SELECT *
FROM sys.dm_tran_locks
WHERE resource_associated_entity_id
 =(
  SELECT TOP 1 object_id FROM sys.partitions
  WHERE OBJECT_NAME(object_id)='TABLE-NAME'
 );

ロックしているテーブルがわかれば、テーブルから処理が追えるだろうとの想定からです。
ただここからが長かった。

拡張イベントログ使う

SQLServerの拡張イベントログを出します。
拡張イベントはN秒ロックしているセッションをだしたり、デットロックされたセッションを出したりできます。
開発者がDBに直接アクセスできるならプロファイラやレポートで確認してもいいかもしれませんが、
そうでない場合は拡張イベントログが便利です。

結局原因は?

原因は排他ロック(X)が残り、DB・アプリケーション間のコネクションタイムアウトが発生する。
ただ詳細にインシデントをヒアリングするとDB・アプリケーション間のタイムアウトではなく、HTTPのタイムアウトが起きている場合もあるとのこと。
ロック以外の問題もありそうです。
さらにロックされているテーブルに傾向はなく、どの処理でロックされているかなどはわかりませんでした。

インシデント解決手段を探す

原因がわからないからといって、何もしませんでは進みません。
違うアプローチで対処方法を探ります。

リソースを確認する

真因はわかりませんが、「負荷が高いときにリソース不足になっていているのでは?」と仮定します。
JDKにはJavaリソースを監視できるツールがデフォルトではいっています。

JConsole
メモリやスレッドの状況が確認できます。メモリもNewやOld領域など細かく確認可能です。
今回見たかったTomcat側に設定しているJDBCの設定値も監視できます。
#DBとどのくらいコネクションはっているかとか

VisualVM
JConsoleと同じようにメモリなど見れます。

Javaリソースだけでなく他も色々使って確認しましたが、結局メモリもCPUが足りないということはわかりました。
特にCPUはSQLServerが使用しているCPUが足りないということが分かりました。

DBの設定を変える

リソース不足で遅くなるのは仕方がないとして、排他ロックが残るのは別に問題がありそう。
ということでDBの設定情報を変更します。

SQL Serverはデフォルトだとロックエスカレーションという機能があります。
この機能はロックするリソースが多くなった時、行ロックではなくページやテーブルロックしロックリソースを削減します。
状況的にはこれだけでは解消しないと思いますが、発生頻度は下げられるかも。ということでエスカレーションをOFFにします。
ついでに統計情報更新タイミングも深夜に変更します。

セッションKill

インシデントが発生したとき、「SQLServerのセッションをKillすればサーバ再起動しなくても大丈夫ではないか?」
と考え発生時にKillしてみます。
結果はダメでした。アプリで色々問題があり違うエラーが出てしまいます。

トランザクションを見直す

実は排他ロックが残るということでトランザクション回りが一番怪しいのは理解していたのですが、
コードを見直した限り大丈夫との認識でした。
色々手を尽くした後、再度見直してみたら、「エラーログには出ていないが、もしここで例外発生したらトランザクションがクローズされないままになる」箇所が見つかり、念のため対策しました。
結果大当たりでした。

結果

結局以下の2つを実施した後はインシデントが起きなくなりました。
・メモリやCPUを増やした
・見直したトランザクションでアプリを修正した

またHTTPのタイムアウトが起きていた問題ですが、これはDB・アプリケーション間のタイムアウトが起きていないことが原因でした。
なぜかというと、「プロシージャでPrint文を大量に入れているとタイムアウトしないことがある」ということが分かりました。
なぜPrint文を入れるとタイムアウトしないのかは長くなるのでここでは省略いたします。

ここに書いてないことも色々やっていたのですが、かなりのコストと時間を費やしてしまいました。
解決策が見えないとあれこれ手を出して何をやっているのかわからなくなりますが、
そんな時こそ「何をやって何をやっていないのか?」「どのような想定で何を調べているのか?」
を整理して行動、報告しないとお客様は納得してくれないと感じました。

弊社では一緒に働いてくれるメンバー募集中です。ご興味があれば以下バナーから詳しい情報をご覧ください!