がとーしょこらの技術録(旧)

記録や技術的な記事を書いていきます

VRChatのインスタンス参加の複雑性

VRChatではいろんな人と交流することができる。
この交流の場は実際はインスタンスという名前がついている。
これはワールドという型から作られたものであり、
VRChatのユーザーなら誰でも新しく作成して開くことができる。

インスタンスパーミッション

このインスタンスには誰が参加できるかに応じて5つのレベルがある。
このレベルを本記事では便宜上パーミッションとする。
またパーミッションインスタンスを建てる際に建てるユーザー(以下、Organizer)が決めることができる。

  • Public:誰でも入れる
  • Friend+インスタンスにいるユーザーのフレンドなら入れる
  • FriendOnly:Organizerのフレンドなら入れる
  • Invite+インスタンスにいるユーザーの承認が通れば入れる
  • InviteOnly:Organizerの承認が通れば入れる

表にすると以下のようになる。

名称 参加できるユーザー 承認必要
Public 誰でも ×
Friend+ インスタンスにいるユーザーのフレンド ×
FriendOnly Organizerのフレンド ×
Invite+ インスタンスにいるユーザーのフレンド
InviteOnly Organizerのフレンド

ここで承認という概念が出てきた。
これはある人をそのインスタンスに参加(Join)させてよいかというものである。
ここでいうある人はそのインスタンスにいる人のフレンドである。
そのフレンドは会いに行きたいフレンド(以下、Joinee)に対して、
そのインスタンスに参加したいという承認要求メッセージ(Request Invite)を送ることができる。

このメッセージはJoineeがPrivate表記になっているときに送ることになる。
Private表記ではないときには承認なしにJoin可能である。
Private表記になるのは

である。
(蛇足だが、2020年2月25日現在の仕様では3つ目の状態の場合、
Organizerと参加したい人がフレンドでない場合、インスタンスに参加することはできない。)

ユーザーステータス

ユーザーの現状態を示すユーザーステータス機能がある。
これはユーザーが自由に設定でき、フレンドはそれを見ることができる。
今までは3種類だったものが、近々アップデートで4種類になる。
Upcoming Status System Changes - VRChat - Medium

ユーザーステータスは以下の4つの種類がある。

  • 青:現在地を隠さないし、絶対承認する
  • 緑:現在地は隠さないし、承認できる
  • 橙:現在地は隠すけど、承認できる
  • 赤:現在地は隠すし、絶対承認しない

表にすると以下のようになる。

現在地の表示 承認する
×
× ×

現在地を隠すということはフレンドから見たときにPrivate表記になる。
そして、参加したい人がRequestInviteを送ったときにそれを承認するかどうかも異なっている。
青は自動で承認され、赤は自動で非承認される。
緑と橙はRequestInviteを受け取ったユーザーが承認するか選択する。

パーミッションとユーザーステータスの関連性

ユーザーステータスは
「ユーザーレベルでプライバシーを確保するもの」 だと言える。
それに対して、インスタンスパーミッション
インスタンスレベルでプライバシーを確保するもの」 だと言える。

ユーザーはそれぞれの思想の元、どの程度プライバシーを守るか設定する。
インスタンスにいるユーザーAが「フレンドにJoinしてほしい」という思想の元、青ステータスにしていたとしても
Organizerが「自分の知らない人が入ってほしくない」という思想の元、FriendOnlyで開いていた場合、
ユーザーAのフレンドはOrganizerとフレンドでなければインスタンスに参加できない。
よって、Organizerの思想のほうが実際のインスタンス運用に関しては影響を受けやすい。

また、パーミッションというインスタンスレベルのプライバシーが背景にあって、
実際に誰を入れるかという部分の最終決定はJoineeのRequestInviteの承認可否に委ねている。
これはインスタンスに参加するためにはそのインスタンスにいる人が窓口になるという設計によるものである。

(Public, FriendOnly, Friend+はワールドのインスタンス一覧からも参加することができるが、
実際のところ基本的にはフレンドからのJoinが多いように感じる。)

このようなシステム設計によってユーザーコミュニティの形成にどのような影響があるのか気になるので今後も考察していきたい。

その他

承認が不要という観点でインスタンスのプライバシーレベルは

Public > Friend+ > FriendOnly > Invite+ > InviteOnly

であるが、
Organizerとフレンドであるかという観点から
そのインスタンスに参加できる可能性があるユーザーの総数は

Public > Friend+ = Invite+ > FriendOnly = InviteOnly

である。

しかし、Invite+はインスタンスにいるユーザー全員がPrivate表記になり、
FriendOnlyはOrganizerとフレンドであり、そのインスタンスにいるユーザーが青または緑ステータスの場合、場所が表示された状態になる。
よって、FriendOnlyのほうが承認なしでJoin可能であることを確認でき、参加しようとするユーザーが多いように感じる。

VR空間におけるテキスト入力のためのUI/UX考察

VR空間におけるUI/UXはまだ研究段階で多くの研究者および開発者が試行錯誤しています。 その中でもテキスト入力についていま存在するUI/UXを見ながらどんな要素が必要なのか考察していきます。

著者はUI/UXの研究者ではなく、 あくまでいち開発者の視点から考察していきますのであらかじめご了承ください。

VR空間におけるテキスト入力のためのUI/UXの代表例

まず現在VRで使われているテキスト入力のためのUI/UXの代表例を挙げてみます。

コントローラからのレーザーポインタ

コントローラから出たレーザーポインタで選択し入力する f:id:gatosyocora:20200225171514j:plain:w400
撮影元:VRChat

物理的に押す

バーチャルな指やコントローラなどでバーチャルキーボードを押すことで入力する

f:id:gatosyocora:20200227002159g:plain:w400
引用元 : https://www.moguravr.com/punchkeyboard/

手の回転を使う

手を回転させて文字を選択し入力する

f:id:gatosyocora:20200227002208g:plain:w400
引用元 : https://yutokun.com/vr/jpinput/

フリック入力

特定の方向にフリックすることで入力する www.youtube.com

手にキーボードをマッピング

親指と各指をあわせることで対応した文字を入力する

f:id:gatosyocora:20200120183414p:plain
引用元 : KITTY: Keyboard Independent Touch Typing in VR

現実空間でのテキスト入力から考えるVR空間でのテキスト入力

私たちが暮らす現実空間ではどんなテキスト入力が使われているか見てみます。

パソコン:キーボードを物理的に押す スマートフォンフリック入力

共通点として

  • 手自体は定位置にある

  • 手から近い位置にある

  • 指を動かして入力するため小移動である

が挙げられます。

私はVRにおいてもこれが重要な要素になるのではと思っています。

VRにおいて空間的な入力が可能であるため腕ごと動かして入力できますが、 上記の要素に従えば、VR空間でも文字入力においては手は小移動の入力が良いと思われます。

現在、多く使われているレーザー式の入力がこの要素を持っていると思います。 別の文字を選ぶ際には手首を動かして角度をつけるか、腕を少し動かす程度の移動です。

これは「手自体は定位置にある」や「小移動である」はある程度満たしていると思います。

また、この入力方法は入力のために遠距離にあるバーチャルキーボードのキーにレーザーを狙う必要があります。 そのためキーに照準を合わせる必要があり、これがスムーズな入力を阻害し、負荷になっている可能性があります。

現実空間のテキスト入力の要素の一つである「手から近い位置にある」も満たし、スムーズで負荷が少ない入力が求められます。

現在、現実空間で使われているUI/UXでは上記であげた要素以外にも様々な要素が含まれています。 これを分析して、それを満たすUI/UXがVR空間においても広く使われていくのではないかと思います。

2019年の振り返りと来年の目標

2019年ももう終わりですね。皆さん良い2019年を過ごすことができたでしょうか。

ぼくはまずまずといったところでしょうか(2018年が激動すぎた感じがありましたね...)

来年も頑張るためにも2019年にがとーしょこらがどんなことをやったかを振り返っていきます。

2019年の振り返り

1月

2018年の終わりごろにShaderを触っていたので1月もまだShaderを触っていました。 このころはバーチャルシンガーのYuNiちゃんにはまっていて、 Shader×VRC_VideoPlayerで動画くっつけようとしたり、動画内での演出っぽいことをしたりしてました。


さらにこのタイミングで前々から作ってみたかったVRオーバーレイアプリを作成しました。 VaNiiMenu開発者のSegmentationFaultさんVRオーバーレイアプリ開発のためのライブラリや記事を出してくださっていたのですごく助かりました。

VRオーバーレイはいいぞ


また、2018年から作っていたVRChat向けのEditor拡張セットに新しい仲間が増えました。

Editor拡張はこういった単純な作業を自動化できて、誰でも簡単にできるようになることが魅力の一つだと思っています。


2月

VRオーバーレイツール第二弾としてVRChatで今いるワールドをツイートするツールを作成したりもしてました。

これは公開してませんが、Twitterとの連携とか苦労した記憶があります。

Twitterを見て誰かに会いに行くということが増えたらいいなってことで作ってました。


Editor拡張ではまたVRChat向けのEditor拡張セットに新しい仲間が増えました。

これで当時考えていたものは一通り追加できました。

VRChatをやっているとBoundやLightProbeまわりで見た目が気になるってことがコミュニケーションを阻害しかねないと思っていたので早急に取り組みたかった内容でした。


そして、元怒さんEmoteSwitchV3を公開されるにあたって、簡単に設定できるEditor拡張が欲しいとのことだったので作成させていただきました。

これは私の中でもいい感じに作れたと思っています。

また、同じく元怒さんが配布されたまばたき防止機構のEditor拡張も作成させていただいてます。


3月

3月にはバーチャルマーケット2が開催され、参加しました。

こういうイベントへの参加は初めてだったのでうまくいくか心配だった記憶があります。


そして、VRCAvatarEditorをこのこ今回は昔に作ってBooth等で配布しているシェーダーを展示していましたが、Editor拡張を展示するような出店もまたしてみたいなって思っています。 ろにリリースしました。

これはVRChat向けのEditor拡張セットにアバター向けのものが増えてきたので「これらを統合して使いやすくしよう」と思い、作成しました。

VRChatを始めた人でも使いやすくを目指したのでUIの見せ方やドキュメント整備などいろいろ工夫をしています。


また、このころにリリースされた東京クロノスをOculusGoでプレイしました。

ストーリーが面白かったことに加えて、VRノベルゲーム特有の新しい表現やモバイルVR機器でも動くように負荷軽減などさまざまな工夫がされていて面白かったです。


4月

VRChat向けのEditor拡張セットの新しい仲間です。

「シェイプキーの名前を変えたはいいけど、表情アニメーション使えなくなったんだけど...」ってことがあったので作ったツールです。


そして、注目していた新しいVRSNS「ambr」がリリースされたので行ってみました。

モバイルVR向けということもあって、負荷とか表現とかが気になっていましたが、想像以上のすごさでした。


そして同時期にVRChatのモバイル対応とテスト版としてOculusGoで動くVRChatが公開されました。

VRChatに手軽に行けるということがすごく感動でしたね。

その流れでモバイルVRのVRChatへのコンテンツのアップロードを支援するEditor拡張を作りました。


ambrで遊びながら、そろそろEditor拡張以外のツールも作成したいなと感じ始め、初のWPFアプリケーションを作成しました。

これも公に配布はしていませんが、個人的にはいまも現役で使っています。


5月

5月はQittaでuGUIの記事を書いたり、公開しているEditor拡張のアップデートをおこなったりしました。


さらにVRMのアプリケーションも作ってみたいなということで昔作ったバーチャルアシスタントのVRMバージョンも作ったりしていました。

VRMを使ってどんな表現ができるかいろいろ考えた時期でした。


6月

VRChatの某ワールドでダンスをしているときに「表情とか変わってほしいけど、Blender触りたくない...」ということで作りました。

(AnimationPropertyConvertorのほうが後だと思ってましたがこっちが後だったんですね...)


7月

研究室に視線検出できるViveProEyeが納品されたのでVirtualCastで試していました。

目のトラッキングで表現の幅は広がるもののちゃんと動かさないといけないので大変そうだなって印象でした。

加えてViveProEyeでとれる情報を調べて記事にまとめたりもしました。


さらにVRoidモバイルがリリースされたのでそちらで遊んだりもしていました。

VRMアバターでいろんなところにおでかけできるのはすごく良きでした。


他にもclusterSDKでアバターやワールドアップロードも試したりVR技術者になったりもしました。


そして、7月終わりぎりぎりにボーンを削除するEditor拡張を公開しました。

「clusterにアップロードするときにボーン制限があるけど、Unityで削除できない...」というところから作成してます。

このEditor拡張からアバターの軽量化に着目して様々なEditor拡張を作成していくことになります。


8月

よくアップロード制限で悩まされる部分がポリゴン数です。

8月はポリゴン数を減らす方法としてどういうものがいいか模索しています。


その第一弾がサブメッシュ単位でメッシュを削除です。

削除するなら意味がある単位で削除したいということでサブメッシュに着目しました。

しかし、この方法ではあらかじめサブメッシュに分かれていないと削除できないので自由度が低いです。


第一弾を踏まえて作成した第二弾がテクスチャを塗ってメッシュを削除です。

サブメッシュよりもさらに細かい範囲でも大きな範囲でも削除可能ということにしました。

しかし、どのメッシュを削除するか選択することが大変で、いろいろ考えてたどり着いたものがテクスチャを塗るでした。


メッシュ削除系だけでなくシェイプキーを合成するEditor拡張もつくりました。


そして、8月後半にはとあるデジタルアート系の企業さんでインターンに参加させていただきました。

実際に就業させていただく形のインターンは初めてだったのでいろいろ得られるものが多かったです。


9月

9月上旬はpixivさんのインターンに参加させていただきました。

実際に稼働しているサービスのAndroidアプリの開発をお手伝いしました。

ピクシブ技術職向け夏インターン2019に参加した話 - がとーしょこらの技術録


そして、後半にはUnite Tokyo 2019に参加しました。

去年も参加してすごく楽しかったのですが、今年も最高でした。

特にUniteおにぎりやタピオカはおいしかったです。


10月

10月はVRCAvatarEditorをアップデートしていました。

また、とあるQuestアプリを作成し始めました。(公開できるように頑張ります。)


11月

シェイプキーの順番を入れ替えるEditor拡張を作りました。

これでUnity上でシェイプキーの操作は代替できるようになってきたと思います。


さらに新しいワールドも公開しました。

このころにNPCが流行っていたのでいろいろ実験的なものをいれたNPCを配置しました。


12月

12月といえばAdvent Calenderということで今年もVRChat Advent Calender 2019を主催しました。

多くの方に参加していただいて本当に感謝です。ありがとうごさいました。

今年は2つの記事を書きました。

VRChatで「見えない」を実装する - がとーしょこらの技術録

【VRChat他】アバター改変を支援するために作ったツールの紹介 - がとーしょこらの技術録


そして、Lavender、Nostos、NeosVRを体験しました。

どれもマルチプレイ可能なVRコンテンツではあるもののそれぞれに色があって面白かったです。

Nostosは感想的なものを記事にまとめてあります。


さらにclusterでのライブにも参加しました。

面白い視覚的表現がいろいろなされていたのですごく良かったです。

そしてclusterも久しぶりにインしましたが、UIまわりがすごく使いやすくなっていました。

まとめ

2019年はいろんなEditor拡張をつくりました。

特にVRCAvatarEditorとMeshDeleterWithTextureはいまも多くの人に使っていただいているので嬉しいです。

ボーンやメッシュの削除などのアバターまわりはまだまだやりたいことがあるので取り組んでいきたいですね。


また、インターンに参加したり、いろんなVRコンテンツを体験したりでいろんな経験ができました。

この経験を制作に活かしていきたいですね。

2020年の目標

2020年はVRC技術市でEditor拡張系の本を出します(予定)。


また、VRCAvatarEditorの新バージョンのリリースも予定しています。

(VRChat 2018公開に合わせてリリース予定が伸びている)


そして、まだ作りたいEditor拡張もあるので作っていきます。

2020年はEditor拡張以外にもいろいろ作っていきたいですね。


長文にはなりましたが、ここまで読んでいただきありがとうございました。

それでは良いお年を。

【VRChat他】アバター改変を支援するために作ったツールの紹介

はじめに

本記事はVRChat 2 Advent Calender 2019 16日目の記事です。

これまで

主にVRChatのアバター改変で使えるUnity向けツール

を開発をしてきたのでそれを一通り紹介していきます。

ここで紹介しているものはすべて がとーしょこらのおみせ @gatosyocora - BOOTH で公開しています。

VRChat向けツール

ここではVRChatのアバター改変で使用することを前提として開発したツールを紹介します。

VRCDeveloperTool

Unityでちょっとした作業をやりやすくするEditor拡張を詰めたよくばりセットです。 gatosyocora.booth.pm

便利なツールがあっても一つ一ついれるのが大変なので、「これをいれたらいろんな便利なツールが使えるよ」ってものをイメージして作りました。

この中でよく使われているものをピックアップして紹介します。

ちなみにHandPoseAdder, HumanoidPoseResetter, MeshBoundsSetter, ProbeAnchorSetterは後述のVRCAvatarEditorに同様の機能を持たせているのでそちらを使うのをオススメします。

  • HandPoseAdder

表情切り替え用アニメーションファイルに手の形のアニメーションを追加します。

FISTやHANDOPENなどVRChatでよく用いられる手の形はアニメーションファイルを右クリックで簡単に追加できます。 さらにCustomHandPose機能を使ってそれ以外の手の形を設定すれば同様に追加できるようになります。

  • ShapeKeyNameChanger

アバターのシェイプキーの名前を変更します。

特定のワールドのアニメーションではシェイプキーの名前を参照して表情を変えたりするので、名前を変更することでそれに対応できます。

また、好きな名前を入力して設定するだけでなく, ツール側で用意した名前から選ぶこともできるようになったので某ワールド対応が簡単になりました。

  • ShapeKeyMixer

複数のシェイプキーを合成して一つのシェイプキーにします。

例えば, 目を動かすシェイプキーと口を動かすシェイプキーを合成することで目と口を一緒に動かすシェイプキーを作ることができます。 片目同士のシェイプキーを合成で、両目を動かすシェイプキーにするなどいろいろ組み合わせることができると思います。

  • SubMeshDeleter

マテリアルレベルでメッシュを削除します。

例えば, 服と体のマテリアルが分かれている場合, これを使うことで服だけ消したり, 体だけ消したりすることができます。

  • ShapeKeyReorder

シェイプキーの順番を変えます。

VRChatでは上から4つのシェイプキーがアイトラッキングに使用されるため, 適切に順番を設定する必要があります。

これをBlenderなどのモデリングソフトを使わずにUnity上でおこなえます。

  • AnimationPropertyConverter

アニメーションファイルに含まれるプロパティの名前を変更します。

表情切り替え時にアニメーションファイルで設定されたシェイプキーの名前でシェイプキーを参照して表情を切り替えています。 ShapeKeyNameChangerなどでシェイプキーの名前を変更した際にシェイプキーを参照できなくなりアニメーションが機能しなくなります。 その際にアニメーションファイルで設定されているシェイプキーの名前を変更後のものに変更することで使えるようにできます。

ShapeKeyNameChangerとあわせてお使いください。


VRCAvatarEditor

UnityでVRChat用アバターを編集することを手助けします。

https://gatosyocora.booth.pm/items/1258744

このツールのポイントは小さなモニターで実際のアバターを確認しながら表情などの編集をおこなえるところです。

以下のような機能を持っています。

  • アバターの簡単な情報を確認したり, 設定したりする
  • アバターの表情を設定する
  • 顔などの一部分だけ光の当たり方が変になる現象を解消する
  • アバターの一部がまれに消えてしまう現象を解消する
  • 使われているシェーダーを確認する

これまで表情設定する際に毎回SceneViewで顔を写しながらするのが大変だったところから、小さなモニターを見ながら編集できるようにしました。

マニュアルもありますが、使い方を紹介してくださっている記事もありますのでそちらを参考にしてみてください。

VRChat 表情変更のやり方|mi|note


EmoteSwitchV3Editor

VRChatのEmoteでオブジェクトを出し入れするEmoteSwitchの設定を簡単におこなえるようにするEditor拡張です。

gend-vrchat.booth.pm

EmoteSwitchV3のギミック本体は元怒さんが作成されたものでPrefab化されており、Editor拡張でそれをアバターに設定しています。

使い方を紹介してくださっている方々がいるのでそちらも記事も参考にしてみてください。

第20回 Emoteで取り出せ!~EmoteSwitchV3解説~ | ユニティちゃんでわかるVRchatのためのunity教室

【VRChat】EmoteSwitch V3(エモートスイッチ)使ってみた!! | ケーキのPC情報集会所


EasyToTakeSSシェーダー

VRChatでスクリーンショットを取るときに撮影画面に貼りつくことで綺麗に撮影できるようにします。

gatosyocora.booth.pm

VRChatではワールドで作成した抱き枕カバー習字スクリーンショットとして持ち帰ったり, シェーダーで処理した結果をSteamCameraで外部配信する際などに使っていただいています。

全般向けツール

ここではVRChatのアバター改変でも使用できますが, その他プラットフォームのアバター改変でも使用することを目指して開発したツールを紹介します。

MeshDeleterWithTexture

Unity上でテクスチャを塗ることで対応するメッシュを削除できます。

https://gatosyocora.booth.pm/items/1501527

これはUnity上で簡単なメッシュ編集する方法としてどんなものがいいかなと模索した結果の一つです。 他にもさまざまな方法で編集ができると良さそうですね。

Quadを使ってメッシュを分割および削除するものを作っておられる方もいます。

処理の高速化のために塗る部分にComputeShaderを使ったり、マスク画像を作れるようにしたりなどちょっとしたポイントにも力を入れました。

こちらの記事で使い方を紹介していただいてます。

[Unity]テクスチャを塗りつぶすだけでメッシュ削除する方法 | VIRTUALBANKAS


ModelBoneDeleter

Unity上でアバターのボーンを削除できます。

https://gatosyocora.booth.pm/items/1484630

ウェイトが塗られたアバターだとボーンを削除するとメッシュがすごいことになります。

本ツールではウェイトを塗りなおすことでこれを解消するように作りました。

こだわりポイントは削除するボーンを選択するところのUIです。たぶん使いやすくなったと思います。


UploadPlatformChecker

現在のビルドプラットフォームを確認できたり, 切り替えたりできます。

gatosyocora.booth.pm

Quest対応アバターをアップロードする際にAndroid用にビルドプラットフォームに切り替える必要があります。

Unityの標準機能でも確認できますが、結構移動しないといけないのでぱっと確認できるようにと作りました。

切り替え機能は実はおまけです。

さいごに

VRにおいてアバターは重要な存在で、特にVRSNSにおいては自分の個性を表現する大きな手段です。 また、アバターはVRSNSをつなぐ架け橋になりうるとも感じています。

どんな人でも表現したいアバターが作れるようになることを望んでこれからもツールを作っていきたいです。

Nostosをプレイして

はじめに

本記事はVRオープンワールドRPG「Nostos」をプレイしてみて感じたことを開発視点で述べています。

あくまで忘れないうちの記録用のような立ち位置です。

特にVRゲームという点に注目してVRにおけるデザイン的な部分が多い気がします。

単にプレイした感想の記事ではなく, メタ的な要素も含まれており世界観を壊しかねないので 不安な方は記事を読まないことをおすすめします。

簡単な感想はレビューに書いたのでそちらをどうぞ https://steamcommunity.com/profiles/76561198372147683/recommended/943150/

Nostosとは

NetEase Gamesから発売されたVRオープンワールドPRGです。

狩りや採掘で食料や武器を集めながらファンタジーな世界で過ごしていきます。 store.steampowered.com

プレイして感じたこと

一通りプレイして感じたことを羅列していきます。

あくまで私が感じた所感であり, 技術的にも心理学的にも根拠のないことがほとんどなのであらかじめご了承ください。

下記の内容は2019年12月11日のリリースバージョンをプレイしたものなのでそれ以降のバージョンでは異なる可能性があります。

統一された世界観はすごく良い

ファンタジー的な世界観で全体的にトゥーン調に仕上がっていて世界としてのまとまりが良かった。 また, 原始的な生活にもかかわらず, 近未来的なかっこいいUIが使われていたが, それは物語で保管されており違和感なく世界観を損なわなかった。 身体的なものを含め様々な矛盾は没入感を損ねる要因になりかねないので, 没入感を維持or高める要因として世界観の統一は重要だと思った。

頭を振ると視界が一瞬暗くなるのは酔い低減になる?

高速に頭を横に振ったときに一瞬視界が暗くなっていた。 これは描画更新時の負荷による動きと視界のラグに対する対策として酔いの低減に関与しそうだと思った。 その反面, 明るいところからいきなり暗くなるという現象は視界的にあまり良くないので逆に酔いの発生原因になりかねないと思った。

車の窓から見ている感は良かった

移動手段の1つである車に乗り込んで移動している際にフロントガラス部分などによって視界の変化量が多い部分が少なくなっていた。 視界の広範囲の情報が変化すると強い酔いに繋がると感じたので視界を絞る手段として有効に感じた。

トリガー長押しによる選択は良かった

採取や装備作成時などにコントローラで触れながらViveコントローラのトリガーを押すUIが用いられていた。 その際にトリガーを一瞬ではなく一定時間押すことで各項目を選択できた。 これはコントローラのトリガーで様々な操作が要求されるVRにおいては語選択を防止するために有効だと感じた。

視界上にHPバーなどがあるのは良さそう

本ゲームでは左上に常にHPバーや状態を示すアイコンが表示されていた。 VRにおいて視界に固定点を置くことは酔いの低減に効果があるといわれている。 よってHPバーを常に視界上においておくことも酔いを低減させる効果があると思われる。

UIを出す手の角度の調整は必要そう

本ゲームでは手の甲部分にメニューUIが存在した。 これは普段は非表示になっており, 手の甲を見るように上に向けると出現する。 しかし, 必要なときになかなか出現することがなく, 回転の閾値は微調整が必要そうだと感じた。

移動時の加速はあまり良くなさそう

止まっているときから移動する際に指数関数的に速度が上がっていた。 これは現実の動きや移動時の視界の見えと大きく異なっているので酔いを起こす要因に感じた。

高速移動時の集中線はあまり良くなさそう

移動時の集中線のようなエフェクトはベクション*1として知覚されそう。 止まってプレイしているとさらに身体運動との矛盾が発生するので酔いの原因になるかもしれない。 ただ過度な集中線がダメであり, 本ゲームで使われている程度のものであれば大丈夫そう。 走っている感は出したいから音を使うのは良さそうという意見があった(良さそう)

頭を動かすと同期して視界が変わってほしい

タイトルやワールドに入った際のロード中に画面が固まる。 様々な処理が動いているので重くなるのは仕方がないが, 頭の動きに対して視界が全く変わらないのは不安感を感じた。 VRゲームではロード時間を長くしてでも身体運動と同期した視界(または違和感がないように)を確保するべきだと思った。 また, 別途ロード時間を暇にさせない工夫が必要。

1人称視点のムービーは良くない

ストーリーを進めているときにアニメーションでキャラが動いている頭の位置に3DoFで1人称な視点へと切り替わった。 視点だけ独立しており, 腕や体の動きは用意されたアニメーションによって実行されていたため, 没入感の低下が懸念された。 また, 視線も映像に合わせて強制的に移動させられたので酔いにもつながりそうだと感じた。 さらに, 映像によってはプレイアブルなキャラクター以外の1人称視点で見せられることがあった。 攻撃されているモンスターなどの1人称視点になったこともあったが, 物語的に意味もなく視点切り替えをするのは世界への没入に関してあまり良くないと感じた。

乗り物系には十分な考慮が必要

移動手段としてバイクや車が登場した。冒険する地形として凹凸が多い地形であり, 崖も多く存在した。 移動時の縦揺れは多く, 崖から落ちた際には1回転すらした。 さらに徒歩より高速な移動をするため, 移動時の視界更新の処理が重くラグがすごかった。 これらですごく酔いを感じたので過剰演出はVRにおいては良くないと思った。

移動するときに視線方向に移動はやめたほうがいいかも

コントローラの前を押すと前方向に移動するが, 正確には視線方向に動いていた。 本ゲームのような膨大なワールドにおいては横を見ながら前方向に移動したいといったことも出てくると思うので移動方法も検討が必要だと思った。

武器の脱着場所は考慮しないといけない

武器は腰あたりにあるところでコントローラのトリガーを押すことで持ったり離したりができる。 腰に近ければ近いほど, 真下を見て脱着部分を目視する必要があり, 高速な脱着は難しい。 現実では触覚などの視覚以外の情報で脱着可能だと思うのでバイブレーションを利用するなどの方法があると思った。 本ゲームでも着脱部分に触れたときに微かに振動したがもっと大げさでも良いと思った。

ボイスチャットの仕様に対して意味を持たせたほうがいい

本ゲームはボイスチャット機能がついているが, ワールドのどこにいても他人の声が聞こえるようになっている。 オープンワールドなゲームにおいては有効に思えるが, VRにおいては現実に似せて自然にしたほうがよいとされるのでデフォルトとしては発声されるプレイヤーの位置から声が発せらえており, 距離減衰が備わっているほうがいいだろう。 本仕様のようにボイスチャットを使うのであれば無線機器などを使った音声通信でやりとりしているなどのその仕様になっている意味を持たせて実装したほうがいいと感じた。

バーチャルな手と実際の手は位置を正確にあわせたほうがいい

本ゲームではコントローラの位置にあわせてアバターの手のモデルがバーチャル空間上に表示されていた。 しかし, Viveコントローラ使用時に座った場合, バーチャルな手の位置が実際の手と比べて前方向に移動してしまうことや 聞いた話ではOculusコントローラの場合は実際の手とバーチャルな手の向きが一致していないことがあった。 手は道具を使用するなどで最もよく見る身体部位である。よってこれに不一致が生じていれば没入感を大きく低下させる可能性があるため, 違和感がないように一致させる必要があるだろう。

*1:映像を見ることで自分は動いていないのに動いているように感じること。視覚誘導性自己運動感覚

VRChatで「見えない」を実装する

がとーしょこらです。
この記事はVRChat Advent Calender 2019の9日目の記事です。
昨日の記事は奈良阪さんによる『今よりもっと「クロスプラットフォーム」なVRChatを作りませんか?
』でした。
adventar.org

本記事ではVRChatで「見えない」を実装するいくつかの方法を紹介します。

VRChatでは見えないオブジェクトを実装することができます。
これは自分にだけ見えなかったり, 特定の方法でだけ見えなかったりすることができます。
これらをうまく使うといろいろなことができるようになります。

この記事で紹介したシェーダーを使った方法を実装した簡単なシェーダーは以下に置いておきます。
drive.google.com

見えないを実装する

いろいろな見えないを実装していきますが, そのすべてを以下の方法で実装できます。

  • 特別なシェーダーを使う
  • レイヤーを使う

しかし, 方法によってはアバターだけワールドだけでしか使えないものもあります。
(対象の方法には[アバター専用], [ワールド専用]と記載してます。)

ワールド専用はワールドのギミックとして見えないを実装するときに使います。
自分が作成したワールド以外でも見えないを実装したい場合はワールド専用以外の方法を用いりましょう。

特別なシェーダーを使う

Unityにおいて見えの部分の大半はシェーダーでなんとかできます。
見えないを実装する場合はそのカメラの状態を調べることでそのカメラに写すかどうかの判断をします。
アバターでは後述のレイヤーを変える方法は使えないのでこちらの方法を使うことになると思います。

レイヤーを変える

カメラに写るかどうかはそのオブジェクトが属するレイヤーによって変えることもできます。
しかし, レイヤーを自由に設定できるのはワールドだけなのでワールドだけで使える方法です。

レイヤーについては以前こちらに詳しくまとめましたので参考にしてください
https://vrcworld.wiki.fc2.com/wiki/Layers

オブジェクトのレイヤーを設定する方法

Unityでのレイヤーはオブジェクトのグループ分けの一種です。
これによってUnityではあるレイヤーのものだけ写せるだったり, あるレイヤーのものだけ持てるなどが実現できます。

例えばCubeにレイヤーを設定する場合はCubeのInspectorでLayerから設定したいレイヤーにチェックをいれることでできます。
(下記の画像の場合はDefaultレイヤーに設定されています。)
f:id:gatosyocora:20191207153559p:plain

方法まとめ

本記事で紹介する方法を先にまとめておきます。

シェーダー(アバター レイヤー(ワールド) その他
VRCCamera 画面サイズ1280x720 & 1920x1080 PlayerLocal, UiMenu, UI
カメラ 設定したRenderTextureのサイズ 設定したレイヤー
unity_CameraProjection[2][0] != 0.f or unity_CameraProjection[2][1] != 0.f PlayerLocal, 設定したレイヤー
自分 自分のローカルカメラが動いているかどうか MirrorReflection Headボーン以下に入れる(アバター)

 

VRCCameraで見えないを実装する

VRモードで使用できるカメラ(通称VRCCamera)で見えないを実装する方法です。

綺麗なワールドを作ったときにスクリーンショットにスイッチなどが写らないようにしたいときなどに使えます。

特別なシェーダーを使う

 VRCCameraの解像度が1280x720なのでこれで判断します。

bool IsInVRCCamera() {
	return (_ScreenParams.x == 1280 && 
		_ScreenParams.y == 720);
}

しかし, この状態だと撮影したスクリーンショットには写ってしまいます。
スクリーンショットの解像度は1920x1080なのでこれで判断します。

bool IsInVRCCameraSS() {
	return (_ScreenParams.x == 1920 && 
		_ScreenParams.y == 1080);
}

レイヤーを変える[ワールド専用]

VRCCameraにはPlayerLocalとUiMenuとUIレイヤーのものが表示されません。
よってこれらのレイヤーになるように設定してあげると良いです。

しかし, PlayerLocalレイヤーは鏡に写らず, 多くの場合UiMenuレイヤーも鏡に写らないように設定することが多いため, VRCCameraには写らないけど, 鏡に写したい場合はUIレイヤーをオススメします。

ワールドのカメラで見えないを実装する

ワールドに置いてあるカメラに写らないオブジェクトを実装する方法です。

ホラーワールドなどの演出や特殊なカメラの使い方の際に写したくないがあるときなどに使えます。

特別なシェーダーを使う

Cameraコンポーネントに設定したRenderTextureのサイズがカメラの画面サイズになるのでこれと一致しているかで判断します。

Properties {
	~
	_CameraRT ("Camera RenderTexture", 2D) = "white" {}
}

~
float4 _CameraRT_TexelSize;

bool IsInCamera() {
	return (_ScreenParams.x == _CameraRT_TexelSize.z && 
		_ScreenParams.y == _CameraRT_TexelSize.w);
}

レイヤーを変える[ワールド専用]

カメラではあらかじめ写さないレイヤーを設定することができます。

CameraコンポーネントのCullingMaskのチェックを外すことでそのレイヤーのオブジェクトは写らないようにできます。そして, 写したくないオブジェクトをそのレイヤーに設定します。

(下記ではStereoLeftレイヤーで本方法を試しています。)
f:id:gatosyocora:20191208015622p:plain
f:id:gatosyocora:20191208015830p:plain

鏡で見えないを実装する

ワールドに置いてある鏡(VRC_MirrorReflectionコンポーネントをつけたもの)に写らないオブジェクトを実装する方法です。

特別なシェーダーを使う

VRChat公式Discordで鏡に写らないシェーダーのコードを公開してくださっていた方がいました。
これを使うことで鏡に写っているオブジェクトか判別できます。
 


bool IsInMirror() {
	return unity_CameraProjection[2][0] != 0.f ||
		unity_CameraProjection[2][1] != 0.f;
}

レイヤーを変える[ワールド専用]

 鏡には仕様によりPlayerLocalレイヤーが写らないようになっています。

また, 鏡についているVRC_MirrorReflectionコンポーネントのReflectLayersでチェックを外すことで写らないレイヤーを追加することができます。
ネームプレートを鏡に写さないためにUiMenuレイヤーも写らないように設定していることが多いです。

このReflectLayersのチェックが外れているレイヤーに設定することで鏡で見えないオブジェクトにすることができます。
f:id:gatosyocora:20191207152933p:plain

自分に見えないを実装する

自分からだけ見えないオブジェクトを実装する方法です。

アバターで首につける装飾が視界の妨げになっているときなどに使えます。

特別なシェーダーを使う[アバター専用]

アバターではカメラが自分の環境だけでしか動かないことを利用して自分の視点かどうか判断をします。
カメラに色のついたオブジェクトを常に写しておきます。
自分の環境ならその色がカメラに写り, 他の人の環境ならカメラが写らず表示されません。
そしてそのカメラにつけたRenderTextureの色を見ることで判断できます。

このような実装で配布されている方がいるのでこちらを利用させていただくのが良いです。
booth.pm

レイヤーを変える[ワールド専用]

これはワールド専用の方法です。

通常, アバターの視点ではMirrorReflectionレイヤーのオブジェクトは見えないようになっています。
これを利用してワールドにおいてあるオブジェクトの場合, MirrorReflectionレイヤーにすることで見えないオブジェクトをつくることができます。

しかし, これは自分の視点から見えなくなるだけでカメラや鏡には表示されます。

Headボーン以下に入れる[アバター専用]

これはアバター専用の方法です。

VRCharの仕様でアバターのメッシュは複製されて, 片方をMirrorReflectionレイヤー, もう一方をPlayerLocalレイヤーになっています。
前述のようにアバターの視点からはMirrorReflectionレイヤーは見えなくなっています。
さらに1人称視点で視界の妨げになる頭のメッシュはHeadボーンのScaleを0にすることで疑似的に消しているようです。

これを利用し, Headボーン以下にオブジェクトを入れることでそのオブジェクトは見えなくすることができます。しかし, そのオブジェクトにVRC_IKFollowerコンポーネントをつけている場合, Headボーンの子ではなくなるようで見えてしまうので注意です。

最後に

特定の環境だけで見えなくするというのはVRやARならではだと思うので
うまく活用すると面白いものがつくれると思うのでぜひ活用してください!

ピクシブ技術職向け夏インターン2019に参加した話

f:id:gatosyocora:20191003131057j:plain

2019年9月4日(水)~13日(金)の8日間開催されたPIXIV SUMMER BOOTCAMP 2019に参加してきました

recruit.pixiv.net

こちらは技術職志望の学生向け夏インターンシップピクシブで展開されている様々なサービスに実務形式で関わることができるものです。

この中でも私はpixiv コミック(Android)コースで参加させていただきました。

 

 

 

なぜ参加したのか?

ピクシブが展開しているイラスト投稿サービスpixivを始め, BoothやVRoid関連など様々なサービスにお世話になっています。また,ピクシブが掲げる「創作活動がもっと楽しくなる場をつくる」という企業理念がいいなと感じたので, どんな環境でどんな人たちが働いているのかを知るために参加しました。

 

pixivコミックとは?

インターンでやったことを話す前にこれを軽く触れておく必要があると思います。

pixivコミックとは簡潔に説明すると電子書籍マンガが読めるサービスです。

プロの漫画家の人気作品だけでなく,pixivに投稿されたマンガも読むことができます。

Webブラウザからだけでなく, AndroidiOSのアプリからもサービスを利用できます。

comic.pixiv.net

 

やったこと

今回のインターンでは, pixivコミックのAndroidアプリのアカウント情報編集画面の新UIの作成をおこないました。

 

1日目

開発環境を準備したりしていました。

IDEを準備するときによくハマりがちなので今回も案の定Android Studioの設定でハマってしまいました。他にもチーム内で開発で使っているツールを準備しました。(slackとかgithubとか)

チームごとに使うツールが違うらしいです。(サービスの内容や対象プラットフォームが違うのでそれはそうだなーって感じですね)

 

2, 3日目

pixivコミックのAndroidアプリはkotlinで開発されています。以前JavaでのAndroidアプリはやったことあるのですが, kotlinは初めてだったので簡単なタスクをおこなって慣れていきました。実際に動いているサービスに自分がコミットすることは初めてて人生初のPull RequestをLGTMしてもらいました。

 

4~7日目

メインタスクをおこなっていきました。

アカウント情報管理画面はこんな感じの画面です。

f:id:gatosyocora:20190929154311p:plain

 アカウント情報がそれぞれ表示されています。

そして「>」がついている項目はタップすると下図のようにダイアログが表示されて変更できます。

 

f:id:gatosyocora:20190929154315p:plain

アカウント情報の変更には同じAPIを使っており, 複数の項目を変更しようとするとリクエストが項目ごとに飛んでよくないので一気に変更できるようにしたいということで新UIの実装をおこないました。

新UIは既にデザイナーさんが考えてくださっていました。
各項目はテキストを入力できるようになっていて, いずれかを入力すると更新ボタンが押せるようになって更新できるという感じです。

 

今回のインターンシップで実際にできた画面はこちらです。
パスワードを変更しようと入力しています。
(動いているところはリリースされてから実際に触って確認してみてください)

f:id:gatosyocora:20191003130550p:plain

 

この画面を作成するためにいろいろな課題がありました。

  • 新UIではUIを構成するViewがいろいろ変わっているため確かめながらやっていく必要がある
  • 最初期につくられた画面なので他の画面では採用されているMVVM的な設計がされていない

これらを主に解決できるように進めていきました。

 

1つ目はマテリアルデザインなViewを使う必要がありました。
マテリアルデザインとはGoogleが推奨するデザインです。

material.io


特徴としてはボタンからの影が落ちていて浮かんでいるように見せて、ひとつの分離したオブジェクトとして見せている感じです。
特に今回はテキストを入力するためにTextInputLayoutを使ったわけですが, 他の画面で使われていなかったので調べながら変更する必要がありました。
特にデザインを意識してそれぞれのプロパティを設定するのが大変でした。

 

2つ目はすべての処理を画面を構成するActivityに書いてあったので分ける必要がありました。
アプリ全体としてMVVMが採用されており, 役割ごとにコードを分離していきます。具体的には

  • Activity : 画面のViewを操作する
  • ViewModel : 画面に表示する情報を取得したり, 加工したりする
  • Repository : 情報をAPIやキャッシュから取得する

のような感じに分けました。
これは他の画面では実装されていたのでそれを参考にしながら変更しました。画面の設計にはRxBindingも使われていました。Rxは聞いたことはあるもののこれもメンターの方に教えてもらいながら実装していきました。

 

8日目(最終日)

最終日はやった内容を報告するプレゼンをおこないました。

プレゼンの準備は前日からおこなっていましたが, ぎりぎり準備がまとまった感じでした。プレゼンは自分が想定していた通りうまく行きましたが, 他のインターン参加者のプレゼンがエンジニアらしい技術的なプレゼンばかりでした。私のプレゼンは一般向けのような構成にしていたので技術的な部分はあまりなかったので対象を見定めてプレゼンをおこなう必要があると感じました。

 

会社の雰囲気

多くのチームで10時に今日やることを確認するミーティングをおこなって19時に業務を終わるという感じでした。

印象に残っているのが19時以降の時間の使い方です。社員同士で雑談をしたりゲームをしたりしていました。特にインターンシップに参加したときはポケモンカードが流行っていてバトルしている光景を見かけました。他にも麻雀やボードゲーム, ぷよぷよなどもやっていました。他にもイベント会場として貸していることも多く, 勉強会もおこなわれていました。

また, 毎週水曜日には全社会という社員全員が参加する集まりもありました。ピクシブは多くのサービスを取り扱っているので他のプロダクトの状況や方針などを共有できる場はすごく大切だと思いました。ここで社員全員に対して新しく入った社員が自己紹介をおこなったりもしていました。その日の昼には部署関係なく集まってランチをするランチ会というのもおこなわれて社員交流の場としてすごく良かったです。

ピクシブのサービス的にも社員さんの中に様々なジャンルや作品のコアなファンが多くてインターン初日にもデレマスのライブに参加するために休んでいる社員さんが何人かいました。趣味に寛容で全力な人も多いと感じました。

 

まとめ

インターンは参加してすごく良かったです。

今回の目的だった「どんな環境でどんな人たちが働いているのか」は個人的に十分に知れましたし, kotlinはいいぞってなったのでAndroid開発をするときには積極的に使っていきたいと思います。

普段はUnityとC#で開発をしていますが, C#は最近のバージョンではnull許容やreadonlyなどでどんどんkotlinに近づいてきているのでさらに使いやすくなっていきそうです。
また, 今回使ったMVVMやRxも普段の開発にどんどん取り入れていきたいと思います。

心残りとしては本当はVRoidがあればそちらで応募予定だったのですが, 今回はなかったのでまたあればそちらで参加もしてみたいですね。

ノベルティもいっぱいもらいました(嬉しい)

f:id:gatosyocora:20191003133521j:plain