diff --git a/config/attack_box/box_large.tres b/config/attack_box/box_large.tres new file mode 100644 index 0000000..1063732 --- /dev/null +++ b/config/attack_box/box_large.tres @@ -0,0 +1,10 @@ +[gd_resource type="Resource" script_class="AttackBoxCfg" load_steps=3 format=3 uid="uid://bnfnjdw0tms3h"] + +[ext_resource type="Script" path="res://script/config/attack_box_cfg.gd" id="1_661yg"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_87jhu"] + +[resource] +script = ExtResource("1_661yg") +shape = SubResource("BoxShape3D_87jhu") +offset = Vector2(0.5, 0.5) diff --git a/config/attack_box/box_mid.tres b/config/attack_box/box_mid.tres new file mode 100644 index 0000000..888d60f --- /dev/null +++ b/config/attack_box/box_mid.tres @@ -0,0 +1,11 @@ +[gd_resource type="Resource" script_class="AttackBoxCfg" load_steps=3 format=3 uid="uid://diedb7vw7eyxp"] + +[ext_resource type="Script" path="res://script/config/attack_box_cfg.gd" id="1_hxvsy"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_87jhu"] +size = Vector3(1.6, 1.2, 1.2) + +[resource] +script = ExtResource("1_hxvsy") +shape = SubResource("BoxShape3D_87jhu") +offset = Vector2(0.8, 0.6) diff --git a/config/attack_box/box_normal.tres b/config/attack_box/box_normal.tres index 41dbd7a..1359b03 100644 --- a/config/attack_box/box_normal.tres +++ b/config/attack_box/box_normal.tres @@ -1,10 +1,10 @@ -[gd_resource type="Resource" script_class="AttackBoxCfg" load_steps=2 format=3 uid="uid://bqejjllfy03h3"] +[gd_resource type="Resource" script_class="AttackBoxCfg" load_steps=3 format=3 uid="uid://bqejjllfy03h3"] [ext_resource type="Script" path="res://script/config/attack_box_cfg.gd" id="1_d4mqn"] +[sub_resource type="BoxShape3D" id="BoxShape3D_87jhu"] + [resource] script = ExtResource("1_d4mqn") -height = 1.0 -radius = 0.0 -size = Vector2(1, 1) -offset = Vector2(0.5, 0) +shape = SubResource("BoxShape3D_87jhu") +offset = Vector2(0.5, 0.5) diff --git a/config/attack_box/circle_normal.tres b/config/attack_box/circle_normal.tres index 17d8557..36b4b7b 100644 --- a/config/attack_box/circle_normal.tres +++ b/config/attack_box/circle_normal.tres @@ -1,10 +1,11 @@ -[gd_resource type="Resource" script_class="AttackBoxCfg" load_steps=2 format=3 uid="uid://57sukcw6ewqo"] +[gd_resource type="Resource" script_class="AttackBoxCfg" load_steps=3 format=3 uid="uid://57sukcw6ewqo"] [ext_resource type="Script" path="res://script/config/attack_box_cfg.gd" id="1_8rhve"] +[sub_resource type="CylinderShape3D" id="CylinderShape3D_pmh6g"] +height = 1.0 + [resource] script = ExtResource("1_8rhve") -height = 1.0 -radius = 0.5 -size = Vector2(0, 0) +shape = SubResource("CylinderShape3D_pmh6g") offset = Vector2(0, 0) diff --git a/config/skill_player_weapon/hero01_fist_air_skill01.tres b/config/skill_player_weapon/hero01_fist_air_skill01.tres index 9d62eeb..87b93d9 100644 --- a/config/skill_player_weapon/hero01_fist_air_skill01.tres +++ b/config/skill_player_weapon/hero01_fist_air_skill01.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="SkillPlayerCfg" load_steps=6 format=3 uid="uid://dkxgra6y2u30l"] +[gd_resource type="Resource" script_class="SkillPlayerCfg" load_steps=7 format=3 uid="uid://dkxgra6y2u30l"] [ext_resource type="Resource" uid="uid://dib6g7t6p5ac2" path="res://config/attack/blunt_normal_hit.tres" id="1_nott2"] [ext_resource type="Script" path="res://script/config/player_skill_cfg.gd" id="2_mje6b"] +[ext_resource type="Resource" uid="uid://57sukcw6ewqo" path="res://config/attack_box/circle_normal.tres" id="2_nvq3h"] [ext_resource type="Animation" uid="uid://dxgqn5fa7aokj" path="res://resource/skill_animation/hero01_fist_air_skill01.tres" id="3_q461t"] [ext_resource type="SpriteFrames" uid="uid://cajgs8smbkjan" path="res://resource/animation/character/hero01_fist_skill01.aseprite" id="4_seudu"] [ext_resource type="Resource" uid="uid://c6alg8pmqfdxm" path="res://config/weapon/fist.tres" id="5_70pp4"] @@ -17,6 +18,7 @@ name = "" skill_animation = ExtResource("3_q461t") free_lock = false attack1 = ExtResource("1_nott2") +attack1_box = ExtResource("2_nvq3h") refresh_animation = false sprite_frames = ExtResource("4_seudu") animation_name = "fist_air_skill01" diff --git a/config/skill_player_weapon/hero01_fist_attack01.tres b/config/skill_player_weapon/hero01_fist_attack01.tres index 0e7937c..2a90e72 100644 --- a/config/skill_player_weapon/hero01_fist_attack01.tres +++ b/config/skill_player_weapon/hero01_fist_attack01.tres @@ -1,6 +1,7 @@ -[gd_resource type="Resource" script_class="SkillPlayerCfg" load_steps=6 format=3 uid="uid://7e4fnj5sg72s"] +[gd_resource type="Resource" script_class="SkillPlayerCfg" load_steps=7 format=3 uid="uid://7e4fnj5sg72s"] [ext_resource type="Resource" uid="uid://dib6g7t6p5ac2" path="res://config/attack/blunt_normal_hit.tres" id="1_k0cmy"] +[ext_resource type="Resource" uid="uid://bqejjllfy03h3" path="res://config/attack_box/box_normal.tres" id="2_ixt4v"] [ext_resource type="Script" path="res://script/config/player_skill_cfg.gd" id="2_yc8jq"] [ext_resource type="Animation" uid="uid://t01a4jvp8srr" path="res://resource/skill_animation/hero01_fist_attack01.tres" id="3_b2pdb"] [ext_resource type="SpriteFrames" uid="uid://bhsotj76tuovy" path="res://resource/animation/character/hero01_fist_attack.aseprite" id="4_ymqrn"] @@ -17,6 +18,7 @@ name = "" skill_animation = ExtResource("3_b2pdb") free_lock = false attack1 = ExtResource("1_k0cmy") +attack1_box = ExtResource("2_ixt4v") refresh_animation = false sprite_frames = ExtResource("4_ymqrn") animation_name = "fist_attack01" diff --git a/config/skill_player_weapon/hero01_fist_attack02.tres b/config/skill_player_weapon/hero01_fist_attack02.tres index b228aa0..2c751c9 100644 --- a/config/skill_player_weapon/hero01_fist_attack02.tres +++ b/config/skill_player_weapon/hero01_fist_attack02.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="SkillPlayerCfg" load_steps=6 format=3 uid="uid://dubkvm86cj32f"] +[gd_resource type="Resource" script_class="SkillPlayerCfg" load_steps=7 format=3 uid="uid://dubkvm86cj32f"] [ext_resource type="Resource" uid="uid://c87w2x5qfqdns" path="res://config/attack/blunt_normal_hit_back.tres" id="1_ixy7x"] [ext_resource type="Script" path="res://script/config/player_skill_cfg.gd" id="2_h70wx"] +[ext_resource type="Resource" uid="uid://bqejjllfy03h3" path="res://config/attack_box/box_normal.tres" id="2_saiae"] [ext_resource type="Animation" uid="uid://cyu0yin1rpiak" path="res://resource/skill_animation/hero01_fist_attack02.tres" id="3_tllt1"] [ext_resource type="SpriteFrames" uid="uid://bhsotj76tuovy" path="res://resource/animation/character/hero01_fist_attack.aseprite" id="4_fevaa"] [ext_resource type="Resource" uid="uid://c6alg8pmqfdxm" path="res://config/weapon/fist.tres" id="5_gliie"] @@ -17,6 +18,7 @@ name = "" skill_animation = ExtResource("3_tllt1") free_lock = false attack1 = ExtResource("1_ixy7x") +attack1_box = ExtResource("2_saiae") refresh_animation = false sprite_frames = ExtResource("4_fevaa") animation_name = "fist_attack02" diff --git a/config/skill_player_weapon/hero01_fist_attack03.tres b/config/skill_player_weapon/hero01_fist_attack03.tres index d9cc3a0..58a22bd 100644 --- a/config/skill_player_weapon/hero01_fist_attack03.tres +++ b/config/skill_player_weapon/hero01_fist_attack03.tres @@ -1,7 +1,8 @@ -[gd_resource type="Resource" script_class="SkillPlayerCfg" load_steps=6 format=3 uid="uid://dekpkk8o6o8hk"] +[gd_resource type="Resource" script_class="SkillPlayerCfg" load_steps=7 format=3 uid="uid://dekpkk8o6o8hk"] [ext_resource type="Resource" uid="uid://duu05cr8gk5v4" path="res://config/attack/blunt_mid_hit_blow.tres" id="1_am4eq"] [ext_resource type="Script" path="res://script/config/player_skill_cfg.gd" id="2_fde7v"] +[ext_resource type="Resource" uid="uid://diedb7vw7eyxp" path="res://config/attack_box/box_mid.tres" id="2_ja1d4"] [ext_resource type="Animation" uid="uid://c6mk8tfdpniys" path="res://resource/skill_animation/hero01_fist_attack03.tres" id="3_6rajt"] [ext_resource type="SpriteFrames" uid="uid://bhsotj76tuovy" path="res://resource/animation/character/hero01_fist_attack.aseprite" id="4_orcy6"] [ext_resource type="Resource" uid="uid://c6alg8pmqfdxm" path="res://config/weapon/fist.tres" id="5_r5lmk"] @@ -17,6 +18,7 @@ name = "" skill_animation = ExtResource("3_6rajt") free_lock = false attack1 = ExtResource("1_am4eq") +attack1_box = ExtResource("2_ja1d4") refresh_animation = false sprite_frames = ExtResource("4_orcy6") animation_name = "fist_attack03" diff --git a/config/skill_player_weapon/hero01_fist_attack04.tres b/config/skill_player_weapon/hero01_fist_attack04.tres index e6da5fd..75c4000 100644 --- a/config/skill_player_weapon/hero01_fist_attack04.tres +++ b/config/skill_player_weapon/hero01_fist_attack04.tres @@ -1,6 +1,7 @@ -[gd_resource type="Resource" script_class="SkillPlayerCfg" load_steps=6 format=3 uid="uid://b4aysymwqtvtd"] +[gd_resource type="Resource" script_class="SkillPlayerCfg" load_steps=7 format=3 uid="uid://b4aysymwqtvtd"] [ext_resource type="Resource" uid="uid://duu05cr8gk5v4" path="res://config/attack/blunt_mid_hit_blow.tres" id="1_s12sc"] +[ext_resource type="Resource" uid="uid://diedb7vw7eyxp" path="res://config/attack_box/box_mid.tres" id="2_0lps6"] [ext_resource type="Script" path="res://script/config/player_skill_cfg.gd" id="2_mhuew"] [ext_resource type="Animation" uid="uid://6u3dhxly760l" path="res://resource/skill_animation/hero01_fist_attack04.tres" id="3_bst70"] [ext_resource type="SpriteFrames" uid="uid://bhsotj76tuovy" path="res://resource/animation/character/hero01_fist_attack.aseprite" id="4_hyek5"] @@ -17,6 +18,7 @@ name = "" skill_animation = ExtResource("3_bst70") free_lock = false attack1 = ExtResource("1_s12sc") +attack1_box = ExtResource("2_0lps6") refresh_animation = false sprite_frames = ExtResource("4_hyek5") animation_name = "fist_attack04" diff --git a/config/skill_player_weapon/hero01_fist_attack05.tres b/config/skill_player_weapon/hero01_fist_attack05.tres index 8fdcb20..f6fe186 100644 --- a/config/skill_player_weapon/hero01_fist_attack05.tres +++ b/config/skill_player_weapon/hero01_fist_attack05.tres @@ -1,6 +1,7 @@ -[gd_resource type="Resource" script_class="SkillPlayerCfg" load_steps=6 format=3 uid="uid://0n2jnkdrwa2l"] +[gd_resource type="Resource" script_class="SkillPlayerCfg" load_steps=7 format=3 uid="uid://0n2jnkdrwa2l"] [ext_resource type="Resource" uid="uid://bwe8xlgfhx1gl" path="res://config/attack/blunt_heavy_hit_blow.tres" id="1_5lwhl"] +[ext_resource type="Resource" uid="uid://diedb7vw7eyxp" path="res://config/attack_box/box_mid.tres" id="2_xua7v"] [ext_resource type="Script" path="res://script/config/player_skill_cfg.gd" id="2_ym7q1"] [ext_resource type="Animation" uid="uid://b2xdmgnem1h4g" path="res://resource/skill_animation/hero01_fist_attack05.tres" id="3_dbjmb"] [ext_resource type="SpriteFrames" uid="uid://bhsotj76tuovy" path="res://resource/animation/character/hero01_fist_attack.aseprite" id="4_mhr07"] @@ -17,6 +18,7 @@ name = "" skill_animation = ExtResource("3_dbjmb") free_lock = false attack1 = ExtResource("1_5lwhl") +attack1_box = ExtResource("2_xua7v") refresh_animation = false sprite_frames = ExtResource("4_mhr07") animation_name = "fist_attack05" diff --git a/config/skill_player_weapon/hero01_long_attack01.tres b/config/skill_player_weapon/hero01_long_attack01.tres index 81eb2a3..0980a7e 100644 --- a/config/skill_player_weapon/hero01_long_attack01.tres +++ b/config/skill_player_weapon/hero01_long_attack01.tres @@ -1,8 +1,9 @@ -[gd_resource type="Resource" script_class="SkillPlayerCfg" load_steps=6 format=3 uid="uid://dkr1k00c2eecc"] +[gd_resource type="Resource" script_class="SkillPlayerCfg" load_steps=7 format=3 uid="uid://dkr1k00c2eecc"] -[ext_resource type="Resource" uid="uid://bsqk3q6mccllg" path="res://config/attack/sharp_normal_hit.tres" id="1_6ven2"] +[ext_resource type="Resource" uid="uid://d3mcp8sf6qbmd" path="res://config/attack/sharp_normal_hit.tres" id="1_6ven2"] [ext_resource type="Script" path="res://script/config/player_skill_cfg.gd" id="1_gik08"] [ext_resource type="Animation" uid="uid://daopmieibx3b7" path="res://resource/skill_animation/hero01_long_attack01.tres" id="2_6nbpq"] +[ext_resource type="Resource" uid="uid://bqejjllfy03h3" path="res://config/attack_box/box_normal.tres" id="2_my38a"] [ext_resource type="Resource" uid="uid://cy3wwalxeyro0" path="res://config/weapon/long.tres" id="4_id85o"] [ext_resource type="SpriteFrames" uid="uid://ce83cuqwgwwi4" path="res://resource/animation/character/hero01_long_attack.aseprite" id="5_xel5p"] @@ -17,6 +18,7 @@ name = "" skill_animation = ExtResource("2_6nbpq") free_lock = false attack1 = ExtResource("1_6ven2") +attack1_box = ExtResource("2_my38a") refresh_animation = false sprite_frames = ExtResource("5_xel5p") animation_name = "long_attack01" diff --git a/scene/character/character.tscn b/scene/character/character.tscn index 8dfda5e..dfb1506 100644 --- a/scene/character/character.tscn +++ b/scene/character/character.tscn @@ -13,7 +13,7 @@ [ext_resource type="Script" path="res://script/character/buff.gd" id="9_jlnhy"] [ext_resource type="Script" path="res://script/character/effect.gd" id="12_eyfcd"] -[sub_resource type="BoxShape3D" id="BoxShape3D_ty8lx"] +[sub_resource type="CylinderShape3D" id="CylinderShape3D_qajx7"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_3u7mw"] render_priority = 0 @@ -29,13 +29,12 @@ _data = [Vector2(0, 6), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] point_count = 2 [node name="Character" type="CharacterBody3D"] -collision_layer = 512 +collision_layer = 16 script = ExtResource("1_tonbs") [node name="Collision" type="CollisionShape3D" parent="."] unique_name_in_owner = true -transform = Transform3D(0.4, 0, 0, 0, 0.4, 0, 0, 0, 0.4, 0, 0, 0) -shape = SubResource("BoxShape3D_ty8lx") +shape = SubResource("CylinderShape3D_qajx7") [node name="Status" type="Node3D" parent="."] unique_name_in_owner = true diff --git a/scene/character/player.tscn b/scene/character/player.tscn index d58078a..b379fa2 100644 --- a/scene/character/player.tscn +++ b/scene/character/player.tscn @@ -13,7 +13,7 @@ [node name="View" parent="." index="2"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.693056, 0) sprite_frames = ExtResource("2_7gyv2") -animation = &"long_attack04" +animation = &"long_attack01" [node name="Combo" type="Node3D" parent="." index="8"] unique_name_in_owner = true diff --git a/script/_global/util.gd b/script/_global/util.gd index 41a1993..4e880f2 100644 --- a/script/_global/util.gd +++ b/script/_global/util.gd @@ -4,9 +4,7 @@ extends Node3D func get_resource_name(resource:Resource) -> String:return resource.resource_path.get_file().trim_suffix('.tres') #todo 性能 func snap_vector3(value:Vector3) -> Vector3:return Vector3(snap_float(value.x),snap_float(value.y),snap_float(value.z)) func snap_float(value:float) -> float:return floor(value/Setting.pixel_size) * Setting.pixel_size -func grid_vector3(value:Vector3) -> Vector3:return Vector3(grid_float(value.x),grid_float(value.y),grid_float(value.z)) -func grid_vector2(value:Vector2) -> Vector2:return Vector2(grid_float(value.x),grid_float(value.y)) -func grid_float(value:float) -> float:return Setting.pixel_size * Setting.grid_pixel_size * value +func dir_angle(dir:Vector2) -> float:dir.x = abs(dir.x);return dir.angle_to(Vector2.RIGHT) func vector_reduce(vector:Vector2,reduce:float) -> Vector2: var len = vector.length() @@ -16,45 +14,23 @@ func vector_reduce(vector:Vector2,reduce:float) -> Vector2: var scale_rate = new_len / len return vector * scale_rate -func raycast_wall(from:Vector3,to:Vector3) -> bool: +func raycast_wall(from:Vector3 ,to:Vector3) -> bool: var space_state = get_world_3d().direct_space_state var query = PhysicsRayQueryParameters3D.create(from,to,1) var result = space_state.intersect_ray(query) return result.size()>0 -func attack_detection(pos:Vector3,target_pos:Vector3,target_radius:float,target_height:float,attack_dir:Vector2,attack_height:float,attack_size:Vector2,attack_radius:float) -> bool: - # 检查Y - var attack_y_min = pos.y - var attack_y_max = pos.y + attack_height - var target_y_min = target_pos.y - var target_y_max = target_pos.y + target_height - if attack_y_min > target_y_max || attack_y_max < target_y_min: - return false - # 保底距离 - if pos.distance_to(target_pos) < 0.01: - return true - - # 2d距离 - var dist_2d = Vector2(pos.x,pos.z).distance_to(Vector2(target_pos.x,target_pos.z)) - - # 如果是圆形 - if attack_radius: - return dist_2d <= attack_radius + target_radius - - # 旋转target - var angle = attack_dir.angle_to(Vector2.RIGHT) - target_pos = target_pos - pos - target_pos = target_pos.rotated(Vector3.UP,angle) - - var dist_x = abs(target_pos.x) - attack_size.x - var dist_y = abs(target_pos.z) - attack_size.y - - if dist_x <= target_radius && dist_y <= target_radius: - if (dist_x <= 0 || dist_y <= 0): - return true - var dist_squared = pow(dist_x, 2) + pow(dist_y, 2) - return dist_squared <= pow(target_radius, 2) - return false +func raycast_character(shape:Shape3D ,origin:Vector3 ,dir:Vector2): + var space_state = get_world_3d().direct_space_state + var query = PhysicsShapeQueryParameters3D.new() + var angle = dir_angle(dir) + query.shape = shape + query.transform.origin = origin + query.transform.basis = query.transform.basis.rotated(Vector3.UP, angle) + var result = space_state.intersect_shape(query) + result = result.map(func(v): return v["collider"]) + result = result.filter(func(v): return v is Character) + return result func refresh_animation_lib(): var animation_library_path = "res://resource/skill_animation_library/animation_library.tres" diff --git a/script/character/battle.gd b/script/character/battle.gd index 9d5dcaf..9f19ef4 100644 --- a/script/character/battle.gd +++ b/script/character/battle.gd @@ -23,29 +23,19 @@ func attack2(): var attack_box = status.skill_cfg.get_attack2_box() call_deferred("_attack",attack,attack_box) -func _attack(attack,attack_box): - if !status.skill_cfg: - return - var enemy_list = Global.character_mgr.get_enemy_list(character.id()) +func _attack(attack:AttackCfg,attack_box:AttackBoxCfg): var pos = character.pos() var attack_dir = status.skill_dir.normalized() - var attack_height = attack_box.height - var attack_size = Util.grid_vector2(attack_box.size) - var attack_radius = attack_box.radius - var offset_xz = attack_dir * Util.grid_float(attack_box.offset.x) - pos += Vector3(offset_xz.x,Util.grid_float(attack_box.offset.y),offset_xz.y) + var offset_xz = attack_dir * attack_box.offset.x + var offset_y = attack_box.offset.y + pos += Vector3(offset_xz.x,offset_y,offset_xz.y) + var result = Util.raycast_character(attack_box.shape,pos,attack_dir) var is_stuck = false - for enemy in enemy_list: - var target_pos = enemy.pos() - var target_radius = enemy.radius() - var target_height = enemy.height() - if Util.attack_detection(pos,target_pos,target_radius,target_height,attack_dir,attack_height,attack_size,attack_radius): - var hit_info = HitInfo.new() - hit_info.from = character.id() - hit_info.to = enemy.id() - hit_info.dir = attack_dir - hit_info.attack = attack - is_stuck = is_stuck or settle(hit_info) + for target:Character in result: + if target.team() == character.team(): + continue + target.add_attack(character.id(),attack_dir,attack) + is_stuck = true if !is_stuck and !attack.is_force_pause: skill.on_attack_miss() diff --git a/script/character/character.gd b/script/character/character.gd index 5b9d38f..d531107 100644 --- a/script/character/character.gd +++ b/script/character/character.gd @@ -16,7 +16,7 @@ func init(id:int,cfg:CharacterCfg,team:Enum.ETeam): var half_height = Setting.pixel_size * cfg.sprite_harf_height var height = half_height * 2 var width = Setting.pixel_size * cfg.sprite_width - var body_scale = Vector3(width,height,width) + var body_scale = Vector3(width,half_height,width) collision.position = Vector3(0,half_height,0) collision.scale = body_scale status.basic_offset = Vector3(0,half_height,0) diff --git a/script/character/effect.gd b/script/character/effect.gd index 18cecb9..1350fdc 100644 --- a/script/character/effect.gd +++ b/script/character/effect.gd @@ -86,9 +86,7 @@ func _cast_particle(resource:Resource ,is_attach:bool): return var new_particle = resource.instantiate() as Particle new_particle.name = "particle" - var dir = status.skill_dir as Vector2 - dir.x = abs(dir.x) - var angle = dir.angle_to(Vector2.RIGHT) + var angle = Util.dir_angle(status.skill_dir) new_particle.rotation.y = angle if is_right else -angle new_particle.scale.x = abs(new_particle.scale.x) * (1 if is_right else -1) new_particle.position = status.basic_offset diff --git a/script/config/attack_box_cfg.gd b/script/config/attack_box_cfg.gd index 2b45f91..aaf51b4 100644 --- a/script/config/attack_box_cfg.gd +++ b/script/config/attack_box_cfg.gd @@ -2,7 +2,5 @@ extends Resource class_name AttackBoxCfg -@export var height : float = 1 #判定框高度 -@export var radius : float #圆形判定框 半径 -@export var size : Vector2 #矩形判定框 大小 +@export var shape : Shape3D @export var offset : Vector2 #偏移