hildsoftのコード置き場

プログラム関連で調べたことやコードの保管場所です

Unityの物理演算(Rigidbody)を設定したオブジェクトが崩れたりバラけたりして安定しない

UnityのRigidbodyが崩れたりバラけたりするため上手く積めない

検証環境

Unity:5.6.1f1

Rigidbodyコンポーネント

f:id:hildsoft:20170621091637p:plain

RigidbodyはUnityで物理演算で物を動かす時などに使います。

ただ、初期設定のままで使うと、上手く積むことができません。

意図したところでピタっと止めたい場合の対処法です。

Cubeを縦に10個、横に4個積んでみました。

f:id:hildsoft:20170621091755p:plain

左側はキッチリと積めていますが、右側は揺れていて安定しません。

微妙な力がお互いに影響し合っている状態ですね。

Dragの値で調整

設定調整で簡単に動きを止めることはできます。

f:id:hildsoft:20170621092454p:plain

何をしたかというと、Dragの値を調整しました。

公式のヘルプによるとDragは

力により動く際に、オブジェクトに影響する空気抵抗の大きさ。0 の場合、空気抵抗が 0 で、無限の場合、オブジェクトは動きを止めます。
「 Drag 」値が低いと、オブジェクトが重く見えるようになります。この値が高いと、軽く見えます。「 Drag 」の通常の値は、.001 (金属の塊) と 10 (羽) の間です。

とのことです。

今回は右側のオブジェクトはDrag値:0
左側のオブジェクトはDrag値:20
にしました。

確かにDrag値を増やせば動きにくくなり安定します。

しかし、安定するということは、動かしたいときに動かしにくいということにもなります。

公式のヘルプでも"通常の値は、.001 (金属の塊) と 10 (羽) の間"との記載があります。

Dragの値での動きにくさ

同じ重さの球を同じ速さでぶつけてみます。

Drag:0

f:id:hildsoft:20170621093253g:plain

Drag:20

f:id:hildsoft:20170621093453g:plain

このように、キッチリと積むことはできても、思ったような物理演算を実現できなくなる可能性があります。

力を加えても空気抵抗が大きすぎるため、すぐに止まってしまうのです。

水中で物を動かすのに近いですね。

Rigidbodyの物理動作を止める

Rigidbodyは計算量節約のため、動作時(Awake)と停止時(Sleep)の状態を持っています。

停止状態では物理演算が行われないので、初期位置から動くことはありません。

f:id:hildsoft:20170621094556p:plain

起動時に強制的に停止状態にしておくことで、初期配置でグラグラ動いたり、はじけ飛んだりすることを防げます。

各Cubeに、下記のスクリプトを追加しました。

void Start () {
    this.GetComponent<Rigidbody>().Sleep();
}

停止状態は、新たにColliderが接触したりWakeUpメソッドなどで解除できます。

f:id:hildsoft:20170621094856g:plain

先ほどと同じように球をぶつけてみると、Drag:0の時と同様に崩れていきます。

関連リンク

Unity - マニュアル: Rigidbody

Unity - スクリプトリファレンス: Rigidbody

UnityでスクリプトからTransformコンポーネントを取得する方法

UnityでスクリプトからTransformコンポーネントを取得する方法

検証環境

Unity:5.6.1f1

Transformコンポーネント

Transformコンポーネントは、すべてのGameObjectに追加される基本的なコンポーネントです。

位置、回転、スケール、親子情報などシーン内のGameObjectにアクセスするために使用します。

空のオブジェクトを作成しても追加されます。

f:id:hildsoft:20170616093504j:plain

アタッチされたゲームオブジェクトのTransformコンポーネントにアクセス

f:id:hildsoft:20170616100333j:plain

アタッチされているC#スクリプトから自身のTransformへは簡単にアクセスできます。

MonoBehaviourを継承していればフィールドにありますので、

Transform myTransform = this.transform;

だけで使用可能です。

親子間のTransformコンポーネントにアクセス

親の場合

var parentTransform = this.transform.parent;

子の場合

var childTransform = this.transform.Find("child_name");

// 古い取得方法
//var childTransform_old = this.transform.FindChild("child_name");

“child_name"部分に、Hierarchyに表示されている子要素の名前を設定してください。

それ以外のTransformコンポーネントにアクセス

親や子を伝って取ることがほとんどだと思いますが、親子関係にないオブジェクトは検索して取得することになります。

var anotherTransform1 = GameObject.Find("object_name").transform;
var anotherTransform2 = GameObject.Find("/parent/child").transform;

/で区切ることによって階層を指定して検索することもできます。

名前が同じものが複数ある場合は、最初に見つかったもの(Hierarchyの順とは限らない)が取得できますが、同じ階層で重複する名前は極力使わないようにしましょう。

また、Hierarchy上で灰色(Inspectorで使用をoff)にしている状態だと探せませんので、NullReferenceExceptionに注意してください。

関連リンク

Unity - スクリプトリファレンス: Transform

Unity - スクリプトリファレンス: GameObject.Find

プライバシーポリシー

プライバシーポリシー

広告について

当サイトでは、第三者配信の広告サービス(GoogleアドセンスA8.netAmazonアソシエイトバリューコマース)を利用または利用を予定しています。 広告配信事業者は、ユーザーの興味に応じた広告を表示するためにCookie(クッキー)を使用することがあります。 Cookieを無効にする設定およびGoogleアドセンスに関する詳細は「こちら」をご覧ください。

アクセス解析ツールについて

当サイトではアクセス解析ツール「Google Analytics」を利用しトラフィックデータ収集のためにCookieを使用しています。 またトラフィックデータは匿名で収集されており、個人を特定するものではありません。 もし収集を拒否したい場合はCookieを無効にしてください。 この規約に関して、詳しくはこちら、またはこちらをクリックしてください。