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
相关产品推荐
相关产品推荐

