質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

15049閲覧

Unityで衝突したオブジェクトを指定した方向へ飛ばす武器の作成

gkjsanghrojlka

総合スコア9

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

4クリップ

投稿2017/06/12 15:31

###前提・実現したいこと
Unityでオブジェクトを指定した方向へ飛ばす武器を実現したいです。
想定しているものは例えるなら大乱闘スマッシュブラザーズのアイテム「ハンマー」です。
アニメーションを起動すると左右に往復運動を行い、他のオブジェクトと衝突したときにエフェクトを発生させ、ハンマーの動きに合わせて飛ばす方向が変わるものを理想としています。

###発生している問題
・animationで時間によってRotationを変更していますがワールド座標系からローカル座標系に変換する方法がわかりません。
・アニメーション起動とともにColliderを出現させ、衝突するとparticleも発生させることはできたのですが、衝突したオブジェクトの挙動を操ることができませんでした。

###試したこと
C#で作業を行っています。
・OnCollisionEnterを使用して衝突の判定を行い、衝突した位置をContactPointで格納しVector3に置き換えることはできたのですが、保存した位置をどのように使えばいいのか調べてもわかりませんでした。
・AddforceやLookat関数も使おうとしましたが扱う座標系をどう合わせればよいのかわからず仕舞いです。
伝わりずらい部分も多いとは思いますがアドバイスをいただけないでしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

座標系変換については、変換行列が欲しい場合はtransformのlocalToWorldMatrixworldToLocalMatrixを使い、あるローカル/ワールド座標が、ワールド/ローカル座標系だとどうなるかが分かれば十分であるなら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/06/17 12:27

Bongo

総合スコア10807

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gkjsanghrojlka

2017/07/04 14:51

丁寧な回答ありがとうございます! コメント遅くなりました。 無事衝突時にオブジェクトを飛ばすことができました。 想定しているものでは球体にぶつかるものであるので衝突個所により吹っ飛び方が変わる必要はなかったのでそのままスクリプトを引用させていただきました。 また、ほかの武器作成時にも参考にさせていただいているので非常にためになりました。 ありがとうございます!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問