物理ベースのキャラに実在感を与える、いくつかの手法を示します。
振り向かせる
顔の向きを利用者に追随させるのに、物理ベースのキャラでもLookAt()が使えます。
これはキネマティクスのアニメーションを、ダイナミクスに変換する要領と同じですーーまず次のように空のオブジェクトを配置し:
- ・
- キャラの首の、子ノードにする
- ・
- キャラの頭と、同じ位置に置く
次いで空オブジェクトをLookAt()で利用者の方へ向ければ、首と頭(が向くべき方向)のローカルの角度差が得られますーーあとはそれをConfigurableJoint のターゲットに設定することで、物理演算による、キャラの頭の回転が実行されます:[※1]
public GameObject objhed, objtgt; private GameObject objvir, objpar; private ConfigurableJoint cfjhed; private Quaternion rotini; private void Start() { rotini=objhed.transform.localRotation; cfjhed=objhed.GetComponent<ConfigurableJoint>(); objpar=cfjhed.connectedBody.gameObject; objvir=new GameObject(); objvir.transform.parent=objpar.transform; } private void Update() { objvir.transform.position=objhed.transform.position; objvir.transform.LookAt(objtgt.transform); cfjhed.SetTargetRotationLocal(objvir.transform.localRotation,rotini); }
- ※1
- ここでも、ConfigurableJoint の機能を拡張する次のメソッドを使います:
- ・
- https://gist.github.com/mstevenson/7b85893e8caf5ca034e6
物理的な反応をほどこす(重みや抵抗を感じさせる)
XR上のキャラクタに、もっともらしい物理的な反応をほどこす(利用者に重みや抵抗を感じさせる)には、次のような物理特性を調整します:[※1][※2]
- ・
- Rigidbody.mass
- ・
- Rigidbody.drag
- ・
- Rigidbody.angularDrag
- ・
- Collider.material (PhysicMaterial.dynamicFriction)
- ・
- Collider.material (PhysicMaterial.staticFriction)
- ・
- Collider.material (PhysicMaterial.bounciness)
- ・
- ConfigurableJoint.slerpDrive (JointDrive.positionSpring)
- ・
- ConfigurableJoint.slerpDrive (JointDrive.positionDamper)
- ・
- ConfigurableJoint.slerpDrive (JointDrive.maximumForce)
- ※1
- とはいえ、この調整にも限界がありますーーひとつはコントローラに物理演算を適用できないためですねーーキャラクタはダイナミクス(優先:Rigidbody )で演算するのに対し、コントローラを利用者の腕や指の動きに追随させるには、キネマティクス(優先:Transform )で演算するしかありません。XRの利用者は、XRのキャラクタに対し無限大の力で対応することになるので、どうしてもムリは出ますーーこれを解決するには、ジャイロなどコントローラそのものの改良が必要になるでしょうか。
- ※2
- もちろんそれなりに回避策はありますーーたとえば一部のアプリ(VaM, etc. )は、空間にキャラクタを<ピン留め>することで、重みや抵抗の感覚を実現していますーーただそういったやり方では、キャラクタが自律的に動くことができないので(強化学習による自律歩行など)、汎用性という点で限界がありますし……