座標系変換については、変換行列が欲しい場合はtransformのlocalToWorldMatrixやworldToLocalMatrixを使い、あるローカル/ワールド座標が、ワールド/ローカル座標系だとどうなるかが分かれば十分であるならTransformPointを使うのが簡単かと思います。
衝突を検出するところまで来ているようですので、あとは衝突相手のRigidbodyに対してAddForceで力をかければ飛んでいくかと思いますが、力のベクトルをどうするかは確かに悩みどころかもしれませんね。
とりあえず思いついたのは、ContactPointはエフェクトの表示だけに使うことにして、吹き飛ばしベクトルは「(衝突相手の座標 - ハンマーの回転中心座標)を正規化し、適当な係数をかける」方法ですがどうでしょう?
試しに作ってみたものは以下のような構成です。ご質問者さんの設計に合わせて適宜アレンジしてみてください。
- ハンマーの頭部と柄を用意し、これらを空のGameObjectに入れてハンマーとし、これをアニメーションで動かす
- 頭部に衝突検出用スクリプトをアタッチする
衝突検出用スクリプト(エフェクト表示は省略)
C#
1using UnityEngine;
2
3namespace Assets.Scripts
4{
5 public class HammerCollisionHandler : MonoBehaviour
6 {
7 private float impulseMagnitude;
8
9 private void Start()
10 {
11 this.impulseMagnitude = 50.0f;
12 // 衝突時に発生させる力積の大きさ、とりあえず50ニュートン秒とした
13 }
14
15 private void Update()
16 {
17 }
18
19 private void OnCollisionEnter(Collision collision)
20 {
21 var rigid = collision.gameObject.GetComponent<Rigidbody>();
22 // 衝突相手はRigidbodyをアタッチした立方体で、別途空から降らせる
23
24 var impulse = (rigid.position - transform.parent.position).normalized * this.impulseMagnitude;
25 // 衝突相手の座標から回転中心の座標(頭部から見てハンマー本体は親なので、transform.parent.positionで親の位置をとる)を引き、正規化してimpulseMagnitudeをかける
26 // ※衝突相手とハンマーはどちらもシーンの一番上層にあるので、それらの座標がそのままワールド座標になる
27
28 rigid.AddForce(impulse, ForceMode.Impulse);
29 // 瞬間的な衝撃をかける場合(力積を加える場合)はForceMode.Impulseを使う
30 // ※ちなみにVelocityChangeを使うと衝突相手の速度を直接変えられる
31 // 今回は衝突相手の質量に応じて吹き飛び量を変えたかったため、Impulseとした
32 }
33 }
34}
動かすと以下の図のようになりました。なお、立方体は1kg〜5kgをランダムに降らせており、色が黒いものほど重いです。
スマッシュブラザーズらしくするには、もっと動きをチューニングする必要がありそうですが、とりあえず吹っ飛ぶようにはなりました。
また、別パターンとして、ハンマー自体にもRigidbodyをアタッチし、アニメーションではなくAddForceで動かしてみると下図のようになります。
ハンマーの打撃面が立方体中心にミートするとよく飛び、外れると回転するような動きになりました。
物理的なリアリティは向上しそうですが、スマッシュブラザーズからは遠ざかってしまったように思います。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/07/04 14:51