衝突判定



MeshFilterとcolliderを実装したゲームオブジェクトはマウスクリックされたかどうかを無計算で検出できる


[RequireComponent(typeof(MeshCollider))]
public class MikuPeiceCtrl : MonoBehaviour {

  bool isNowDragging = false;

  //計算抜きで自分のメッシュの上でクリックされたか調べられる 
   void OnMouseDown(){
       isNowDragging = true;
   }
   
   void OnMouseUp(){
       isNowDragging = false;
   }
}


衝突発生時コールバックするオーバーライド関数


適用するオブジェクトにはcolliderとrigidBodyが必要です

<?php


using UnityEngine;
using System.Collections;

public class HitTest1 : MonoBehaviour {

    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
    
    }
    
    //衝突が始まったときに1度だけ呼ばれる関数(接触したオブジェのタグを表示する) 
    void OnCollisionEnter(Collision col){
        print("col_enter:"+col.gameObject.tag);
    }
    
    //衝突が終わったときに1度だけ呼ばれる関数
    void OnCollisionExit(Collision col){
        print("col_end:"+col.gameObject.tag);
    }
    
    //衝突している間呼ばれる関数(完全に静止したオブジェクトでは呼ばれない) 
    void OnCollisionStay(Collision col){
        print("col_stay:"+col.gameObject.tag);
    }
    
    //以下はトリガー用------------------------------------------------------- 
    //コールバック関数の引数がCollisionとColliderで違いがあることに注意 
    
    void OnTriggerEnter(Collider col){
        print("trig_enter:"+col.gameObject.tag);
    }

    void OnTriggerExit(Collider col){
        print("trig_end:"+col.gameObject.tag);
    }
    
    //注意:こちらは静止していても中にいる間は呼ばれ続ける 
    void OnTriggerStay(Collider col){
        if(col.gameObject.tag =="Enemy")
        {
            print("Hit Enemy tag object");
        }
    }
 }

?>

キャラクターコントローラーを使った衝突判定


通常時のやり方とは少し変わってくる点に注意
<?php

using UnityEngine;
using System.Collections;

public class HitTest4 : MonoBehaviour {

    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
    
    }
    
    //オブジェクトがCharacterControllerで動かされている場合OnControllerColliderHit以外で衝突は検出できなくなる事に注意 
    //OnCollisionEnterは反応しにくくなる(反応しない訳ではない) また「物体が動いている間だけ」呼び出しが発生する 
    void OnControllerColliderHit(ControllerColliderHit hit){
        if(hit.gameObject.tag == "Enemy"){
            print("hit");
        }
        
        //物体を押す処理(Enamy2タグのついてるオブジェクトは押せる)
        if(hit.gameObject.tag == "Enemy2"){
            Rigidbody body = hit.collider.attachedRigidbody;
            
            if(body == null | | body.isKinematic){return;}    //rigidBodyがない、もしくは物理演算の影響を受けない設定をされている 
            if(hit.moveDirection.y<-0.3){return;}            //押す力が弱い 
            
            Vector3 pushDir = new Vector3(hit.moveDirection.x,0,hit.moveDirection.z);    //y成分を0に 
            
            float pushPower = 2.0f;
            body.velocity = pushDir * pushPower;    //押す力を加える 
        }
        
    }
    
    //これはめり込むなどの非常時以外反応しない 
    void OnCollisionEnter(Collision col){
        print("OnCollisionEnter_hit");
    }
    
    //これは機能する 
    void OnTriggerEnter(Collider col){
        print("OntriggerEnter_hit");
    }
}

?>

衝突時の処理

<?php

using UnityEngine;
using System.Collections;

public class HitTest1 : MonoBehaviour {

    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
    
    }
    
    void    OnTriggerEnter(Collider col){
    
        //SendMessage(“関数名”) で対象が持っているスクリプトが持っている関数を呼び出すことができる  
        if(col.gameObject.tag == "Enemy"){
            col.gameObject.SendMessage("ScoreAdd",10);
        }
        
        //コンポーネントとしてスクリプトオブジェクトを取り出し関数を実行する事もできる 
        //呼び出される側の関数は勿論publicにしておく事を忘れずに
        //ちなみに上のやり方だとprivateでもOK
        if(col.gameObject.tag == "Enemy2"){
            Enemy2Script script = col.gameObject.GetComponent<Enemy2Script>();
            script.ApplyDamage(10);
        }
        
        //どちらの方法を選ぶかは好みや状況による 
    }
}


using UnityEngine;
using System.Collections;

public class ScroeAdd : MonoBehaviour {
    
    private int score = 0;
    
    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
    
    }
    
    void ScoreAdd(){
        print("Score= "+ ++score);
        
    }
}


using UnityEngine;
using System.Collections;

public class Enemy2Script : MonoBehaviour {
    
    public int life=50;
    
    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
    
    }
    
    public void ApplyDamage(int damage){
        life-=damage;
        print("LifePoint= " + life);
    }
}

?>

RayCastによる衝突判定


レイ投射により、その線上のオブジェクト衝突を検出する事が出来る

<?php


using UnityEngine;
using System.Collections;

public class raycastHit : MonoBehaviour {

    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
        
        //レイを飛ばしてその線上のオブジェクトを検出する 
        //第3パラメータにRaycastHit型の変数を渡すとレイが当たったときの情報をその変数に代入して返す 
        //その変数をcolliderとして扱うと情報が引き出せる
        RaycastHit hit;
        if(Physics.Raycast(transform.position,Vector3.right,out hit,Mathf.Infinity)){
            print("find" + hit.collider.gameObject.name);
        }
    }
}


?>

画面に対するRayCastによる衝突判定(マウスポインタ上のオブジェクトを検出する)

<?php

using UnityEngine;
using System.Collections;

public class raycastHit : MonoBehaviour {

    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
        
        if(Input.GetMouseButtonDown(0)){
            
            RaycastHit hit;
            //カメラからみたマウス位置のレイ
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            
            //レイを投射してオブジェクトを検出
            if(Physics.Raycast(ray,out hit)){
                print(hit.collider.gameObject.name);
            }
            
        }

    }
}

?>

配置したPlaneコリジョンから平面上の衝突「位置」を割り出す


using UnityEngine;
using System.Collections;

public class RayCastTest : MonoBehaviour {
  
   // Use this for initialization
   void Start () {
   }
   
   float depth;
   Vector3 worldPosition;
   
   // Update is called once per frame
   void Update(){
       
       if(Input.GetMouseButtonDown(0)){
           
           //Planeメッシュとは無関係の無限な平面を持つアタリ判定 
           Plane plane = new Plane (Vector3.up,Vector3.zero);
           //カメラからマウス位置へレイを飛ばす 
           Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
           
           //Planeメッシュから衝突を検出して深度から位置を割り出す 
           if(plane.Raycast(ray,out depth)){
               worldPosition = ray.origin + ray.direction * depth;
           }
           else{
               worldPosition = Vector3.zero;
           }
           
           print(worldPosition);
       }
   }
}


レイキャストの親戚



Physics.LineCast() ワールド座標で始点と終点を指定する使いやすいキャスト。無限長のレイだけが撃てない
Physics.SphereCast() 球を始点から終点まで引っ張る。いわば太いレイキャスト
Physics.CapsuleCast() カプセルヒット形状を始点から終点まで引っ張る


colliderのトリガー化


colliderをトリガー化するとヒット形状の中に進入できるようになる
インスペクタ内のIsTriggerスイッチをオフにすると設定できる

メモ


  • ゲームオブジェクトには複数のコライダーを取り付けることができる
  • 見た目に正確なメッシュコライダーと、大きめのカプセルコライダーの2つを取り付けて、ヒット判定は前者、イベント判定は後者で行うことが可能

メニュー



  • 最終更新:2014-06-13 12:09:40

このWIKIを編集するにはパスワード入力が必要です

認証パスワード