MkItYs

MkItYs > 音楽・漫画・VR・自律制御 > 

images

物理ベースのキャラに実在感を与える(振り向かせる、重みや抵抗、など):Unity (Quaternion)

images

物理ベースのキャラに実在感を与える、いくつかの手法を示します。

振り向かせる


顔の向きを利用者に追随させるのに、物理ベースのキャラでも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. )は、空間にキャラクタを<ピン留め>することで、重みや抵抗の感覚を実現していますーーただそういったやり方では、キャラクタが自律的に動くことができないので(強化学習による自律歩行など)、汎用性という点で限界がありますし……