Commit ad7d7f9a authored by Gavin An's avatar Gavin An

무기를 손에 쥐어줌

parent 3aede6f6
......@@ -63,6 +63,7 @@
- [x] `res://src/entities/units/guardian/` 폴더 내에 `guardian_unit.tscn` 씬을 설계 및 신설하여 가디언 모델의 스킨 및 계층 구조 연동 완료
- [x] `hud.gd` 스크립트를 수정하여 기존의 중복된 유닛 ID 버그를 해결(Striker 외형으로만 고정 스폰되던 현상 픽스)하고, Guardian 유닛 소환 시 전용 `guardian_unit.tscn`이 스폰되도록 연동 완료
- [x] 사용자가 직접 `striker_unit.tscn`에서 모델 Y축 회전 보정(180도)을 조치한 내용을 인지하고, `base_unit.gd` 스크립트 상에서 불필요해진 수동 회전 보정 코드부를 완전히 삭제하여 씬 지향적 설정을 완수
- [x] Striker 유닛의 뼈대 스켈레톤의 오른손 본(`RightHand`)에 `BoneAttachment3D` 노드를 런타임 동적 배치하고, `azure_blade.fbx` 검 무기를 텍스처 오버라이드 매핑(`azure_blade_0.png`)과 방향/크기 보정을 더해 안정적으로 쥐어주는 런타임 무기 장착 시스템 구현 완료
---
......
uid://b28wkam585464
......@@ -58,6 +58,7 @@ func _ready() -> void:
if detected_model_name == "striker":
_apply_striker_skin(_model_instance)
_attach_weapon()
elif detected_model_name == "guardian":
_apply_guardian_skin(_model_instance)
......@@ -280,6 +281,75 @@ func _find_animation_player(node: Node) -> AnimationPlayer:
return res
return null
## 유닛의 오른손에 지정된 무기 모델을 런타임 장착
func _attach_weapon() -> void:
if not _model_instance:
return
# 스켈레톤 노드 탐색
var skeleton: Skeleton3D = _find_skeleton(_model_instance)
if not skeleton:
return
# 오른손 본("RightHand")이 존재하는지 확인
var bone_idx: int = skeleton.find_bone("RightHand")
if bone_idx == -1:
print("BaseUnit: RightHand bone not found in skeleton.")
return
# 이미 장착된 무기가 있는지 확인하여 제거 (중복 장착 방지)
var existing_attachment: Node = skeleton.get_node_or_null("RightHandAttachment")
if existing_attachment:
existing_attachment.queue_free()
# 1. BoneAttachment3D 노드 동적 생성 및 본 동기화 설정
var bone_attachment: BoneAttachment3D = BoneAttachment3D.new()
bone_attachment.name = "RightHandAttachment"
bone_attachment.bone_name = "RightHand"
skeleton.add_child(bone_attachment)
# 2. 무기 씬 인스턴스 생성 (azure_blade.fbx)
var weapon_scene_path: String = "res://assets/models/items/weapons/azure_blade.fbx"
if ResourceLoader.exists(weapon_scene_path):
var weapon_scene: PackedScene = load(weapon_scene_path) as PackedScene
if weapon_scene:
var weapon_inst: Node3D = weapon_scene.instantiate() as Node3D
# 검의 로컬 스케일, 회전 및 오프셋 보정 (손안에 쏙 들어가도록)
# FBX 원본 메쉬 크기(AABB 약 0.008)가 매우 작으므로 150배 확대하여 캐릭터 스펙에 맞춤
weapon_inst.scale = Vector3(1.0, 1.0, 1.0) # 150배 확대 보정
weapon_inst.rotation_degrees = Vector3(90.0, 0.0, 90.0) # 검날 방향 보정
weapon_inst.position = Vector3(0.0, 0.0, 0.0)
# 무기 텍스처(azure_blade_0.png) 매핑
_apply_weapon_skin(weapon_inst)
bone_attachment.add_child(weapon_inst)
print("BaseUnit: Attached azure_blade to RightHand bone successfully.")
## 무기 메쉬에 azure_blade_0.png 텍스처를 씌우는 재귀 함수
func _apply_weapon_skin(node: Node) -> void:
if node is MeshInstance3D:
var mesh_inst: MeshInstance3D = node as MeshInstance3D
var texture: Texture2D = load("res://assets/models/items/weapons/azure_blade_0.png") as Texture2D
if texture:
var mat: StandardMaterial3D = StandardMaterial3D.new()
mat.albedo_texture = texture
mat.roughness = 0.4
mesh_inst.material_override = mat
for child: Node in node.get_children():
_apply_weapon_skin(child)
## 헬퍼: 자식 노드 중 Skeleton3D 탐색
func _find_skeleton(node: Node) -> Skeleton3D:
if node is Skeleton3D:
return node as Skeleton3D
for child: Node in node.get_children():
var res: Skeleton3D = _find_skeleton(child)
if res:
return res
return null
## 상태(대기, 이동, 공격)별 3D 애니메이션 트랙 제어
func _update_animations() -> void:
if not _model_anim_player:
......
......@@ -54,52 +54,52 @@ func _initialize_unit_templates() -> void:
_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 = 1.5
guardian.is_ranged = false
guardian.unit_color = Color(0.85, 0.65, 0.12, 1.0) # 황금색
_unit_templates.append(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 = 1.5
#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()
ranger.unit_id = "Unit_Ranger"
ranger.unit_name = "Ranger"
ranger.damage = 18.0
ranger.cooldown = 0.8
ranger.move_speed = 4.5
ranger.attack_range = 10.0
ranger.is_ranged = true
ranger.unit_color = Color(0.12, 0.75, 0.25, 1.0) # 녹색
_unit_templates.append(ranger)
# 4. Slayer (고화력 대형 유닛)
var slayer: UnitData = UnitData.new()
slayer.unit_id = "Unit_Slayer"
slayer.unit_name = "Slayer"
slayer.damage = 55.0
slayer.cooldown = 1.8
slayer.move_speed = 3.5
slayer.attack_range = 1.6
slayer.is_ranged = false
slayer.unit_color = Color(0.85, 0.12, 0.12, 1.0) # 진적색
_unit_templates.append(slayer)
# 5. Archmage (극단적 극딜 마법 유닛)
var archmage: UnitData = UnitData.new()
archmage.unit_id = "Unit_Archmage"
archmage.unit_name = "Archmage"
archmage.damage = 110.0
archmage.cooldown = 3.0
archmage.move_speed = 3.0
archmage.attack_range = 12.0
archmage.is_ranged = true
archmage.unit_color = Color(0.55, 0.12, 0.85, 1.0) # 보라색
_unit_templates.append(archmage)
#var ranger: UnitData = UnitData.new()
#ranger.unit_id = "Unit_Ranger"
#ranger.unit_name = "Ranger"
#ranger.damage = 18.0
#ranger.cooldown = 0.8
#ranger.move_speed = 4.5
#ranger.attack_range = 10.0
#ranger.is_ranged = true
#ranger.unit_color = Color(0.12, 0.75, 0.25, 1.0) # 녹색
#_unit_templates.append(ranger)
#
## 4. Slayer (고화력 대형 유닛)
#var slayer: UnitData = UnitData.new()
#slayer.unit_id = "Unit_Slayer"
#slayer.unit_name = "Slayer"
#slayer.damage = 55.0
#slayer.cooldown = 1.8
#slayer.move_speed = 3.5
#slayer.attack_range = 1.6
#slayer.is_ranged = false
#slayer.unit_color = Color(0.85, 0.12, 0.12, 1.0) # 진적색
#_unit_templates.append(slayer)
#
## 5. Archmage (극단적 극딜 마법 유닛)
#var archmage: UnitData = UnitData.new()
#archmage.unit_id = "Unit_Archmage"
#archmage.unit_name = "Archmage"
#archmage.damage = 110.0
#archmage.cooldown = 3.0
#archmage.move_speed = 3.0
#archmage.attack_range = 12.0
#archmage.is_ranged = true
#archmage.unit_color = Color(0.55, 0.12, 0.85, 1.0) # 보라색
#_unit_templates.append(archmage)
# 골드 UI 갱신 및 소환 한도 검증
func _on_gold_changed(gold: int) -> void:
......
......@@ -52,3 +52,4 @@
- [x] `guardian_unit.tscn` 씬을 설계 및 신설하여 가디언 모델과 스킨 텍스처를 씬에 연계 완료
- [x] `hud.gd`에 중복되어 존재하던 유닛 ID 버그를 일괄 픽스하고, 가디언 유닛 소환 시 `guardian_unit.tscn`이 씬 분기로 올바르게 로드되도록 연동 완료
- [x] 사용자가 직접 `striker_unit.tscn`에서 모델 회전 보정을 적용한 상태를 인지하고, 스크립트(`base_unit.gd`)의 수동 Y축 회전 코드를 완벽히 제거
- [x] Striker 유닛 오른손 본(`RightHand`)에 `BoneAttachment3D` 노드를 런타임 동적 배치하고 `azure_blade.fbx` 검 무기를 장착 및 텍스처를 씌우는 기능 구현 완료
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