You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Godot 4.4中Raycast3D无法检测玩家问题求助

问题描述

我正在用节点状态机制作敌方NPC AI,计划通过RayCast3D实现玩家检测功能。预期当NPC与玩家碰撞时,AIIdleState脚本会打印"Player detected",但实际碰撞时没有输出该字符串,AI也未检测到玩家。

提供的AIIdleState代码如下:

extends State

class_name AIIdleState

var stateName : String = "AIIdle"

var cR : EnemyTest
var wander_time : float = 0.0
var player_detected : bool = false

@onready var raycast: RayCast3D = $"../../RayCast3D"
@export var target: Vector3

func wander():
    #generate a random point around the character within a certain radius
    var random_direction = Vector3(randf_range(-1, 1), 0, randf_range(-1, 1)).normalized()
    target = random_direction
    wander_time = randf_range(2.0, 5.0) #wander for a random time between 2 and 5 seconds

    print("wandered to : ", target)

func enter(char_Ref : CharacterBody3D):
    print("idle")
    cR = char_Ref
    if raycast and cR:
        raycast.add_exception(cR)

func update(delta : float):
    if wander_time <= 0.0:
        wander()
    else:
        wander_time -= delta

func physics_update(delta: float):
    if cR:
        #move towards the target
        cR.velocity = lerp(cR.velocity, target * cR.speed, 0.1)
        #rotate towards the target
        cR.rotation.y = lerp(cR.rotation.y, atan2(target.x, target.z), 0.05)
        
    playerDetection()
    
    transition()

func transition():
    if player_detected == true:
        transitioned.emit(self, "AICombat")

func playerDetection():
    if raycast.is_colliding():
        if raycast.get_collider().is_in_group("Player"):
            print("Player detected")
            player_detected = true

节点树结构:

  • EnemyTest(CharacterBody3D,根节点)
    • StateMachine
      • AIStates
        • AIIdleState(挂载上述脚本)
    • RayCast3D
问题分析与修复方案

以下是可能导致检测失效的原因及对应的修复方法:

1. RayCast3D路径引用错误

代码中使用$"../../RayCast3D"的相对路径引用RayCast3D,若实际节点层级与该路径不匹配,会导致raycast变量为空,无法执行检测逻辑。

修复:
通过字符引用直接获取RayCast3D,修改enter方法:

func enter(char_Ref : CharacterBody3D):
    print("idle")
    cR = char_Ref
    raycast = cR.get_node("RayCast3D")
    if raycast and cR:
        raycast.add_exception(cR)

也可以在编辑器中将RayCast3D节点直接拖到脚本的raycast变量上,避免路径错误。

2. RayCast3D检测方向与范围未配置

RayCast3D默认检测方向为-Z轴,若NPC朝向与该方向不一致,或检测长度过短,会无法触碰到玩家。

修复:

  • 在编辑器中选中RayCast3D,调整Target Position的Z值(如设为Vector3(0,0,5)),增加检测范围。
  • 在physics_update中同步RayCast3D的朝向,使其跟随NPC旋转:
func physics_update(delta: float):
    if cR:
        # 原有移动和旋转代码
        cR.velocity = lerp(cR.velocity, target * cR.speed, 0.1)
        cR.rotation.y = lerp(cR.rotation.y, atan2(target.x, target.z), 0.05)
        # 更新RayCast3D朝向
        raycast.global_basis = cR.global_basis
    playerDetection()
    transition()

3. 未强制更新RayCast3D检测状态

RayCast3D默认不会自动刷新检测结果,当NPC或玩家移动时,检测结果可能滞后。

修复:
在playerDetection方法开头添加强制更新:

func playerDetection():
    raycast.force_raycast_update()
    if raycast.is_colliding():
        if raycast.get_collider().is_in_group("Player"):
            print("Player detected")
            player_detected = true

4. 玩家节点未加入"Player"组

若玩家节点未添加到"Player"组,is_in_group("Player")会返回false,无法触发检测提示。

修复:
选中玩家节点,在编辑器右侧Groups面板中添加"Player"组。

5. RayCast3D碰撞掩码未匹配玩家层

RayCast3D的Collision Mask若未勾选玩家所在的碰撞层,会忽略玩家的碰撞。

修复:
在编辑器中选中RayCast3D,检查Collision Mask设置,确保勾选玩家节点对应的碰撞层。

6. 未重置player_detected状态

一旦检测到玩家后,player_detected会保持true,即使玩家离开检测范围,AI也不会重新检测。

修复:
修改playerDetection方法,添加未检测到玩家时的重置逻辑:

func playerDetection():
    raycast.force_raycast_update()
    if raycast.is_colliding() and raycast.get_collider().is_in_group("Player"):
        print("Player detected")
        player_detected = true
    else:
        player_detected = false

内容的提问来源于stack exchange,提问作者Muhammad Afzal Faizi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.03 05:03:10