1. 程式人生 > >unity ray射線說明, 及使用ray拾取物體的方法。

unity ray射線說明, 及使用ray拾取物體的方法。

Ray射線的說明

射線即是從指定位置發射一條射線,檢測與射線碰撞的物體。該方法通常應用在物體拾取,射擊等功能。
ray的主要方法

Ray、RaycastHit 、Raycast

RaycastHit用於儲存射線碰撞到的第一個物件資訊,
Raycast 用於檢測碰撞
RaycastHit[] RaycastAll(Ray ray, float distance, int layerMask) 獲取所有碰撞物體
public static bool Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance);  
ray:射線
hitinfo:這條射線所碰撞物體的資訊,使用out
用於返回 maxDistance:這條射線的最大距離;以射線ray經過的maxDistance長度之內,與第一個物件進行的物理碰撞的資訊儲存在hitInfo中;如果有碰撞物體,返回true, 沒有反false;

Ray從某處向滑鼠位置發射一條射線1。

Ray(Vector3 origin, Vector3 direction)  

if(Input.GetMouseButton(0)){
//          獲取螢幕中點選的點
            Ray myRay=Camera.main.ScreenPointToRay(Input.mousePosition);            
if(Physics.Raycast(myRay,out hitInfo)){ // 如果點選了某個點,就用這個點減去發射者位置,得到新的向量 Vector3 direction =hitInfo.point-player.transform.position; // 從發射物體,發射射線 Ray newray=new Ray(player.transform.position,direction); Debug.DrawLine
(newray.origin,hitInfo.point); print("hit"); //hitInfo.collider.gameObject.tag=="animy" if(hitInfo.transform.CompareTag("animy")){ print("animy"); } } }

Ray從某處向滑鼠位置發射一條射線 2 2017.2版本。

Ray myRay=RectTransformUtility.ScreenPointToRay(Camera.main, Input.mousePosition);

從攝像機 向滑鼠位置發射一條射線。

Ray ray=Camera.main.ScreenPointToRay(Input.mousePosition);

從某物體發射一條向前的射線

在指令碼中輸入Vector3 fwd = transform.TransformDirection(Vector3.forward);
if (Physics.Raycast(transform.position, fwd,out hit,1))
Debug.DrawLine(transform.position,hit.point,Color.red);
其中,Physics.Raycast(transform.position, fwd,out hit,1)為發射射線函式,transform.position為射線原點,fwd為發射方向,1為距離。
如果前方有碰撞體,則發射射線。

拾取物體

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class mainRay : MonoBehaviour {
    private GameObject pickGameObj=null;
            //從攝像機到 滑鼠位置發出射線
    private Ray ray;
         //獲取射線資訊
    private RaycastHit hitInfo;
    // Update is called once per frame
    void Update () {
        ray=Camera.main.ScreenPointToRay(Input.mousePosition);
//      rayDrag("plane","boot");
//      rayPick("plane","boot");
        rayFlow("plane","boot");            
    }
    //點選拾取,再點選釋放
    void rayPick(string planeTag,string targetTag){
        if(pickGameObj==null){
            if(Input.GetMouseButtonDown(0)){            
                if(Physics.Raycast(ray,out hitInfo)){
                    if(hitInfo.collider.gameObject.tag==targetTag){
                        pickGameObj=hitInfo.collider.gameObject;
                    }               
                }
            }
        }else{          
            if(Physics.Raycast(ray,out hitInfo)){
                    if(hitInfo.collider.gameObject.tag==planeTag){
                        pickGameObj.transform.position=hitInfo.point;
                    }               
                }
            if(Input.GetMouseButtonDown(0)){
                pickGameObj=null;
            }
        }       
    }
    //直接跟隨
    void rayFlow(string planeTag,string targetTag){
        GameObject gameObj=GameObject.FindGameObjectWithTag(targetTag);
        if(Physics.Raycast(ray,out hitInfo)){
            GameObject planeGameObj=hitInfo.collider.gameObject;
            if(planeGameObj.tag==planeTag){
                gameObj.transform.position=hitInfo.point;
            }
        }   
    }
    //拖拽
    void rayDrag(string planeTag,string targetTag){
        if(Input.GetMouseButton(0)){
            if(Physics.Raycast(ray,out hitInfo)){
                //輔助檢視射線,只能在scene檢視看到    origin 原點,direction方向,distance長度,layermask層。
                Debug.DrawLine(ray.origin,hitInfo.point);
    //          獲取發生碰撞的物件
                if(hitInfo.collider.gameObject.tag ==targetTag){    
    //              儲存被抓取的物件
                    pickGameObj=hitInfo.collider.gameObject;
                }
            }       
        }
        //如果有拾取的物體,並且滑鼠與地面碰撞,則使物體移動
        if(pickGameObj!=null){
            if(Physics.Raycast(ray,out hitInfo)){
            //與下句相同
            //hitInfo.transform.GompareTag("somemeshTag")
                if(hitInfo.collider.gameObject.tag ==planeTag){ 
                    pickGameObj.transform.position=hitInfo.point;
                }
            }           
        }
        //釋放物體
        if(Input.GetMouseButtonUp(0)){
            pickGameObj=null;
        }
    }
        void shoot(){       
        if(Input.GetMouseButton(0)){
            Ray myRay=Camera.main.ScreenPointToRay(Input.mousePosition);            
            if(Physics.Raycast(myRay,out hitInfo)){     
                Vector3 direction =hitInfo.point-player.transform.position;
                Ray newray=new Ray(player.transform.position,direction);
                Debug.DrawLine(newray.origin,hitInfo.point);            
                print("hit");
                //hitInfo.collider.gameObject.tag=="animy"
                if(hitInfo.transform.CompareTag("animy")){
                    print("animy");
                }       
            }
        }
    }
}

座標轉換

http://www.bubuko.com/infodetail-1292358.html

世界空間中的點座標轉換到螢幕座標:
screenPos = RectTransformUtility.WorldToScreenPoint(cam, worldPos.transform.position);
UGUI物體的座標轉換到螢幕座標:
screenPos = RectTransformUtility.WorldToScreenPoint(canvas.worldCamera, uguiObj.transform.position);
螢幕座標轉換到UGUI座標:
Vector3 worldPoint;
if (RectTransformUtility.ScreenPointToWorldPointInRectangle(rectTrans, camPos, canvas.worldCamera,out worldPoint))
{
  transform.position = worldPoint;
}
螢幕座標轉換到世界空間座標(射線碰撞位置):
var ray = RectTransformUtility.ScreenPointToRay(worldCamera, screenPos);
RaycastHit hitInfo;
if (Physics.Raycast(ray, out hitInfo))
{
  pos.transform.position = hitInfo.point;
}