環境
開発環境
-
Unity5.5
- 5.6にはRectTransformとCanvasのバグがあったので使ってないです
- OculusRift
- PhotonNetwork
Asset
- FinalIK(有償)
- Unity-chan(無償) ※2017/6/12現在アセットストアのはバージョンが古かったので公式からダウンロードするのがいいと思います
- Oculus Utilities for Unity 5(無償)
- PhotonUnityNetwork(無料プランもあります)
やりたかったこと
- Unity-chanをOculusRiftで手と頭のトラッキングをして、コントローラーでワープ移動(VRでよくある移動先をコントローラーで指し示して一瞬で移動する方法)できるようにする
- またアナログスティックで前後移動と左右の回転もできるようにする
- トラッキングはOVRCameraRigをつかって問題なく動作できた
- Unity-chanにはFinalIKのVRIK、PhotonViewとPhotonTransfromViewのコンポーネントをアタッチしてPhotonViewでPhotonTransformViewをObservedComponentsに入れていた
- それをネットワーク上で同期させたい
問題
現象
- Unity-chanをA地点からB地点にワープさせるとA地点に足が地面にくっついたままびよーんと伸びてしまう
解決方法
足が伸びてしまう問題の解消
- リファレンスに載ってないのでVRIKのスクリプトから処理を追っていくと、IKSolverVR にReset関数が用意されており以下のようにコメントされていたのでこれを使うことで解消した
Resets all tweens, blendings and lerps. Call this after you have teleported the character.
- ローカルでは移動処理後に
Reset()
を呼び出すと自然な動きになった
ネットワーク上で互いに移動すると足が伸びてしまう問題の解消
- はじめは自身のワープ処理後にRPC経由で
Reset()
を呼び出したが、同期がうまくあわないのか(?)うまくいかなかった -
PhotonTransformView
を使うのをやめて、PhotonView
のOnPhotonSerializeView
でTransform
を同期し、Updateの!PhotonView.isMine
の中で同期を行うように変更し、その中で移動距離に応じて、アナログスティック移動とワープ移動を理由、ワープ移動内でのみReset処理を呼び出した
void Update() {
if (photonView.isMine) {
// do anything
} else {
float distance = Vector3.Distance(transform.position, currentPosition);
if(distance > 1.0f) {
transform.position = currentPosition;
VRIK ik = GetComponentInChildren<VRIK>();
if (ik != null) {
ik.solver.Reset();
}
} else {
transform.position = Vector3.Lerp(transform.position, currentPosition, Time.deltaTime * 5);
}
transform.rotation = Quaternion.Lerp(transform.rotation, currentRotation, Time.deltaTime * 5);
}
}
void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info) {
if (stream.isWriting) {
stream.SendNext(transform.position);
stream.SendNext(transform.rotation);
} else {
currentPosition = (Vector3)stream.ReceiveNext();
currentRotation = (Quaternion)stream.ReceiveNext();
}
}
- ちなみにMonoBehaviorのUpdateの中で
Reset()
呼んだらどうなるか試してみましたが、足とかが常に軸回転してしまうのでやめたほうがいいです
うまい方法がほかにあればご教授いただけるとうれしいです