淺析射線檢測 raycast 的使用 !Cocos Creator 3D !

哎呀?爲何我設置了節點點擊回調沒反應呀?

記得在寫小雞拍拍的時候遇到一個問題,想要捕捉排球的點擊事件,按照 2d 的寫法,給3d 節點添加 node 事件,結果點了沒反應。代碼大概是如下的樣子。html

this.node_volleyball.on(Node.EventType.TOUCH_START, () => {
    console.log('不可能看見我')
}, this);

後來在論壇上找了個方法,稀裏糊塗的寫上去就完事了。node

可是,最近我把版本升級到 v1.0.1 以後,發現以前的方法無論用了。還好,在最新官方文檔找到了解決方案。那 就 是 —— 射線檢測git

什麼是射線檢測呢?上網查了一下,射線檢測是這樣子的。github

這好像不是我想要的東西。因而,我就腦補了一下射線檢測是怎麼個邏輯。canvas

首先,咱們看到的視角是這樣子的。假設咱們點擊其中屏幕中的一個位置(圖中的紅點點)。ide

由於這個視角是攝像機提供的,咱們就把這個點點和攝像機組合一條射線。學習

接着,檢查這條射線穿過了那些物體,這些物體中可能就有咱們點擊的對象。ui

也能夠這麼理解,你用眼睛看着一塊區域,伸出手指。你能夠看到手指頭擋住了一點視線,從你的視線作通過手指這個點畫一條射線,這個射線穿過的物體,就恰好是你想要點擊的物體。this

05-06.png

講了大概原理(?),一塊兒看看如何使用吧。spa

既然是射線檢測,固然要先建立一個射線。

private _ray: geometry.ray = new geometry.ray();

觸摸檢測的就用全局系統事件。

systemEvent.on(SystemEventType.TOUCH_START, this.onTouchStart, this);
//onTouchStart(touch: Touch, event: EventTouch)

開始畫射線,就要用到攝像機嘛!記得上面說的是由點擊的點和攝像機決定這條射線的吧。

this.camera_3d.screenPointToRay(touch._point.x, touch._point.y, this._ray);

接下來就是檢測這條線穿過了哪些物體啦。

creator 3d 提供了三種檢測方案,能夠一塊兒看看是如何使用的。

基於物理碰撞器的射線檢測:

咱們先給須要檢測的物體添加碰撞器。

在代碼中調用物理碰撞器檢測方法就能夠啦。

//基於物理碰撞器的射線檢測
if (PhysicsSystem.instance.raycast(this._ray)) {
    const r = PhysicsSystem.instance.raycastResults;
    for (let i = 0; i < r.length; i++) {
        const item = r[i];
        if (item.collider.node.uuid == this.node_volleyball.uuid) {
            this.label_info.string = '點了排球'
        }
    }
}

基於模型的射線檢測:

大體與物理模型檢測相同,使用的是模型組件。

檢測代碼以下。

//基於模型的射線檢測
const rs = director.getScene().renderScene;
if (rs.raycastSingleModel(this._ray, this.model_basketball.model)) {
    const r = rs.rayResultSingleModel;
    for (let i = 0; i < r.length; i++) {
        const item = r[i];
        if (item.node.uuid == this.model_basketball.node.uuid) {
            this.label_info.string = '點了籃球'
        }
    }
}

基於 UITransform 組件的射線檢測:

由於 canvas 有本身的相機實體,咱們須要切換攝像機,代碼以下。

//基於 UITransform 組件的射線檢測
const uiCamera = this.canvas_2d.camera;
uiCamera.screenPointToRay(this._ray, touch._point.x, touch._point.y);
if (rs.raycastAllCanvas(this._ray)) {
    const result = rs.rayResultCanvas;
    for (let i = result.length; i--;) {
        const item = result[i];
        if (item.node.uuid == this.label_info.node.uuid) {
            this.label_info.string = '點了文字';
        }
    }
}

一塊兒看看最後的效果吧!


官方文檔寫的很詳細了,這裏只是稍作整理,若有錯誤,歡迎指出!但願對正在學習 Cocos Creator 3D 的朋友有點幫助。


完整代碼
原文連接

相關文章
相關標籤/搜索