Waffen-Modell an Spielerhand via BoneAttachment3D
Schwert (medieval_sword.glb) wird zur Laufzeit an mixamorig_RightHand gehängt. Modell erscheint/verschwindet beim Ausrüsten/Ablegen. Equipment-Ressource um model_scene Property erweitert. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e4efb239f2
commit
9ed18e034c
13 changed files with 241 additions and 2 deletions
|
|
@ -190,6 +190,13 @@ Resource-Klasse für alle Ausrüstungsgegenstände.
|
|||
- **iron_helm.tres** — Eisenhelm (Kopf)
|
||||
- **wooden_shield.tres** — Holzschild (Nebenhand)
|
||||
|
||||
### Waffen-Modell am Charakter (BoneAttachment3D)
|
||||
- Schwert-Modell (`medieval_sword.glb`) wird zur Laufzeit an die rechte Hand (`mixamorig_RightHand`) des Spielers gehängt
|
||||
- Verwendet `BoneAttachment3D` am Skeleton3D des Spielermodells
|
||||
- Modell wird beim Ausrüsten einer Waffe (`equip_item`) angezeigt und beim Ablegen entfernt
|
||||
- Position/Rotation/Scale werden im Code gesetzt: `Vector3(0.5, 0.2, 0)`, `Vector3(90, 180, 0)`, `Vector3(0.8, 0.8, 0.8)`
|
||||
- Funktionen: `_setup_weapon_attachment()`, `_attach_weapon_model()`, `_remove_weapon_model()`
|
||||
|
||||
### Character Panel (character_panel.gd, C-Taste)
|
||||
Zeigt zwei Spalten:
|
||||
- **Stats-Spalte:** Stärke, Beweglichkeit, Intelligenz, Ausdauer, Rüstung, HP
|
||||
|
|
|
|||
BIN
assets/Weapons/medieval_sword.glb
Normal file
BIN
assets/Weapons/medieval_sword.glb
Normal file
Binary file not shown.
42
assets/Weapons/medieval_sword.glb.import
Normal file
42
assets/Weapons/medieval_sword.glb.import
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
[remap]
|
||||
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://8klqbvdg43b3"
|
||||
path="res://.godot/imported/medieval_sword.glb-6bd5ad7fbf20317ed64b8bc381ee05fb.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/Weapons/medieval_sword.glb"
|
||||
dest_files=["res://.godot/imported/medieval_sword.glb-6bd5ad7fbf20317ed64b8bc381ee05fb.scn"]
|
||||
|
||||
[params]
|
||||
|
||||
nodes/root_type=""
|
||||
nodes/root_name=""
|
||||
nodes/root_script=null
|
||||
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=false
|
||||
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={}
|
||||
gltf/naming_version=2
|
||||
gltf/embedded_image_handling=1
|
||||
BIN
assets/Weapons/medieval_sword_0.jpg
Normal file
BIN
assets/Weapons/medieval_sword_0.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 362 KiB |
44
assets/Weapons/medieval_sword_0.jpg.import
Normal file
44
assets/Weapons/medieval_sword_0.jpg.import
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cr8svhu2algti"
|
||||
path.s3tc="res://.godot/imported/medieval_sword_0.jpg-94723da2994d60d5619ffcd032251761.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={
|
||||
"md5": "e8adc51a863b1e90561d52d69ad93bfc"
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/Weapons/medieval_sword_0.jpg"
|
||||
dest_files=["res://.godot/imported/medieval_sword_0.jpg-94723da2994d60d5619ffcd032251761.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
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
|
||||
BIN
assets/Weapons/medieval_sword_1.png
Normal file
BIN
assets/Weapons/medieval_sword_1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 476 KiB |
44
assets/Weapons/medieval_sword_1.png.import
Normal file
44
assets/Weapons/medieval_sword_1.png.import
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://51b8qklemnky"
|
||||
path.s3tc="res://.godot/imported/medieval_sword_1.png-a07317cea2a7cf66dc265905e26d7546.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={
|
||||
"md5": "694b37b7841572959ed4f217aef8380f"
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/Weapons/medieval_sword_1.png"
|
||||
dest_files=["res://.godot/imported/medieval_sword_1.png-a07317cea2a7cf66dc265905e26d7546.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
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=8
|
||||
roughness/src_normal="res://assets/Weapons/medieval_sword_2.jpg"
|
||||
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
|
||||
BIN
assets/Weapons/medieval_sword_2.jpg
Normal file
BIN
assets/Weapons/medieval_sword_2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 589 KiB |
44
assets/Weapons/medieval_sword_2.jpg.import
Normal file
44
assets/Weapons/medieval_sword_2.jpg.import
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dwb4r1domnogc"
|
||||
path.s3tc="res://.godot/imported/medieval_sword_2.jpg-5b274ce8d251c67b5d49b4af74f182a1.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
generator_parameters={
|
||||
"md5": "c9583464c97ca6ecfbb32b19e1fa9180"
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/Weapons/medieval_sword_2.jpg"
|
||||
dest_files=["res://.godot/imported/medieval_sword_2.jpg-5b274ce8d251c67b5d49b4af74f182a1.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=1
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=1
|
||||
roughness/src_normal="res://assets/Weapons/medieval_sword_2.jpg"
|
||||
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
|
||||
|
|
@ -38,6 +38,9 @@ enum Rarity {
|
|||
@export var attack_speed: float = 1.5 # Sekunden zwischen Angriffen
|
||||
@export var weapon_range: float = 3.0
|
||||
|
||||
# 3D-Modell (GLB/GLTF) – wird an der Hand des Spielers angezeigt
|
||||
@export var model_scene: PackedScene
|
||||
|
||||
# Icon für UI
|
||||
@export var icon: Texture2D
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
[gd_resource type="Resource" script_class="Equipment" format=3 uid="uid://vprfv2phlcbc"]
|
||||
[gd_resource type="Resource" script_class="Equipment" load_steps=4 format=3 uid="uid://vprfv2phlcbc"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://re0xiie1udfq" path="res://equipment.gd" id="1_equipment"]
|
||||
[ext_resource type="Texture2D" uid="uid://bi7sh66txlj1c" path="res://icons/iron_sword_icon.svg" id="2_icon"]
|
||||
[ext_resource type="PackedScene" uid="uid://8klqbvdg43b3" path="res://assets/Weapons/medieval_sword.glb" id="3_model"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_equipment")
|
||||
|
|
@ -9,4 +10,5 @@ item_name = "Eisenschwert"
|
|||
strength = 2
|
||||
min_damage = 3
|
||||
max_damage = 6
|
||||
model_scene = ExtResource("3_model")
|
||||
icon = ExtResource("2_icon")
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
[gd_resource type="Resource" script_class="Equipment" load_steps=3 format=3]
|
||||
[gd_resource type="Resource" script_class="Equipment" load_steps=4 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://equipment.gd" id="1_equipment"]
|
||||
[ext_resource type="Texture2D" path="res://icons/steel_sword_icon.svg" id="2_icon"]
|
||||
[ext_resource type="PackedScene" uid="uid://8klqbvdg43b3" path="res://assets/Weapons/medieval_sword.glb" id="3_model"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_equipment")
|
||||
|
|
@ -17,4 +18,5 @@ min_damage = 5
|
|||
max_damage = 9
|
||||
attack_speed = 1.4
|
||||
weapon_range = 3.0
|
||||
model_scene = ExtResource("3_model")
|
||||
icon = ExtResource("2_icon")
|
||||
|
|
|
|||
51
player.gd
51
player.gd
|
|
@ -141,6 +141,9 @@ var target = null # Aktuell markierter Gegner
|
|||
# ═══════════════════════════════════════════════════════════════
|
||||
|
||||
var anim_player: AnimationPlayer = null
|
||||
var skeleton: Skeleton3D = null
|
||||
var weapon_attachment: BoneAttachment3D = null
|
||||
var current_weapon_model: Node3D = null
|
||||
var is_attacking: bool = false
|
||||
var is_dead: bool = false
|
||||
var is_walking: bool = false
|
||||
|
|
@ -346,6 +349,9 @@ func equip_item(item: Equipment) -> Equipment:
|
|||
hud.update_resource(current_resource, max_resource, get_resource_name())
|
||||
if character_panel and character_panel.panel_visible:
|
||||
character_panel.update_stats(self)
|
||||
# Waffen-Modell aktualisieren
|
||||
if slot == Equipment.Slot.WEAPON and weapon_attachment != null:
|
||||
_attach_weapon_model(item)
|
||||
return old_item
|
||||
|
||||
func get_equipped_weapon() -> Equipment:
|
||||
|
|
@ -752,6 +758,51 @@ func _setup_animations():
|
|||
|
||||
_play_anim("idle")
|
||||
|
||||
# Waffen-Attachment einrichten
|
||||
_setup_weapon_attachment()
|
||||
|
||||
func _setup_weapon_attachment():
|
||||
if model == null:
|
||||
print("Player Weapon: Kein Model!")
|
||||
return
|
||||
skeleton = model.find_child("Skeleton3D", true, false) as Skeleton3D
|
||||
if skeleton == null:
|
||||
push_warning("Player: Kein Skeleton3D gefunden!")
|
||||
return
|
||||
# Alle Bones auflisten zum Debuggen
|
||||
print("Player Bones: ", skeleton.get_bone_count())
|
||||
for i in range(skeleton.get_bone_count()):
|
||||
if "Hand" in skeleton.get_bone_name(i) or "hand" in skeleton.get_bone_name(i):
|
||||
print(" Bone ", i, ": ", skeleton.get_bone_name(i))
|
||||
var bone_idx = skeleton.find_bone("mixamorig_RightHand")
|
||||
if bone_idx == -1:
|
||||
push_warning("Player: Bone 'mixamorig_RightHand' nicht gefunden!")
|
||||
return
|
||||
print("Player Weapon: RightHand Bone gefunden (idx=", bone_idx, ")")
|
||||
weapon_attachment = BoneAttachment3D.new()
|
||||
weapon_attachment.bone_name = "mixamorig_RightHand"
|
||||
skeleton.add_child(weapon_attachment)
|
||||
|
||||
func _attach_weapon_model(weapon: Equipment):
|
||||
_remove_weapon_model()
|
||||
if weapon == null or weapon.model_scene == null:
|
||||
print("Player Weapon: Kein Model an Waffe! model_scene=", weapon.model_scene if weapon else "null")
|
||||
return
|
||||
if weapon_attachment == null:
|
||||
print("Player Weapon: Kein weapon_attachment!")
|
||||
return
|
||||
current_weapon_model = weapon.model_scene.instantiate()
|
||||
current_weapon_model.rotation_degrees = Vector3(90, 180, 0)
|
||||
current_weapon_model.position = Vector3(0.5, 0.2, 0)
|
||||
current_weapon_model.scale = Vector3(0.8, 0.8, 0.8)
|
||||
weapon_attachment.add_child(current_weapon_model)
|
||||
print("Player Weapon: Schwert angehängt! Scale=", current_weapon_model.scale)
|
||||
|
||||
func _remove_weapon_model():
|
||||
if current_weapon_model != null and is_instance_valid(current_weapon_model):
|
||||
current_weapon_model.queue_free()
|
||||
current_weapon_model = null
|
||||
|
||||
func _load_anim_from_fbx(fbx_path: String, anim_name: String, loop: bool = false):
|
||||
var scene = load(fbx_path)
|
||||
if scene == null:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue