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
f631e2c2
Commit
f631e2c2
authored
Jun 24, 2026
by
Gavin An
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
투사체 속성 넣을 수 있도록
parent
71d60e4a
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
60 additions
and
15 deletions
+60
-15
src/entities/units/mage/mage_unit.gd
src/entities/units/mage/mage_unit.gd
+33
-10
src/entities/units/ranger/ranger_unit.gd
src/entities/units/ranger/ranger_unit.gd
+4
-0
src/entities/units/unit_data.gd
src/entities/units/unit_data.gd
+19
-1
src/ui/summoner_selection/summoner_selection.tscn
src/ui/summoner_selection/summoner_selection.tscn
+4
-4
No files found.
src/entities/units/mage/mage_unit.gd
View file @
f631e2c2
class_name
MageUnit
class_name
MageUnit
extends
BaseUnit
extends
BaseUnit
## Mage 유닛 고유 동작 및 비주얼 제어 클래스
## Mage (마법사) 유닛 고유 동작 및 비주얼 제어 클래스
## - BaseUnit을 상속받아 마법사 모델 스킨 적용, 애니메이션 라이브러리 로드 및
## 불덩이(Fireball) 특수 효과 발사체 생성을 처리합니다.
## 유닛의 3D 비주얼 모델, 스킨 텍스처, 무기 및 애니메이션 플레이어 연동 설정
func
_setup_unit_visuals
()
->
void
:
func
_setup_unit_visuals
()
->
void
:
# 자식 노드 중 메이지
모델 노드 명시적 확보
# 자식 노드 중 메이지
(Mage) 3D 모델 노드 이름을 명시하여 인스턴스를 확보합니다.
var
m_name
:
String
=
"mage"
var
m_name
:
String
=
"mage"
var
node
:
Node3D
=
get_node_or_null
(
m_name
)
as
Node3D
var
node
:
Node3D
=
get_node_or_null
(
m_name
)
as
Node3D
# 모델 노드가 씬 트리 아래에 존재하지 않을 경우 에러를 출력하고 함수를 종료합니다.
if
not
node
:
if
not
node
:
push_error
(
"MageUnit: Model node '"
+
m_name
+
"' not found under children."
)
push_error
(
"MageUnit: Model node '"
+
m_name
+
"' not found under children."
)
return
return
_model_instance
=
node
_model_instance
=
node
#
메이지 스킨 및 무기 결합
#
UnitHelper를 활용해 마법사 전용 스킨 이미지와 무기 메쉬를 결합합니다.
UnitHelper
.
apply_skin
(
_model_instance
,
"res://assets/models/units/mage/mage_0.png"
)
UnitHelper
.
apply_skin
(
_model_instance
,
"res://assets/models/units/mage/mage_0.png"
)
UnitHelper
.
attach_weapon
(
_model_instance
,
unit_data
)
UnitHelper
.
attach_weapon
(
_model_instance
,
unit_data
)
#
애니메이션 플레이어 및 라이브러리 연동
#
모델 씬 내부에 구성되어 있는 AnimationPlayer 노드를 탐색하여 변수에 캐싱합니다.
_model_anim_player
=
UnitHelper
.
find_animation_player
(
_model_instance
)
_model_anim_player
=
UnitHelper
.
find_animation_player
(
_model_instance
)
if
_model_anim_player
:
if
_model_anim_player
:
print
(
"MageUnit: Linked pre-configured model & AnimationPlayer: "
,
m_name
)
print
(
"MageUnit: Linked pre-configured model & AnimationPlayer: "
,
m_name
)
# 마법사 유닛 전용으로 추출된 애니메이션 라이브러리 리소스 경로를 지정합니다.
var
anim_lib_path
:
String
=
"res://assets/models/units/"
+
m_name
+
"/"
+
m_name
+
"_animations.tres"
var
anim_lib_path
:
String
=
"res://assets/models/units/"
+
m_name
+
"/"
+
m_name
+
"_animations.tres"
if
ResourceLoader
.
exists
(
anim_lib_path
):
if
ResourceLoader
.
exists
(
anim_lib_path
):
var
lib
:
AnimationLibrary
=
load
(
anim_lib_path
)
as
AnimationLibrary
var
lib
:
AnimationLibrary
=
load
(
anim_lib_path
)
as
AnimationLibrary
if
lib
:
if
lib
:
# 기존 기본 빈 라이브러리가 존재하면 충돌 방지를 위해 제거합니다.
if
_model_anim_player
.
has_animation_library
(
""
):
if
_model_anim_player
.
has_animation_library
(
""
):
_model_anim_player
.
remove_animation_library
(
""
)
_model_anim_player
.
remove_animation_library
(
""
)
# 마법사 전용 애니메이션 라이브러리가 등록되어 있지 않다면 라이브러리를 추가합니다.
if
not
_model_anim_player
.
has_animation_library
(
m_name
):
if
not
_model_anim_player
.
has_animation_library
(
m_name
):
_model_anim_player
.
add_animation_library
(
m_name
,
lib
)
_model_anim_player
.
add_animation_library
(
m_name
,
lib
)
print
(
"MageUnit: Loaded and registered "
,
m_name
,
" animations library successfully."
)
print
(
"MageUnit: Loaded and registered "
,
m_name
,
" animations library successfully."
)
# 트랙 내 불필요한 루트 모션 경로 정리를 수행합니다.
UnitHelper
.
clean_root_animation_tracks
(
_model_anim_player
)
UnitHelper
.
clean_root_animation_tracks
(
_model_anim_player
)
##
메이지 애니메이션 갱신 제어
##
매 프레임 물리에 맞추어 마법사 유닛의 애니메이션 상태를 제어하는 함수
func
_update_animations
()
->
void
:
func
_update_animations
()
->
void
:
if
not
_model_anim_player
:
if
not
_model_anim_player
:
return
return
var
m_name
:
String
=
"mage"
var
m_name
:
String
=
"mage"
var
library_prefix
:
String
=
m_name
+
"/"
var
library_prefix
:
String
=
m_name
+
"/"
# 전용 애니메이션 라이브러리 내에 기본 대기 상태(Idle) 애니메이션이 있는지 식별합니다.
var
has_custom_anims
:
bool
=
_model_anim_player
.
has_animation
(
library_prefix
+
"Idle"
)
var
has_custom_anims
:
bool
=
_model_anim_player
.
has_animation
(
library_prefix
+
"Idle"
)
var
target_anim
:
String
=
""
var
target_anim
:
String
=
""
...
@@ -46,30 +57,36 @@ func _update_animations() -> void:
...
@@ -46,30 +57,36 @@ func _update_animations() -> void:
var
blend_time
:
float
=
0.2
var
blend_time
:
float
=
0.2
if
has_custom_anims
:
if
has_custom_anims
:
# Mage용 애니메이션 매핑 (Attack, Running, Idle, Casting)
# Mage용 애니메이션
이름
매핑 (Attack, Running, Idle, Casting)
var
attack_anim
:
String
=
library_prefix
+
"Attack"
var
attack_anim
:
String
=
library_prefix
+
"Attack"
var
run_anim
:
String
=
library_prefix
+
"Running"
var
run_anim
:
String
=
library_prefix
+
"Running"
var
idle_anim
:
String
=
library_prefix
+
"Idle"
var
idle_anim
:
String
=
library_prefix
+
"Idle"
var
cast_anim
:
String
=
library_prefix
+
"Casting"
var
cast_anim
:
String
=
library_prefix
+
"Casting"
# 1. 공격 중일 때 (공격 선딜/모션 락 타이머가 작동 중인 경우)
if
_attack_lock_timer
>
0.0
:
if
_attack_lock_timer
>
0.0
:
var
base_speed
:
float
=
1.2
var
base_speed
:
float
=
1.5
# 유닛 쿨다운에 맞춘 애니메이션 속도 보정
if
unit_data
.
cooldown
<
0.6
:
if
unit_data
.
cooldown
<
0.6
:
base_speed
=
0.6
/
unit_data
.
cooldown
base_speed
=
0.6
/
unit_data
.
cooldown
play_speed
=
clampf
(
base_speed
,
1.0
,
3.0
)
play_speed
=
clampf
(
base_speed
,
1.0
,
3.0
)
# 마법을 시전하는 모션(Casting)을 재생합니다.
target_anim
=
cast_anim
target_anim
=
cast_anim
# 2. 이동 중일 때 (속도 벡터 크기가 0.1보다 클 경우)
elif
velocity
.
length
()
>
0.1
:
elif
velocity
.
length
()
>
0.1
:
target_anim
=
run_anim
target_anim
=
run_anim
play_speed
=
1.1
play_speed
=
1.1
# 3. 그 외 기본 대기 상태일 때
else
:
else
:
target_anim
=
idle_anim
target_anim
=
idle_anim
play_speed
=
1.0
play_speed
=
1.0
# 타겟 애니메이션이 정해졌고, 현재 재생 중인 애니메이션과 다를 경우 크로스페이드 재생합니다.
if
target_anim
!=
""
and
_model_anim_player
.
current_animation
!=
target_anim
:
if
target_anim
!=
""
and
_model_anim_player
.
current_animation
!=
target_anim
:
_last_anim_state
=
target_anim
.
replace
(
library_prefix
,
""
)
_last_anim_state
=
target_anim
.
replace
(
library_prefix
,
""
)
_model_anim_player
.
play
(
target_anim
,
blend_time
,
play_speed
)
_model_anim_player
.
play
(
target_anim
,
blend_time
,
play_speed
)
else
:
else
:
#
Fallback 처리
#
전용 애니메이션이 없을 때의 예외 처리 (기본 Fallback 점프 애니메이션 루프 적용)
var
fallback_anim
:
String
=
"Armature|Armature|Basic_Jump|baselayer"
var
fallback_anim
:
String
=
"Armature|Armature|Basic_Jump|baselayer"
if
not
_model_anim_player
.
has_animation
(
fallback_anim
):
if
not
_model_anim_player
.
has_animation
(
fallback_anim
):
return
return
...
@@ -87,16 +104,22 @@ func _update_animations() -> void:
...
@@ -87,16 +104,22 @@ func _update_animations() -> void:
if
target_anim
!=
""
and
_model_anim_player
.
current_animation
!=
target_anim
:
if
target_anim
!=
""
and
_model_anim_player
.
current_animation
!=
target_anim
:
_model_anim_player
.
play
(
target_anim
,
blend_time
,
play_speed
)
_model_anim_player
.
play
(
target_anim
,
blend_time
,
play_speed
)
##
메이지 전용 발사체 생성 및 스폰
##
마법사(Mage) 전용 화염 불덩이(Fireball) 발사체를 월드에 스폰하는 함수
func
_spawn_projectile
(
fire_position
:
Vector3
)
->
void
:
func
_spawn_projectile
(
fire_position
:
Vector3
)
->
void
:
# 공통 Projectile 스크립트를 로드하여 발사체 인스턴스를 동적 생성합니다.
var
projectile_script
=
preload
(
"res://src/entities/units/projectile.gd"
)
var
projectile_script
=
preload
(
"res://src/entities/units/projectile.gd"
)
var
proj
:
Node3D
=
projectile_script
.
new
()
as
Node3D
var
proj
:
Node3D
=
projectile_script
.
new
()
as
Node3D
# 발사체의 능력치 및 비행 속성 주입 (공격력, 유도 대상, 비행 속도, 이펙트 색상)
proj
.
set
(
"damage"
,
unit_data
.
damage
)
proj
.
set
(
"damage"
,
unit_data
.
damage
)
proj
.
set
(
"target"
,
_target_monster
)
proj
.
set
(
"target"
,
_target_monster
)
proj
.
set
(
"speed"
,
18.0
)
# 불덩이는 크고 묵직하므로 조금 느린 속도(18.0m/s)로 날아가게 설정
proj
.
set
(
"color"
,
Color
(
1.0
,
0.35
,
0.1
,
1.0
))
# 붉은 주황색 계열의 색상 지정
#
불덩이 비주얼 효과 씬 장착
#
셰이더 및 GPUParticles3D가 사전 구성된 불덩이 비주얼 효과 씬(.tscn)을 전달합니다.
var
fb_effect
=
preload
(
"res://src/entities/projectiles/fireball/fireball_effect.tscn"
)
var
fb_effect
=
preload
(
"res://src/entities/projectiles/fireball/fireball_effect.tscn"
)
proj
.
set
(
"custom_visual_scene"
,
fb_effect
)
proj
.
set
(
"custom_visual_scene"
,
fb_effect
)
# 발사체를 씬 트리에 등록하고 설정된 발사 좌표(fire_position)를 부여합니다.
get_tree
()
.
current_scene
.
add_child
(
proj
)
get_tree
()
.
current_scene
.
add_child
(
proj
)
proj
.
global_position
=
fire_position
proj
.
global_position
=
fire_position
src/entities/units/ranger/ranger_unit.gd
View file @
f631e2c2
...
@@ -89,8 +89,12 @@ func _update_animations() -> void:
...
@@ -89,8 +89,12 @@ func _update_animations() -> void:
func
_spawn_projectile
(
fire_position
:
Vector3
)
->
void
:
func
_spawn_projectile
(
fire_position
:
Vector3
)
->
void
:
var
projectile_script
=
preload
(
"res://src/entities/units/projectile.gd"
)
var
projectile_script
=
preload
(
"res://src/entities/units/projectile.gd"
)
var
proj
:
Node3D
=
projectile_script
.
new
()
as
Node3D
var
proj
:
Node3D
=
projectile_script
.
new
()
as
Node3D
# 발사체의 속성들을 설정합니다. (공격력, 유도 대상, 비행 속도, 이펙트 색상)
proj
.
set
(
"damage"
,
unit_data
.
damage
)
proj
.
set
(
"damage"
,
unit_data
.
damage
)
proj
.
set
(
"target"
,
_target_monster
)
proj
.
set
(
"target"
,
_target_monster
)
proj
.
set
(
"speed"
,
28.0
)
# 화살은 매우 날렵하므로 빠른 속도(28.0m/s)로 비행하게 설정
proj
.
set
(
"color"
,
unit_data
.
unit_color
)
# 레인저 고유의 유닛 컬러 지정
# 레인저 화살 비주얼 씬 장착
# 레인저 화살 비주얼 씬 장착
var
arrow_effect
=
preload
(
"res://src/entities/projectiles/arrow/arrow_effect.tscn"
)
var
arrow_effect
=
preload
(
"res://src/entities/projectiles/arrow/arrow_effect.tscn"
)
...
...
src/entities/units/unit_data.gd
View file @
f631e2c2
class_name
UnitData
class_name
UnitData
extends
Resource
extends
Resource
## 유닛의 기획 능력치를 정의하는 커스텀 리소스 (UnitData)
## 유닛의 기획 능력치(스펙) 데이터를 정의하는 커스텀 리소스 클래스 (UnitData)
## - Godot의 Resource 클래스를 상속받아 유닛 데이터 템플릿을 생성 및 직렬화하기에 용이합니다.
## - DataManager에서 각 유닛의 기본 능력치를 정의하고 생성할 때 템플릿 데이터로 활용됩니다.
## 유닛 고유 식별자 ID (예: "Unit_Striker", "Unit_Mage")
@
export
var
unit_id
:
String
=
""
@
export
var
unit_id
:
String
=
""
## UI 및 로그에 출력할 유닛 이름 (예: "Striker", "Mage")
@
export
var
unit_name
:
String
=
""
@
export
var
unit_name
:
String
=
""
## 유닛의 기본 공격력 (적에게 가하는 데미지 수치)
@
export
var
damage
:
float
=
10.0
@
export
var
damage
:
float
=
10.0
## 공격 주기/쿨다운 시간 (초 단위, 낮을수록 공격 속도가 빠름)
@
export
var
cooldown
:
float
=
1.0
@
export
var
cooldown
:
float
=
1.0
## 유닛의 전장 내 기본 이동 속도
@
export
var
move_speed
:
float
=
4.0
@
export
var
move_speed
:
float
=
4.0
## 공격 가능 사거리 (단위: 미터, 근접 유닛은 보통 1.5, 원거리는 8.0~10.0)
@
export
var
attack_range
:
float
=
1.5
@
export
var
attack_range
:
float
=
1.5
## 원거리 유닛 여부 (true일 경우 투사체를 발사하고, false일 경우 근접 타격을 가함)
@
export
var
is_ranged
:
bool
=
false
@
export
var
is_ranged
:
bool
=
false
## 유닛 선택 링(Selection Ring) 및 발사체 색상 연출 등에 쓰이는 유닛 고유 색상
@
export
var
unit_color
:
Color
=
Color
.
WHITE
@
export
var
unit_color
:
Color
=
Color
.
WHITE
src/ui/summoner_selection/summoner_selection.tscn
View file @
f631e2c2
...
@@ -56,8 +56,8 @@ alignment = 1
...
@@ -56,8 +56,8 @@ alignment = 1
[node name="Portrait" type="TextureRect" parent="VBoxContainer/CardsHBox/MageCard" unique_id=947627767]
[node name="Portrait" type="TextureRect" parent="VBoxContainer/CardsHBox/MageCard" unique_id=947627767]
custom_minimum_size = Vector2(240, 240)
custom_minimum_size = Vector2(240, 240)
layout_mode = 2
layout_mode = 2
expand_mode =
1
expand_mode =
4
stretch_mode =
6
stretch_mode =
4
[node name="Name" type="Label" parent="VBoxContainer/CardsHBox/MageCard" unique_id=594177406]
[node name="Name" type="Label" parent="VBoxContainer/CardsHBox/MageCard" unique_id=594177406]
layout_mode = 2
layout_mode = 2
...
@@ -88,8 +88,8 @@ alignment = 1
...
@@ -88,8 +88,8 @@ alignment = 1
[node name="Portrait" type="TextureRect" parent="VBoxContainer/CardsHBox/WarriorCard" unique_id=1881168350]
[node name="Portrait" type="TextureRect" parent="VBoxContainer/CardsHBox/WarriorCard" unique_id=1881168350]
custom_minimum_size = Vector2(240, 240)
custom_minimum_size = Vector2(240, 240)
layout_mode = 2
layout_mode = 2
expand_mode =
1
expand_mode =
4
stretch_mode =
6
stretch_mode =
4
[node name="Name" type="Label" parent="VBoxContainer/CardsHBox/WarriorCard" unique_id=1845912094]
[node name="Name" type="Label" parent="VBoxContainer/CardsHBox/WarriorCard" unique_id=1845912094]
layout_mode = 2
layout_mode = 2
...
...
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