Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
L
ldefense
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Packages
Packages
Container Registry
Analytics
CI / CD Analytics
Repository Analytics
Value Stream Analytics
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Gavin An
ldefense
Commits
474297e4
Commit
474297e4
authored
Jun 23, 2026
by
Gavin An
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
유닛, 몬스터 상속 작업 전
parent
711b84d0
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
134 additions
and
92 deletions
+134
-92
src/autoload/data_manager.gd
src/autoload/data_manager.gd
+46
-27
src/core/stage_manager.gd
src/core/stage_manager.gd
+9
-6
src/entities/monsters/base_monster.gd
src/entities/monsters/base_monster.gd
+68
-59
src/entities/monsters/monster_data.gd
src/entities/monsters/monster_data.gd
+10
-0
src/entities/monsters/monster_data.gd.uid
src/entities/monsters/monster_data.gd.uid
+1
-0
No files found.
src/autoload/data_manager.gd
View file @
474297e4
...
...
@@ -4,9 +4,12 @@ extends Node
# 유닛 리소스 템플릿 목록
var
unit_templates
:
Array
[
UnitData
]
=
[]
# 몬스터 리소스 템플릿 목록
var
monster_templates
:
Array
[
MonsterData
]
=
[]
func
_ready
()
->
void
:
_initialize_unit_templates
()
_initialize_monster_templates
()
## 5종의 유닛 능력치 데이터 초기 셋업
func
_initialize_unit_templates
()
->
void
:
...
...
@@ -46,35 +49,51 @@ func _initialize_unit_templates() -> void:
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
)
## 몬스터 능력치 데이터 초기 셋업
func
_initialize_monster_templates
()
->
void
:
#
1. Noble Man (기본 밸런스형 몬스터)
var
noble_man
:
MonsterData
=
MonsterData
.
new
()
noble_man
.
monster_id
=
"noble_man"
noble_man
.
monster_name
=
"Noble Man"
noble_man
.
hp
=
100.0
noble_man
.
speed
=
2.0
noble_man
.
gold_reward
=
15
noble_man
.
model_name
=
"noble_man"
monster_templates
.
append
(
noble_man
)
# 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)
# 2. Zombie (고체력 저속형 몬스터)
var
zombie
:
MonsterData
=
MonsterData
.
new
()
zombie
.
monster_id
=
"zombie"
zombie
.
monster_name
=
"Zombie"
zombie
.
hp
=
150.0
zombie
.
speed
=
1.5
zombie
.
gold_reward
=
20
zombie
.
model_name
=
"zombie"
monster_templates
.
append
(
zombie
)
## 특정 스테이지에 따른 몬스터 체력(HP) 반환
func
get_monster_hp
(
stage
:
int
)
->
float
:
return
100.0
+
(
stage
-
1
)
*
50.0
## 특정 스테이지 스케일이 반영된 완성된 MonsterData 인스턴스를 반환
func
get_stage_monster_data
(
monster_id
:
String
,
stage
:
int
)
->
MonsterData
:
var
template
:
MonsterData
=
null
for
t
in
monster_templates
:
if
t
.
monster_id
==
monster_id
:
template
=
t
break
## 특정 스테이지에 따른 몬스터 처치 보상 골드 반환
if
not
template
:
push_error
(
"DataManager: Monster template not found for ID: "
+
monster_id
)
return
null
# 복제하여 런타임용 데이터 독립 인스턴스 생성
var
stage_data
=
template
.
duplicate
(
true
)
as
MonsterData
# 체력 스케일링: 기본 체력 + (스테이지 - 1) * 50
stage_data
.
hp
=
template
.
hp
+
(
stage
-
1
)
*
50.0
# 처치 골드 리워드 스케일링
stage_data
.
gold_reward
=
get_monster_gold_reward
(
stage
)
return
stage_data
## 특정 스테이지에 따른 몬스터 처치 보상 골드 반환 (기본 연산용)
func
get_monster_gold_reward
(
stage
:
int
)
->
int
:
if
stage
>=
20
:
return
100
elif
stage
>=
15
:
return
60
+
(
stage
-
15
)
*
8
...
...
src/core/stage_manager.gd
View file @
474297e4
...
...
@@ -91,13 +91,16 @@ func _on_spawn_timer_timeout() -> void:
var
monster_instance
:
Node
=
selected_scene
.
instantiate
()
_path_node
.
add_child
(
monster_instance
)
# 몬스터 초기화 (
HP, 보상 골드 설정
)
# 몬스터 초기화 (
리소스 ID 판정 및 스테이지 데이터 획득
)
var
stage
:
int
=
GameManager
.
current_stage
var
monster_hp
:
float
=
DataManager
.
get_monster_hp
(
stage
)
var
monster_gold
:
int
=
DataManager
.
get_monster_gold_reward
(
stage
)
if
monster_instance
.
has_method
(
"initialize_monster"
):
monster_instance
.
call
(
"initialize_monster"
,
monster_hp
,
monster_gold
)
var
monster_id
:
String
=
"noble_man"
# 기본값
var
scene_path
:
String
=
selected_scene
.
resource_path
.
to_lower
()
if
"zombie"
in
scene_path
:
monster_id
=
"zombie"
var
monster_data
:
MonsterData
=
DataManager
.
get_stage_monster_data
(
monster_id
,
stage
)
if
monster_data
and
monster_instance
.
has_method
(
"initialize_monster"
):
monster_instance
.
call
(
"initialize_monster"
,
monster_data
)
GameManager
.
increment_monster_count
()
...
...
src/entities/monsters/base_monster.gd
View file @
474297e4
class_name
BaseMonster
extends
PathFollow3D
## 기본 몬스터 클래스 (
Path3D 상하위에서 경로를 따라 회전하며 피격/사망 처리됨
)
## 기본 몬스터 클래스 (
MonsterData를 기반으로 스펙 및 모델을 설정하고 이동/피격 처리
)
# 몬스터 능력치 설정
@
export
var
monster_data
:
MonsterData
# 몬스터 실시간 스펙 (MonsterData 주입 수치를 따름)
@
export
var
speed
:
float
=
2.0
var
max_hp
:
float
=
100.0
var
current_hp
:
float
=
100.0
...
...
@@ -21,57 +23,64 @@ func _ready() -> void:
# PathFollow3D 루프 설정 활성화 (경로 끝 도달 시 처음으로 돌아감)
loop
=
true
# 자식 노드 중 3D 모델(noble_man 등) 노드 자동 탐색 및 초기화 (base_unit.gd 매커니즘 준수)
#var model_names: Array[String] = ["noble_man", "zombie"]
var
model_names
:
Array
[
String
]
=
[
"zombie"
]
var
detected_model_node
:
Node3D
=
null
var
detected_model_name
:
String
=
""
# 만약 씬 내부에 monster_data 리소스가 사전 설정되어 있다면 바로 로드 실행
if
monster_data
:
_setup_monster_from_data
()
for
m_name
:
String
in
model_names
:
var
node
:
Node3D
=
get_node_or_null
(
m_name
)
as
Node3D
if
node
:
detected_model_node
=
node
detected_model_name
=
m_name
break
## 몬스터 데이터 기반 모델 및 충돌, 스킨/애니메이션 정렬 셋업
func
_setup_monster_from_data
()
->
void
:
if
not
monster_data
:
return
if
not
detected_model_node
:
var
m_name
:
String
=
monster_data
.
model_name
var
node
:
Node3D
=
get_node_or_null
(
m_name
)
as
Node3D
if
not
node
:
push_error
(
"BaseMonster: Model node '"
+
m_name
+
"' not found under children."
)
return
_model_instance
=
node
print
(
"BaseMonster: Identified model ["
,
m_name
,
"] from MonsterData."
)
_model_instance
=
detected_model_node
#GridMap 타일 높이(Y=0.21)에 맞춰 모델 및 충돌 판정 영역 오프셋 보정
#_model_instance.position.y = 0
var
monster_area
=
get_node_or_null
(
"MonsterArea"
)
#if monster_area and monster_area is Node3D:
#monster_area.position.y = 0.71
if
detected_model_name
==
"noble_man"
:
if
m_name
==
"noble_man"
:
_apply_noble_man_skin
(
_model_instance
)
elif
detected_model
_name
==
"zombie"
:
elif
m
_name
==
"zombie"
:
_apply_zombie_skin
(
_model_instance
)
_model_anim_player
=
_find_animation_player
(
_model_instance
)
if
not
_model_anim_player
:
return
print
(
"BaseMonster: Linked model AnimationPlayer: "
,
detected_model_name
)
# 모델명_animations.tres 또는 모델명_anims.tres 라이브러리를 동적으로 로드하여 등록 (base_unit.gd 방식 준수)
# 단, 씬 파일에서 이미 기본 라이브러리("")로 등록된 경우 중복 등록 방지
var
anim_lib_path
:
String
=
"res://assets/models/monsters/"
+
detected_model_name
+
"/"
+
detected_model_name
+
"_animations.tres"
if
anim_lib_path
!=
""
:
var
lib
:
AnimationLibrary
=
load
(
anim_lib_path
)
as
AnimationLibrary
if
lib
and
not
_model_anim_player
.
has_animation_library
(
detected_model_name
):
_model_anim_player
.
add_animation_library
(
detected_model_name
,
lib
)
print
(
"BaseMonster: Loaded and registered "
,
detected_model_name
,
" animations library successfully."
)
if
_model_anim_player
:
print
(
"BaseMonster: Linked model AnimationPlayer: "
,
m_name
)
# 모델명_animations.tres 또는 모델명_anims.tres 라이브러리를 동적으로 로드하여 등록
var
anim_lib_path
:
String
=
"res://assets/models/monsters/"
+
m_name
+
"/"
+
m_name
+
"_animations.tres"
var
anim_lib_path_alt
:
String
=
"res://assets/models/monsters/"
+
m_name
+
"/"
+
m_name
+
"_anims.tres"
var
path_to_load
:
String
=
""
if
ResourceLoader
.
exists
(
anim_lib_path
):
path_to_load
=
anim_lib_path
elif
ResourceLoader
.
exists
(
anim_lib_path_alt
):
path_to_load
=
anim_lib_path_alt
if
path_to_load
!=
""
:
var
lib
:
AnimationLibrary
=
load
(
path_to_load
)
as
AnimationLibrary
if
lib
and
not
_model_anim_player
.
has_animation_library
(
m_name
):
var
already_registered
:
bool
=
false
for
existing_lib_name
in
_model_anim_player
.
get_animation_library_list
():
if
_model_anim_player
.
get_animation_library
(
existing_lib_name
)
==
lib
:
already_registered
=
true
break
if
not
already_registered
:
_model_anim_player
.
add_animation_library
(
m_name
,
lib
)
print
(
"BaseMonster: Loaded and registered "
,
m_name
,
" animations library successfully."
)
else
:
print
(
"BaseMonster: Animation library already present (scene-bound or already added)
."
)
print
(
"BaseMonster: Animation library already registered on model under another name
."
)
# 초기 Idle 애니메이션 재생 시도
# 탐색 순서: 기본 라이브러리("") -> 동적 등록(모델명/) -> FBX 내장
var
init_idle
:
String
=
_resolve_anim_name
(
_model_anim_player
,
detected_model_name
,
"Idle"
)
var
init_idle
:
String
=
_resolve_anim_name
(
_model_anim_player
,
m_name
,
"Idle"
)
if
init_idle
!=
""
:
_model_anim_player
.
play
(
init_idle
)
print
(
"BaseMonster: Playing initial Idle: "
,
init_idle
)
## 몬스터 자식 메쉬에 noble_man_0.png 텍스처를 입히는 재귀 함수
func
_apply_noble_man_skin
(
node
:
Node
)
->
void
:
if
node
is
MeshInstance3D
:
...
...
@@ -116,12 +125,19 @@ func _physics_process(delta: float) -> void:
_update_monster_animation
()
## 몬스터 초기화 (StageManager에 의해 스폰 시 호출됨)
func
initialize_monster
(
hp
:
float
,
reward
:
int
)
->
void
:
max_hp
=
hp
current_hp
=
hp
gold_reward
=
reward
func
initialize_monster
(
data
:
MonsterData
)
->
void
:
monster_data
=
data
max_hp
=
data
.
hp
current_hp
=
data
.
hp
speed
=
data
.
speed
gold_reward
=
data
.
gold_reward
is_dead
=
false
# _ready() 시점에 데이터가 비어 모델 셋업을 보류했던 경우 여기서 실행
if
not
_model_instance
:
_setup_monster_from_data
()
# 체력바 생성
_create_hp_bar
()
...
...
@@ -199,17 +215,14 @@ func _update_monster_animation() -> void:
return
var
model_name
:
String
=
""
if
_model_instance
:
if
monster_data
:
model_name
=
monster_data
.
model_name
elif
_model_instance
:
model_name
=
_model_instance
.
name
# 걷기 애니메이션 탐색 순서:
# 1. 씬 바인딩 기본 라이브러리("") -> "Walking"
# 2. 동적 등록 라이브러리 -> "모델명/Walking"
# 3. FBX 내장 트랙 -> "Armature|Walking"
var
anim_name
:
String
=
_resolve_anim_name
(
_model_anim_player
,
model_name
,
"Walking"
)
if
anim_name
!=
""
:
# 걷는 애니메이션 루프 활성화
var
anim
:
Animation
=
_model_anim_player
.
get_animation
(
anim_name
)
if
anim
:
anim
.
loop_mode
=
Animation
.
LOOP_LINEAR
...
...
@@ -230,16 +243,12 @@ func _find_animation_player(node: Node) -> AnimationPlayer:
return
null
## 헬퍼: 애니메이션 이름 탐색 (기본 라이브러리 -> 모델명 라이브러리 -> FBX 내장 순)
## anim_base_name: "Walking", "Idle", "Running" 등 라이브러리 키 없는 기본 이름
func
_resolve_anim_name
(
player
:
AnimationPlayer
,
model_name
:
String
,
anim_base_name
:
String
)
->
String
:
# 1순위: 씬에서 기본 라이브러리("")로 바인딩된 경우 (noble_man.tscn 방식)
if
player
.
has_animation
(
anim_base_name
):
return
anim_base_name
# 2순위: 동적으로 등록된 모델명 라이브러리
var
lib_anim
:
String
=
model_name
+
"/"
+
anim_base_name
if
player
.
has_animation
(
lib_anim
):
return
lib_anim
# 3순위: FBX 내장 Armature| 접두사 트랙
var
fbx_anim
:
String
=
"Armature|"
+
anim_base_name
if
player
.
has_animation
(
fbx_anim
):
return
fbx_anim
...
...
src/entities/monsters/monster_data.gd
0 → 100644
View file @
474297e4
class_name
MonsterData
extends
Resource
## 몬스터의 기획 능력치 및 메쉬 정보를 정의하는 커스텀 리소스 (MonsterData)
@
export
var
monster_id
:
String
=
""
@
export
var
monster_name
:
String
=
""
@
export
var
hp
:
float
=
100.0
@
export
var
speed
:
float
=
2.0
@
export
var
gold_reward
:
int
=
15
@
export
var
model_name
:
String
=
""
# 자식 노드로 들어갈 3D 모델 노드 이름 (예: "noble_man", "zombie")
src/entities/monsters/monster_data.gd.uid
0 → 100644
View file @
474297e4
uid://c4fjd2powdrha
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment