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

Godot 4.2.1中RayCast3D检测玩家触发空实例错误求助

解决Godot敌人AI中"Attempt to call function 'is_in_group' in base 'null instance'"错误

错误原因

错误核心是调用顺序逻辑错误:代码中先尝试对射线检测结果调用is_in_group,再判断检测结果是否为null。当射线未命中任何物体时,get_collider()返回null,此时调用is_in_group就会触发空实例调用错误。

修复步骤

1. 修正碰撞体判断顺序

将空值判断放在is_in_group调用之前,确保仅当碰撞体存在时才执行分组校验:

# 原错误代码
if view_ray.get_collider().is_in_group("Player") and view_ray.get_collider() != null:
    player_found = true

# 修正后代码
if view_ray.get_collider() != null and view_ray.get_collider().is_in_group("Player"):
    player_found = true

2. 增加Player节点的空值防护

避免因路径配置错误导致player变量为空,在初始化和使用时增加校验:

func _ready():
    if player_path != null:
        player = get_node_or_null(player_path)
        if player == null:
            print("警告:无法找到Player节点,请检查player_path是否正确")

# 在追击逻辑中增加player非空判断
if player_found == true and player != null:
    nav_agent.set_target_position(player.global_transform.origin)
    var next_nav_point = nav_agent.get_next_path_position()
    velocity = (next_nav_point - global_transform.origin).normalized() * SPEED

    look_at(Vector3(player.global_position.x, global_position.y, player.global_position.z), Vector3.UP)

3. 优化射线检测逻辑

合并重复判断,统一更新player_found状态的逻辑,避免代码冗余:

func _process(delta):
    velocity = Vector3.ZERO

    # 先更新玩家检测状态
    var collider = view_ray.get_collider()
    player_found = collider != null and collider.is_in_group("Player")

    # 再执行追击逻辑
    if player_found and player != null:
        nav_agent.set_target_position(player.global_transform.origin)
        var next_nav_point = nav_agent.get_next_path_position()
        velocity = (next_nav_point - global_transform.origin).normalized() * SPEED

        look_at(Vector3(player.global_position.x, global_position.y, player.global_position.z), Vector3.UP)

    move_and_slide()

4. 检查RayCast3D节点配置

确保场景中的RayCast3D已开启Enabled属性,并且调整射线的方向、长度参数,保证能覆盖玩家可能出现的范围。

完整修正代码

extends CharacterBody3D

var player = null
var health = 100

const SPEED = 4.0
const ATTACK_RANGE = 2.0

@export var player_path : NodePath
@onready var nav_agent = $NavigationAgent3D
@onready var view_ray = $MeshInstance3D/RayCast3D

var player_found = false

# Called when the node enters the scene tree for the first time.
func _ready():
    if player_path != null:
        player = get_node_or_null(player_path)
        if player == null:
            print("警告:无法找到Player节点,请检查player_path是否正确")

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
    velocity = Vector3.ZERO

    # 更新玩家检测状态
    var collider = view_ray.get_collider()
    player_found = collider != null and collider.is_in_group("Player")

    # 追击逻辑
    if player_found and player != null:
        nav_agent.set_target_position(player.global_transform.origin)
        var next_nav_point = nav_agent.get_next_path_position()
        velocity = (next_nav_point - global_transform.origin).normalized() * SPEED

        look_at(Vector3(player.global_position.x, global_position.y, player.global_position.z), Vector3.UP)

    move_and_slide()


func _target_in_range():
    return player != null and global_position.distance_to(player.global_position) < ATTACK_RANGE


func _hit_finished():
    if player != null and global_position.distance_to(player.global_position) < ATTACK_RANGE + 1.0:
        var dir = global_position.direction_to(player.global_position)
        player.hit(dir)

func hit():
    health -= 33
    if health <= 0:
        queue_free()

内容的提问来源于stack exchange,提问作者RED91

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 02:53:11