Commit 828df038 authored by Gavin An's avatar Gavin An

연습용 유닛들 제거

parent 231d5a4f
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://ym45af2xwegi"
path="res://.godot/imported/guardian.fbx-84eb2d0d9d2314572eefd0a31b702465.scn"
[deps]
source_file="res://assets/models/units/guardian/guardian.fbx"
dest_files=["res://.godot/imported/guardian.fbx-84eb2d0d9d2314572eefd0a31b702465.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
mesh_library/use_node_names_as_mesh_names=false
array_mesh/deduplicate_surfaces=true
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=true
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
fbx/importer=0
fbx/allow_geometry_helper_nodes=false
fbx/embedded_image_handling=1
fbx/naming_version=2
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cwwchk1itkduy"
path.s3tc="res://.godot/imported/guardian_0.png-465517cd610787ece6553a0f096c207b.s3tc.ctex"
path.etc2="res://.godot/imported/guardian_0.png-465517cd610787ece6553a0f096c207b.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
generator_parameters={
"md5": "8c2ce66c925a00fc68c57af0b1583baf"
}
[deps]
source_file="res://assets/models/units/guardian/guardian_0.png"
dest_files=["res://.godot/imported/guardian_0.png-465517cd610787ece6553a0f096c207b.s3tc.ctex", "res://.godot/imported/guardian_0.png-465517cd610787ece6553a0f096c207b.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/high_quality_mode=0
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0
This source diff could not be displayed because it is too large. You can view the blob instead.
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://ddqbm4y6brray"
path="res://.godot/imported/striker.fbx-49fd3adbc524a538ae9adeae2695cd2a.scn"
[deps]
source_file="res://assets/models/units/striker/striker.fbx"
dest_files=["res://.godot/imported/striker.fbx-49fd3adbc524a538ae9adeae2695cd2a.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
mesh_library/use_node_names_as_mesh_names=false
array_mesh/deduplicate_surfaces=true
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=true
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
fbx/importer=0
fbx/allow_geometry_helper_nodes=false
fbx/embedded_image_handling=1
fbx/naming_version=2
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ccilxf3k1hhpb"
path.s3tc="res://.godot/imported/striker_0.png-659efdfa4934f050dc55ce39840ff050.s3tc.ctex"
path.etc2="res://.godot/imported/striker_0.png-659efdfa4934f050dc55ce39840ff050.etc2.ctex"
metadata={
"imported_formats": ["s3tc_bptc", "etc2_astc"],
"vram_texture": true
}
generator_parameters={
"md5": "4bf449ff8612570375bc5092fac3ec8b"
}
[deps]
source_file="res://assets/models/units/striker/striker_0.png"
dest_files=["res://.godot/imported/striker_0.png-659efdfa4934f050dc55ce39840ff050.s3tc.ctex", "res://.godot/imported/striker_0.png-659efdfa4934f050dc55ce39840ff050.etc2.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/high_quality_mode=0
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -12,8 +12,7 @@ res://src/sandbox/ ...@@ -12,8 +12,7 @@ res://src/sandbox/
├── fit_sandbox.gd # Transform 코드를 에디터에서 자동 추출해주는 헬퍼 스크립트 ├── fit_sandbox.gd # Transform 코드를 에디터에서 자동 추출해주는 헬퍼 스크립트
├── SANDBOX_GUIDE.md # 본 사용 설명서 ├── SANDBOX_GUIDE.md # 본 사용 설명서
├── units/ ├── units/
│ ├── striker_fit_test.tscn # Striker 유닛 조율용 복사본 씬 │ ├── warrior_fit_test.tscn # WarriorLv1 유닛 조율용 복사본 씬
│ └── guardian_fit_test.tscn # Guardian 유닛 조율용 복사본 씬
└── monsters/ └── monsters/
└── monster_fit_test.tscn # Monster 조율용 복사본 씬 └── monster_fit_test.tscn # Monster 조율용 복사본 씬
``` ```
......
...@@ -16,31 +16,7 @@ func _ready() -> void: ...@@ -16,31 +16,7 @@ func _ready() -> void:
## 5종의 유닛 능력치 데이터 초기 셋업 ## 5종의 유닛 능력치 데이터 초기 셋업
func _initialize_unit_templates() -> void: func _initialize_unit_templates() -> void:
# 1. Striker (연사형 근접 유닛) # 1. Ranger (원거리 유닛)
var striker: UnitData = UnitData.new()
striker.unit_id = "Unit_Striker"
striker.unit_name = "Striker"
striker.damage = 12.0
striker.cooldown = 1.5
striker.move_speed = 6.0
striker.attack_range = 2.0
striker.is_ranged = false
striker.unit_color = Color(0.12, 0.45, 0.85, 1.0) # 청색
unit_templates.append(striker)
# 2. Guardian (밸런스형 근접 유닛)
var guardian: UnitData = UnitData.new()
guardian.unit_id = "Unit_Guardian"
guardian.unit_name = "Guardian"
guardian.damage = 25.0
guardian.cooldown = 1.0
guardian.move_speed = 4.0
guardian.attack_range = 2.0
guardian.is_ranged = false
guardian.unit_color = Color(0.85, 0.65, 0.12, 1.0) # 황금색
unit_templates.append(guardian)
# 3. Ranger (원거리 유닛)
var ranger: UnitData = UnitData.new() var ranger: UnitData = UnitData.new()
ranger.unit_id = "Unit_Ranger" ranger.unit_id = "Unit_Ranger"
ranger.unit_name = "Ranger" ranger.unit_name = "Ranger"
...@@ -52,7 +28,7 @@ func _initialize_unit_templates() -> void: ...@@ -52,7 +28,7 @@ func _initialize_unit_templates() -> void:
ranger.unit_color = Color(0.12, 0.75, 0.25, 1.0) # 녹색 ranger.unit_color = Color(0.12, 0.75, 0.25, 1.0) # 녹색
unit_templates.append(ranger) unit_templates.append(ranger)
# 4. Mage (마법사 유닛) # 2. Mage (마법사 유닛)
var mage: UnitData = UnitData.new() var mage: UnitData = UnitData.new()
mage.unit_id = "Unit_Mage" mage.unit_id = "Unit_Mage"
mage.unit_name = "Mage" mage.unit_name = "Mage"
...@@ -64,7 +40,7 @@ func _initialize_unit_templates() -> void: ...@@ -64,7 +40,7 @@ func _initialize_unit_templates() -> void:
mage.unit_color = Color(0.9, 0.25, 0.15, 1.0) mage.unit_color = Color(0.9, 0.25, 0.15, 1.0)
unit_templates.append(mage) unit_templates.append(mage)
# 5. Warrior Lv1 (근접 밸런스 유닛) # 3. Warrior Lv1 (근접 밸런스 유닛)
var warrior_lv1: UnitData = UnitData.new() var warrior_lv1: UnitData = UnitData.new()
warrior_lv1.unit_id = "Unit_Warrior_Lv1" warrior_lv1.unit_id = "Unit_Warrior_Lv1"
warrior_lv1.unit_name = "Warrior Lv1" warrior_lv1.unit_name = "Warrior Lv1"
......
...@@ -5,10 +5,10 @@ extends Resource ...@@ -5,10 +5,10 @@ extends Resource
## - Godot의 Resource 클래스를 상속받아 유닛 데이터 템플릿을 생성 및 직렬화하기에 용이합니다. ## - Godot의 Resource 클래스를 상속받아 유닛 데이터 템플릿을 생성 및 직렬화하기에 용이합니다.
## - DataManager에서 각 유닛의 기본 능력치를 정의하고 생성할 때 템플릿 데이터로 활용됩니다. ## - DataManager에서 각 유닛의 기본 능력치를 정의하고 생성할 때 템플릿 데이터로 활용됩니다.
## 유닛 고유 식별자 ID (예: "Unit_Striker", "Unit_Mage") ## 유닛 고유 식별자 ID (예: "Unit_Warrior_Lv1", "Unit_Mage")
@export var unit_id: String = "" @export var unit_id: String = ""
## UI 및 로그에 출력할 유닛 이름 (예: "Striker", "Mage") ## UI 및 로그에 출력할 유닛 이름 (예: "Warrior", "Mage")
@export var unit_name: String = "" @export var unit_name: String = ""
## 유닛의 기본 공격력 (적에게 가하는 데미지 수치) ## 유닛의 기본 공격력 (적에게 가하는 데미지 수치)
......
[gd_scene format=3 uid="uid://dh00osxx32ll"]
[ext_resource type="PackedScene" uid="uid://ym45af2xwegi" path="res://assets/models/units/guardian/guardian.fbx" id="1_avjtn"]
[ext_resource type="AnimationLibrary" uid="uid://wdrqljuuoobi" path="res://assets/models/units/guardian/guardian_animations.tres" id="2_brs6e"]
[node name="guardian" unique_id=1303946976 instance=ExtResource("1_avjtn")]
transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 0, 0, 0)
[node name="Skeleton3D" parent="Armature" parent_id_path=PackedInt32Array(1897227020) index="0" unique_id=693633454]
bones/0/rotation = Quaternion(0.16135524, 0.017289262, 0.8635694, -0.47740287)
bones/1/rotation = Quaternion(-0.11989136, -0.7847894, 0.48965573, 0.360512)
bones/2/rotation = Quaternion(0.30723146, 0.028167723, 0.019137163, 0.95102537)
bones/3/rotation = Quaternion(-0.48467338, -0.009461789, 0.084976375, 0.8705062)
bones/4/rotation = Quaternion(-0.44517812, -0.036251303, 0.0022491806, 0.8947051)
bones/5/rotation = Quaternion(-0.55861735, -0.34589392, 0.52776814, 0.53829813)
bones/6/rotation = Quaternion(0.24396187, -0.052610878, -0.041842297, 0.96745235)
bones/7/rotation = Quaternion(-0.51089776, 0.016207077, -0.10428674, 0.8531384)
bones/8/rotation = Quaternion(-0.46007094, 0.05177691, -0.0002939275, 0.8863712)
bones/9/rotation = Quaternion(0.51449835, 0.55558264, 0.55473185, 0.34480736)
bones/10/rotation = Quaternion(-0.010586703, 0.039760113, 0.028165929, 0.9987561)
bones/11/rotation = Quaternion(-0.044285484, -0.0022858628, 0.0065958304, 0.9989946)
bones/12/rotation = Quaternion(0.4713875, 0.61777264, -0.43904644, 0.45098686)
bones/13/rotation = Quaternion(0.515525, 0.4640335, 0.11964494, 0.71034634)
bones/14/rotation = Quaternion(-0.12525696, -0.120365754, 0.08248928, 0.98133504)
bones/15/rotation = Quaternion(-0.0055409265, -0.027728662, 0.026517618, 0.99924845)
bones/16/rotation = Quaternion(-0.47947365, 0.60535425, -0.38794234, -0.5031422)
bones/17/rotation = Quaternion(0.5574216, -0.17528728, -0.09270607, 0.80620176)
bones/18/rotation = Quaternion(-0.20086025, 0.21941167, -0.43810183, 0.84828097)
bones/19/rotation = Quaternion(0.042692166, -0.32304475, 0.07524356, 0.9424214)
bones/20/rotation = Quaternion(0.050158884, 0.06416708, 0.02680122, 0.9963174)
bones/21/rotation = Quaternion(0.38534346, 0.030087095, -0.03150925, 0.9217442)
bones/22/rotation = Quaternion(-0.16659413, -3.229459e-09, 0.002792912, 0.98602164)
bones/23/rotation = Quaternion(0.5757769, -4.7371287e-08, -0.0096528055, 0.81755)
[node name="AnimationPlayer" parent="." index="1" unique_id=1985491758]
libraries/ = ExtResource("2_brs6e")
class_name GuardianUnit
extends BaseUnit
## Guardian 유닛 고유 동작 및 비주얼 제어 클래스
const GUARDIAN_ATTACK_ANIM: String = "Slash"
const GUARDIAN_RUN_ANIM: String = "Running"
const GUARDIAN_WALK_ANIM: String = "Walking"
const GUARDIAN_IDLE_ANIM: String = "Idle"
func _setup_unit_visuals() -> void:
# 자식 노드 중 가디언 모델 노드 명시적 확보
var m_name: String = "guardian"
var node: Node3D = get_node_or_null(m_name) as Node3D
if not node:
push_error("GuardianUnit: Model node '" + m_name + "' not found under children.")
return
_model_instance = node
# 가디언 스킨 및 무기 결합
UnitHelper.apply_skin(_model_instance, "res://assets/models/units/guardian/guardian_0.png")
attach_weapon(_model_instance)
# 애니메이션 플레이어 및 라이브러리 연동
_model_anim_player = UnitHelper.find_animation_player(_model_instance)
if _model_anim_player:
var anim_lib_path: String = "res://assets/models/units/" + m_name + "/" + m_name + "_animations.tres"
if ResourceLoader.exists(anim_lib_path):
var lib: AnimationLibrary = load(anim_lib_path) as AnimationLibrary
if lib:
if _model_anim_player.has_animation_library(""):
_model_anim_player.remove_animation_library("")
if not _model_anim_player.has_animation_library(m_name):
_model_anim_player.add_animation_library(m_name, lib)
UnitHelper.clean_root_animation_tracks(_model_anim_player)
func _get_attack_animation_name(_model_name: String) -> String:
return _model_name + "/" + GUARDIAN_ATTACK_ANIM
func _get_weapon_config() -> Dictionary:
return {
"bone_name": "RightHand",
"attachment_name": "RightHandAttachment",
"weapon_scene_path": "res://assets/models/items/weapons/azure_spear/azure_spear.glb",
"texture_path": "res://assets/models/items/weapons/azure_spear/azure_spear_0.png"
}
## 가디언 애니메이션 갱신 제어
func _update_animations() -> void:
if not _model_anim_player:
return
var m_name: String = "guardian"
var library_prefix: String = m_name + "/"
var has_custom_anims: bool = _model_anim_player.has_animation(library_prefix + "Idle")
var target_anim: String = ""
var play_speed: float = 1.0
var blend_time: float = 0.2
if has_custom_anims:
var attack_anim: String = library_prefix + "Slash"
var run_anim: String = library_prefix + "Running"
var idle_anim: String = library_prefix + "Idle"
if _attack_lock_timer > 0.0:
var base_speed: float = 1.5
if unit_data.cooldown < 0.6:
base_speed = 0.6 / unit_data.cooldown
play_speed = clampf(base_speed, 1.0, 3.0)
target_anim = attack_anim
elif velocity.length() > 0.1:
target_anim = run_anim
play_speed = 1.2
else:
target_anim = idle_anim
play_speed = 1.0
if target_anim != "" and _model_anim_player.current_animation != target_anim:
_last_anim_state = target_anim.replace(library_prefix, "")
_model_anim_player.play(target_anim, blend_time, play_speed)
else:
# Fallback 처리
var fallback_anim: String = "Armature|Armature|Basic_Jump|baselayer"
if not _model_anim_player.has_animation(fallback_anim):
return
if _attack_lock_timer > 0.0:
target_anim = fallback_anim
play_speed = 2.5
elif velocity.length() > 0.1:
target_anim = fallback_anim
play_speed = 1.5
else:
target_anim = ""
_model_anim_player.stop()
if target_anim != "" and _model_anim_player.current_animation != target_anim:
_model_anim_player.play(target_anim, blend_time, play_speed)
[gd_scene format=3 uid="uid://cx4vbc5m3myqk"]
[ext_resource type="Script" uid="uid://b4ott7c4tx82j" path="res://src/entities/units/guardian/guardian_unit.gd" id="1_base_unit"]
[ext_resource type="PackedScene" uid="uid://dh00osxx32ll" path="res://src/entities/units/guardian/guardian.tscn" id="2_y84tp"]
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_body"]
radius = 0.4
height = 1.2
[sub_resource type="CapsuleMesh" id="CapsuleMesh_unit"]
radius = 0.4
height = 1.2
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ring"]
albedo_color = Color(0.098039, 0.901961, 0.098039, 1)
emission_enabled = true
emission = Color(0.098039, 0.901961, 0.098039, 1)
emission_energy_multiplier = 2.0
[sub_resource type="TorusMesh" id="TorusMesh_selection"]
material = SubResource("StandardMaterial3D_ring")
inner_radius = 0.65
outer_radius = 0.7
[node name="GuardianUnit" type="CharacterBody3D" unique_id=2140150158]
script = ExtResource("1_base_unit")
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=1623768716]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.6, 0)
shape = SubResource("CapsuleShape3D_body")
[node name="VisualMesh" type="MeshInstance3D" parent="." unique_id=506359796]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.6, 0)
visible = false
mesh = SubResource("CapsuleMesh_unit")
[node name="SelectionRing" type="MeshInstance3D" parent="." unique_id=1020833698]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.02, 0)
mesh = SubResource("TorusMesh_selection")
[node name="NavigationAgent3D" type="NavigationAgent3D" parent="." unique_id=1893995123]
[node name="guardian" parent="." unique_id=1303946976 instance=ExtResource("2_y84tp")]
[editable path="guardian"]
[gd_scene format=3 uid="uid://c2aiejcidlihv"]
[ext_resource type="PackedScene" uid="uid://ddqbm4y6brray" path="res://assets/models/units/striker/striker.fbx" id="1_o8xnq"]
[ext_resource type="AnimationLibrary" uid="uid://08h0jdofeqjh" path="res://assets/models/units/striker/striker_animations.tres" id="2_3y3ie"]
[node name="striker" unique_id=1533136548 instance=ExtResource("1_o8xnq")]
transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 0, 0, 0)
[node name="Skeleton3D" parent="Armature" parent_id_path=PackedInt32Array(141876740) index="0" unique_id=700524040]
bones/0/position = Vector3(-0.07593487, -0.11580749, 1.0055236)
bones/0/rotation = Quaternion(0.10636933, -0.010761774, 0.9278658, -0.35726014)
bones/1/rotation = Quaternion(-0.3992232, -0.76478696, 0.32690945, 0.38581344)
bones/2/rotation = Quaternion(0.4915073, 0.17696312, 0.014548965, 0.8525802)
bones/3/rotation = Quaternion(-0.6221705, 0.14250483, 0.18804844, 0.7464811)
bones/4/rotation = Quaternion(-0.3181853, 0.089018926, 0.04370703, 0.94282734)
bones/5/rotation = Quaternion(-0.6471634, -0.33475423, 0.50315934, 0.46470422)
bones/6/rotation = Quaternion(0.47004598, -0.025201898, 0.0033712722, 0.88227564)
bones/7/rotation = Quaternion(-0.7216642, -0.08517742, -0.24045335, 0.64352757)
bones/8/rotation = Quaternion(-0.31206164, -0.091231756, -0.011618443, 0.94560003)
bones/9/rotation = Quaternion(0.507673, 0.55611384, 0.518061, 0.40573192)
bones/10/rotation = Quaternion(0.09781179, 0.08439563, -0.011313036, 0.9915556)
bones/11/rotation = Quaternion(0.052174386, 0.08322716, 0.0014392042, 0.9951628)
bones/12/rotation = Quaternion(0.5576085, 0.5272101, -0.49115944, 0.4121708)
bones/13/rotation = Quaternion(0.45507017, 0.34419686, 0.3153991, 0.7582632)
bones/14/rotation = Quaternion(-0.48338068, -0.008683227, 0.21203578, 0.84929883)
bones/15/rotation = Quaternion(-0.0067131408, 0.25461575, 0.03839887, 0.9662563)
bones/16/rotation = Quaternion(-0.6152923, 0.47222814, -0.46918163, -0.42223755)
bones/17/rotation = Quaternion(0.54883194, -0.3734153, -0.1059764, 0.7403469)
bones/18/rotation = Quaternion(-0.43201977, 0.12073633, -0.20203601, 0.8706107)
bones/19/rotation = Quaternion(0.0029188972, -0.11325944, -0.31018323, 0.94390154)
bones/20/rotation = Quaternion(0.0021174871, -0.013983027, 0.0034143268, 0.9998942)
bones/21/rotation = Quaternion(0.2352985, 0.1686747, -0.052965716, 0.95570815)
bones/22/rotation = Quaternion(-0.279603, 0.0036110622, 0.00633247, 0.9600881)
bones/23/rotation = Quaternion(0.5067053, 5.5902456e-09, -0.0042108293, 0.8621091)
[node name="AnimationPlayer" parent="." index="1" unique_id=1656754057]
libraries/ = ExtResource("2_3y3ie")
class_name StrikerUnit
extends BaseUnit
## Striker 유닛 고유 동작 및 비주얼 제어 클래스
const STRIKER_ATTACK_ANIM: String = "Slash"
const STRIKER_RUN_ANIM: String = "Running"
const STRIKER_WALK_ANIM: String = "Walking"
const STRIKER_IDLE_ANIM: String = "Idle"
func _setup_unit_visuals() -> void:
# 자식 노드 중 스트라이커 모델 노드 명시적 확보
var m_name: String = "striker"
var node: Node3D = get_node_or_null(m_name) as Node3D
if not node:
push_error("StrikerUnit: Model node '" + m_name + "' not found under children.")
return
_model_instance = node
# 스트라이커 스킨 및 무기 결합 (원래 striker 스킨 경로는 units/striker_0.png 이었음)
UnitHelper.apply_skin(_model_instance, "res://assets/models/units/striker_0.png")
attach_weapon(_model_instance)
# 애니메이션 플레이어 및 라이브러리 연동
_model_anim_player = UnitHelper.find_animation_player(_model_instance)
if _model_anim_player:
var anim_lib_path: String = "res://assets/models/units/" + m_name + "/" + m_name + "_animations.tres"
if ResourceLoader.exists(anim_lib_path):
var lib: AnimationLibrary = load(anim_lib_path) as AnimationLibrary
if lib:
if _model_anim_player.has_animation_library(""):
_model_anim_player.remove_animation_library("")
if not _model_anim_player.has_animation_library(m_name):
_model_anim_player.add_animation_library(m_name, lib)
UnitHelper.clean_root_animation_tracks(_model_anim_player)
func _get_attack_animation_name(_model_name: String) -> String:
return _model_name + "/" + STRIKER_ATTACK_ANIM
func _get_weapon_config() -> Dictionary:
return {
"bone_name": "RightHand",
"attachment_name": "RightHandAttachment",
"weapon_scene_path": "res://assets/models/items/weapons/azure_blade/azure_blade.glb",
"texture_path": "res://assets/models/items/weapons/azure_blade/azure_blade_0.png"
}
## 스트라이커 애니메이션 갱신 제어
func _update_animations() -> void:
if not _model_anim_player:
return
var m_name: String = "striker"
var library_prefix: String = m_name + "/"
var has_custom_anims: bool = _model_anim_player.has_animation(library_prefix + "Idle")
var target_anim: String = ""
var play_speed: float = 1.0
var blend_time: float = 0.2
if has_custom_anims:
var attack_anim: String = library_prefix + "Slash"
var run_anim: String = library_prefix + "Running"
var idle_anim: String = library_prefix + "Idle"
if _attack_lock_timer > 0.0:
var base_speed: float = 1.5
if unit_data.cooldown < 0.6:
base_speed = 0.6 / unit_data.cooldown
play_speed = clampf(base_speed, 1.0, 3.0)
target_anim = attack_anim
elif velocity.length() > 0.1:
target_anim = run_anim
play_speed = 1.2
else:
target_anim = idle_anim
play_speed = 1.0
if target_anim != "" and _model_anim_player.current_animation != target_anim:
_last_anim_state = target_anim.replace(library_prefix, "")
_model_anim_player.play(target_anim, blend_time, play_speed)
else:
# Fallback 처리
var fallback_anim: String = "Armature|Armature|Basic_Jump|baselayer"
if not _model_anim_player.has_animation(fallback_anim):
return
if _attack_lock_timer > 0.0:
target_anim = fallback_anim
play_speed = 2.5
elif velocity.length() > 0.1:
target_anim = fallback_anim
play_speed = 1.5
else:
target_anim = ""
_model_anim_player.stop()
if target_anim != "" and _model_anim_player.current_animation != target_anim:
_model_anim_player.play(target_anim, blend_time, play_speed)
[gd_scene format=3 uid="uid://dwvbc5m3myqbk"]
[ext_resource type="Script" uid="uid://hw8yqaf0uujj" path="res://src/entities/units/striker/striker_unit.gd" id="1_base_unit"]
[ext_resource type="PackedScene" uid="uid://c2aiejcidlihv" path="res://src/entities/units/striker/striker.tscn" id="2_iytoq"]
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_body"]
radius = 0.4
height = 1.2
[sub_resource type="CapsuleMesh" id="CapsuleMesh_unit"]
radius = 0.4
height = 1.2
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ring"]
albedo_color = Color(0.098039, 0.901961, 0.098039, 1)
emission_enabled = true
emission = Color(0.098039, 0.901961, 0.098039, 1)
emission_energy_multiplier = 2.0
[sub_resource type="TorusMesh" id="TorusMesh_selection"]
material = SubResource("StandardMaterial3D_ring")
inner_radius = 0.65
outer_radius = 0.7
[node name="StrikerUnit" type="CharacterBody3D" unique_id=1844747242]
script = ExtResource("1_base_unit")
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=332342782]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.6, 0)
shape = SubResource("CapsuleShape3D_body")
[node name="VisualMesh" type="MeshInstance3D" parent="." unique_id=758090532]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.6, 0)
visible = false
mesh = SubResource("CapsuleMesh_unit")
[node name="SelectionRing" type="MeshInstance3D" parent="." unique_id=1378906746]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.02, 0)
mesh = SubResource("TorusMesh_selection")
[node name="NavigationAgent3D" type="NavigationAgent3D" parent="." unique_id=462079662]
[node name="striker" parent="." unique_id=1533136548 instance=ExtResource("2_iytoq")]
[editable path="striker"]
...@@ -7,8 +7,6 @@ extends RefCounted ...@@ -7,8 +7,6 @@ extends RefCounted
const INVALID_TILE_CELL: Vector3i = Vector3i(2147483647, 2147483647, 2147483647) const INVALID_TILE_CELL: Vector3i = Vector3i(2147483647, 2147483647, 2147483647)
const STRIKER_SCENE: PackedScene = preload("res://src/entities/units/striker/striker_unit.tscn")
const GUARDIAN_SCENE: PackedScene = preload("res://src/entities/units/guardian/guardian_unit.tscn")
const RANGER_SCENE: PackedScene = preload("res://src/entities/units/ranger/ranger_unit.tscn") const RANGER_SCENE: PackedScene = preload("res://src/entities/units/ranger/ranger_unit.tscn")
const MAGE_SCENE: PackedScene = preload("res://src/entities/units/mage/mage_unit.tscn") const MAGE_SCENE: PackedScene = preload("res://src/entities/units/mage/mage_unit.tscn")
const WARRIOR_LV1_SCENE: PackedScene = preload("res://src/entities/units/warrior/lv1/warrior_unit.tscn") const WARRIOR_LV1_SCENE: PackedScene = preload("res://src/entities/units/warrior/lv1/warrior_unit.tscn")
...@@ -121,10 +119,6 @@ func begin_random_unit_placement() -> void: ...@@ -121,10 +119,6 @@ func begin_random_unit_placement() -> void:
## 새 유닛 타입이 추가되면 이 match에만 씬 매핑을 늘리면 배치 흐름은 그대로 재사용됩니다. ## 새 유닛 타입이 추가되면 이 match에만 씬 매핑을 늘리면 배치 흐름은 그대로 재사용됩니다.
func _get_scene_for_unit(unit_data: UnitData) -> PackedScene: func _get_scene_for_unit(unit_data: UnitData) -> PackedScene:
match unit_data.unit_id: match unit_data.unit_id:
"Unit_Striker":
return STRIKER_SCENE
"Unit_Guardian":
return GUARDIAN_SCENE
"Unit_Ranger": "Unit_Ranger":
return RANGER_SCENE return RANGER_SCENE
"Unit_Mage": "Unit_Mage":
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment