53
38

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

衝突判定の再考、壁抜けを止める:「はじめてのUnity」のブロック崩しを改造しながら学ぶ

Last updated at Posted at 2015-07-03

#この解説は
Unityのサイトに昔からあるチュートリアルに、以下があります。
「はじめてのUnity」(旧)
http://tutorial.unity3d.jp/archive/my-first-unity/

これを独自にC#化したものをベースとしています。以下を
この解説は以下の段階があります、前の内容を実行した上でのものとして参照して下さい。現時点(20151026)では、新しい「はじめてのUnity」の玉転がしゲームが公開されています。本サイトのブロック崩しと併せて学習すると広がりがあり、初期の学習にはとても有効です。

#衝突判定の再考
現状での動作はほぼ問題ありませんが、内容を考えなくてはならない部分があります。壁にめり込んだり、抜けたりする場合です。
ラケットの速度は、以下の設定で変わります。

  • RacketRigidbodyコンポーネント内にあるMassが小さいと軽くなって速くなる
  • Racket.csにある変数accelの値が大きいと、加えられる力が大きくて速くなる

これらを修正して、ゲームに合った心地よい操作感を実現していきますが、速くすると、ラケットを左右に振るったときに、壁にはまる、或いは壁の外に出る時があります。
Gyazo

現実の堅さのある物体であればこうした現象は発生しませんが、ゲーム内では発生します。この現象は何故起きるのでしょうか。

##衝突判定の仕組み
Unityでは衝突判定を、一定時間ごとに以下で行っています。

Colliderコンポーネント同士の接触

で判定しています。

##Colliderの状態を確認
LeftWallRacketはそれぞれBox Colliderコンポーネントをそれぞれ、持っています。
この図は、racketのものです。
Gyazo

デフォルトの設定では、Unity内で創りだして置いたCube型のGameObjectColliderの大きさは、見えている外観と同じ物が与えられています。形を確認したい場合は、Box Colliderコンポーネントの[Edit Collider]ボタンを押してみてください。大きさや位置の変更が可能です。
Gyazo

壁にはまっている状態では、Rigidbodyコンポーネントで物理的な動きをしていますので本来、交差はできないので、どう対応するか分からない状態になっています。

##「一定時間」の定義
Unityでは物理判定の処理を、デフォルトでは0.02秒毎に処理します。この値は、[Edit]>[ProjectSettings]>[Time]で設定されており、変更も可能です。[Inspector]タブのTimeManagerFixed Timestepがそれにあたります。
Gyazo

くわしくは以下を参照してください。
[Unity-マニュアル:タイムマネージャ
http://docs.unity3d.com/ja/current/Manual/class-TimeManager.html]
(http://docs.unity3d.com/ja/current/Manual/class-TimeManager.html)

細かければ緻密な処理は可能ですが、演算を多く必要とする可能性が高く、少ないと粗い動きになる可能性があります。

##抜けていく現象の原因
この一定時間の間隔で衝突判定をしていますが、その瞬間に交差しているかが問題になります。現状の抜けている原因は、速度が速いために、物理的に留まるべき状態を瞬間に検知できていないからです。
Gyazo

##解決の方法を模索する
現状の衝突判定を考えて対策する方法は、以下があります。

  1. 衝突判定を瞬間毎ではなく継続性のあるものにする
  2. Fixed Timestepの値を小さくして、物理処理の実行頻度を上げる
  • 【×】物理演算の回数がゲーム全体で増加するため、処理が鈍重になる可能性がある
  • 【×】他の物理演算に影響する
  1. 抜けてはならない物体に対し内部に交差した状態になってしまった場合、強制的にScriptで座標を戻す
  • 【×】衝突判定を2度しているのが無駄になる
  • 【×】Rigidbodyでの物理的な動作が、強制的に変化させると異常になる
  • 【×】対象物によって判定が複雑になる(垂直・水平以外は面倒な数式になる)

この中で、選ぶべき方法は、__衝突判定を瞬間毎ではなく継続性のあるものにする__になります。

##衝突判定の方法を変える
Racketを選択し、[Inspector]タブでRigidbodyCollision DetectionContinuosに変えます。

Gyazo

ここの部分の設定は、物体が動いている場合に抜けてしまう時、有効です。衝突判定したいもので、片方が動いている場合はこれを設定してください。この設定を行うと、移動中にどこかのColliderと衝突していれば、検知します。
この部分の設定をくわしく知りたいときは、以下を参照してください。

[Unity-マニュアル:リジッドボディ
http://docs.unity3d.com/ja/current/Manual/class-Rigidbody.html]
(http://docs.unity3d.com/ja/current/Manual/class-Rigidbody.html)


#まとめ

  • 衝突の判定は
  • 対象をCollider同士で行われる
  • タイミングは一定時間で制御している(Fixed Timestep)
  • 衝突判定は瞬間ごとで抜けているために、求める状態にならない場合がある
  • 衝突判定を移動体に対して継続的にしたい場合、対静物ではCollision DetectionContinuos
53
38
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
53
38

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?