Godot Version
4.2
Question
I have a charactherBody3d with another one inside. When a certain trigger is touched, the first one activates the second charactherbody. somehow, it is not moving. I have another enemy with similar mechanics, and that one works. Can anyone help me?
Trigger code:
# File path: res://path/to/your/script.gd
extends CharacterBody3D
# Variables
var player = null
var state_machine
var fall_angle = 0.0
var health = 14
const SPEED = 6.5
var ATTACK_RANGE = 7.0
const FALL_SPEED = -12 # Degrees per second
@onready var mesh = $Knifethrower/JUDGEMENT/Skeleton3D
@export var player_path: NodePath
@onready var nav_agent = $NavigationAgent3D
@onready var anim_tree = $Knifethrower/anim
@onready var hurtbox = $Knifethrower/hurtbox # Ensure this is the correct path to your Area3D node
@onready var animplayer = $Knifethrower/AnimationPlayer
var HasKnives = true
var HasShot = false
var HasSword = false
var hurt
var istakingdamage = false
var stall = false
@onready var raycast = $Knifethrower/hurt # Ensure you have a RayCast3D node in the scene and set its path here
var next_nav_point
@onready var area = false
var can_dash = false
var blade = preload("res://railcannon_shot.tscn")
var bodycheck = false
# Ready function: Initializes the script
func _ready():
player = get_node(player_path)
state_machine = anim_tree.get("parameters/playback")
add_to_group("enemy")
print("Enemy added to 'enemy' group")
hide()
# Connect the hitbox signal
if hurtbox and hurtbox.has_signal("body_entered"):
# Disconnect the signal if it is already connected
if hurtbox.is_connected("body_entered", Callable(self, "_on_hurtbox_body_entered")):
hurtbox.disconnect("body_entered", Callable(self, "_on_hurtbox_body_entered"))
hurtbox.connect("body_entered", Callable(self, "_on_hurtbox_body_entered"))
# Ensure the RayCast is found and enabled
if raycast:
raycast.enabled = true
else:
print("RayCast3D node not found")
# Connect the animation finished signal to a handler function
animplayer.connect("animation_finished", Callable(self, "_on_animation_player_animation_finished"))
# Process function: Main game loop
func _process(delta):
velocity.y -= FALL_SPEED * delta
if not istakingdamage:
anim_tree.set("parameters/conditions/TakeDamage", false)
if istakingdamage:
anim_tree.set("parameters/conditions/TakeDamage", true)
if raycast.is_colliding():
hurt = raycast.get_collider()
if hurt:
if hurt.is_in_group("aoe"):
die(5)
print("herng")
velocity = Vector3.ZERO
match state_machine.get_current_node():
"Despawn":
if not bodycheck:
bodycheck = true
# Navigation
$Knifethrower.hide()
$Knifethrower/Chkn1_casing.set_as_top_level(true)
$Knifethrower_main.activate()
$CollisionShape3D.disabled = true
# Apply velocity to the character
self.velocity = velocity
move_and_slide()
# Shooting knives
func shoot_the_knife_right():
var w2 = get_tree().get_root()
var projectile
var randomrotate = 0
var r2 = blade.instantiate()
w2.add_child(r2)
r2.global_transform.origin = $Knifethrower/JUDGEMENT/Skeleton3D/rightblasde.global_transform.origin
r2.look_at(player.global_transform.origin, Vector3(0, 1, 0))
func shoot_the_knife_left():
var w2 = get_tree().get_root()
var projectile
var randomrotate = 0
var r2 = blade.instantiate()
w2.add_child(r2)
r2.global_transform.origin = $Knifethrower/JUDGEMENT/Skeleton3D/leftblade.global_transform.origin
r2.look_at(player.global_transform.origin, Vector3(0, 1, 0))
# Damage handling
func die(damvalue):
print("Knifethrower took damage")
anim_tree.set("parameters/conditions/TakeDamage", true) # Ensure correct parameter
GlobalSignals.emit_signal("explosion_emitter")
istakingdamage = true
health -= damvalue
print("Health:", health)
# Check transition to 'dead' state when health is low
if health < 1:
state_machine.travel("dead")
queue_free()
return # Exit if dead
# Trigger the 'hit' state
state_machine.travel("Chicken_hit")
# Wait before allowing state transition
await get_tree().create_timer(0.4215).timeout
istakingdamage = false
anim_tree.set("parameters/conditions/TakeDamage", false)
# Damage stall effect
func stalll():
stall = true
die(2)
await get_tree().create_timer(0.5).timeout
die(2)
await get_tree().create_timer(0.5).timeout
die(2)
await get_tree().create_timer(0.5).timeout
die(2)
# Range checking functions
func _target_in_range1():
return global_position.distance_to(player.global_position) < ATTACK_RANGE
func _target_in_range2():
var distance = global_position.distance_to(player.global_position)
if ATTACK_RANGE < distance and distance <= ATTACK_RANGE + 10:
return true
return false
func _second_condition_met():
return _target_in_range1()
# Hit handling
func _hit_finished():
pass
# Signal handling for hurtbox
func _on_hurtbox_body_entered(body):
if body.is_in_group("aoe"):
print("aoe connected")
# Animation finished signal handler
func _on_animation_player_animation_finished(anim_name):
print("Animation finished:", anim_name)
if anim_name == "takedamage":
# Transition back to the default state (e.g., "wwkalk")
print("Transitioning back to wwkalk")
state_machine.travel("wwkalk")
anim_tree.set("parameters/conditions/takedamage", false)
istakingdamage = false
elif anim_name == "NEWWW_attack":
ATTACK_RANGE = 7
if _target_in_range1() and _second_condition_met():
print("Transitioning to NEWWW_attack_combo1")
state_machine.travel("NEWWW_attack_combo1")
elif anim_name == "NEWWW_attack_combo1":
ATTACK_RANGE = 2
# Hitbox control
func _starthitbox():
$chkn1/Armature_001/Skeleton3D/Cube_005/Cube_005/Area3D.monitoring = true
$chkn1/Armature_001/Skeleton3D/Cube_005/Cube_005/GPUTrail3D.visible = true
func _endhitbox():
$chkn1/Armature_001/Skeleton3D/Cube_005/Cube_005/Area3D.monitoring = false
$chkn1/Armature_001/Skeleton3D/Cube_005/Cube_005/GPUTrail3D.visible = false
# Dash control
func startdash():
can_dash = true
func enddash():
can_dash = false
# Area3D body entered event
func _on_area_3d_body_entered(body):
print("the")
if body.has_method("hit"):
body.hit()
print("player hit")
func _on_detector_area_entered(area):
if area.is_in_group("player"):
show()
$detector.queue_free()
$detector/CollisionShape3D.queue_free()
anim_tree.set("parameters/conditions/checked", true)
second code: (the one that will be activated)
# File path: res://path/to/your/script.gd
extends CharacterBody3D
# Variables
var player = null
var state_machine
var fall_angle = 0.0
var health = 14
const SPEED = 6.5
var ATTACK_RANGE = 7.0
const FALL_SPEED = 12 # Degrees per second
@onready var mesh = $Knifethrower/JUDGEMENT/Skeleton3D
@export var player_path: NodePath
@onready var nav_agent = $NavigationAgent3D
@onready var anim_tree = $Knifethrower/anim
@onready var hurtbox = $Knifethrower/hurtbox # Ensure this is the correct path to your Area3D node
@onready var animplayer = $Knifethrower/AnimationPlayer
var HasKnives = true
var HasShot = false
var HasSword = false
var hurt
var istakingdamage = false
var stall = false
@onready var raycast = $Knifethrower/hurt # Ensure you have a RayCast3D node in the scene and set its path here
var next_nav_point
@onready var area = false
var can_dash = false
var blade = preload("res://railcannon_shot.tscn")
var activation = false
# Ready function: Initializes the script
func _ready():
hide()
player = get_node(player_path)
state_machine = anim_tree.get("parameters/playback")
add_to_group("enemy")
print("Enemy added to 'enemy' group")
if state_machine:
print("State machine found")
# Connect the hitbox signal
if hurtbox and hurtbox.has_signal("body_entered"):
if hurtbox.is_connected("body_entered", Callable(self, "_on_hurtbox_body_entered")):
hurtbox.disconnect("body_entered", Callable(self, "_on_hurtbox_body_entered"))
hurtbox.connect("body_entered", Callable(self, "_on_hurtbox_body_entered"))
if raycast:
raycast.enabled = true
else:
print("RayCast3D node not found")
animplayer.connect("animation_finished", Callable(self, "_on_animation_player_animation_finished"))
# Process function: Main game loop
func _process(delta):
if activation:
velocity.y -= FALL_SPEED * delta
if not istakingdamage:
anim_tree.set("parameters/conditions/TakeDamage", false)
else:
anim_tree.set("parameters/conditions/TakeDamage", true)
if raycast.is_colliding():
hurt = raycast.get_collider()
if hurt and hurt.is_in_group("aoe"):
die(5)
print("herng")
# State Machine and Movement Handling
match state_machine.get_current_node():
"Chicken_run":
# Navigation
nav_agent.set_target_position(player.global_transform.origin)
next_nav_point = nav_agent.get_next_path_position()
velocity.x = (next_nav_point.x - global_transform.origin.x) * SPEED * delta * 20
velocity.z = (next_nav_point.z - global_transform.origin.z) * SPEED * delta * 20
rotation.y = lerp_angle(rotation.y, atan2(-velocity.x, -velocity.z), delta * 20.0)
print("Knifethrower: current state is running", velocity, next_nav_point, player.global_transform.origin)
"Chicken_sword_attack":
HasSword = false
nav_agent.set_target_position(player.global_transform.origin)
next_nav_point = nav_agent.get_next_path_position()
velocity.x = (next_nav_point.x - global_transform.origin.x) * SPEED * delta
velocity.z = (next_nav_point.z - global_transform.origin.z) * SPEED * delta
rotation.y = lerp_angle(rotation.y, atan2(-velocity.x, -velocity.z), delta * 1.3)
print("Knifethrower: current state is sword attacking")
"Chicken_hit":
velocity.x = (next_nav_point.x - global_transform.origin.x) * SPEED * delta * 20
velocity.z = (next_nav_point.z - global_transform.origin.z) * SPEED * delta * 20
print("Knifethrower: current state is taking damage")
"Chicken_unsheath_knives":
velocity = Vector3.ZERO
HasKnives = true
HasShot = false
print("Knifethrower: current state is unsheathing knives")
"Chicken_knife_run_and_throw":
HasShot = true
HasKnives = false
nav_agent.set_target_position(player.global_transform.origin)
next_nav_point = nav_agent.get_next_path_position()
velocity.x = (next_nav_point.x - global_transform.origin.x) * SPEED * delta * 20
velocity.z = (next_nav_point.z - global_transform.origin.z) * SPEED * delta * 20
rotation.y = lerp_angle(rotation.y, atan2(-velocity.x, -velocity.z), delta * 5.0)
print("Knifethrower: current state is throwing knives")
"Chicken_run_and_sword":
HasKnives = true
HasSword = true
nav_agent.set_target_position(player.global_transform.origin)
next_nav_point = nav_agent.get_next_path_position()
velocity.x = (next_nav_point.x - global_transform.origin.x) * SPEED * delta * 20
velocity.z = (next_nav_point.z - global_transform.origin.z) * SPEED * delta * 20
rotation.y = lerp_angle(rotation.y, atan2(-velocity.x, -velocity.z), delta * 2.0)
print("Knifethrower: current state is taking out sword")
# Conditions
anim_tree.set("parameters/conditions/WithinRange(unsheath)", _target_in_range2() and HasKnives)
anim_tree.set("parameters/conditions/WithinRange(shoot)", not _target_in_range1() and HasKnives)
anim_tree.set("parameters/conditions/CanSword", _target_in_range1())
anim_tree.set("parameters/conditions/CanSwordAttack", _target_in_range1())
anim_tree.set("parameters/conditions/Move", not _target_in_range1() or not _target_in_range2())
anim_tree.set("parameters/conditions/Reload", _target_in_range2() and not HasKnives and HasShot)
anim_tree.set("parameters/conditions/TargetNotRange", not _target_in_range1())
anim_tree.set("parameters/conditions/TargetNotRange(knife)", not _target_in_range1() and HasSword)
# Apply velocity to the character and reset after movement calculations
move_and_slide()
velocity = Vector3.ZERO
# Shooting knives
func shoot_the_knife_right():
var w2 = get_tree().get_root()
var projectile
var randomrotate = 0
var r2 = blade.instantiate()
w2.add_child(r2)
r2.global_transform.origin = $Knifethrower/JUDGEMENT/Skeleton3D/rightblasde.global_transform.origin
r2.look_at(player.global_transform.origin, Vector3(0, 1, 0))
func activate():
show()
activation = true
func shoot_the_knife_left():
var w2 = get_tree().get_root()
var projectile
var randomrotate = 0
var r2 = blade.instantiate()
w2.add_child(r2)
r2.global_transform.origin = $Knifethrower/JUDGEMENT/Skeleton3D/leftblade.global_transform.origin
r2.look_at(player.global_transform.origin, Vector3(0, 1, 0))
# Damage handling
func die(damvalue):
print("Knifethrower took damage")
anim_tree.set("parameters/conditions/TakeDamage", true) # Ensure correct parameter
GlobalSignals.emit_signal("explosion_emitter")
istakingdamage = true
health -= damvalue
print("Health:", health)
# Check transition to 'dead' state when health is low
if health < 1:
state_machine.travel("dead")
queue_free()
return # Exit if dead
# Trigger the 'hit' state
state_machine.travel("Chicken_hit")
# Wait before allowing state transition
await get_tree().create_timer(0.4215).timeout
istakingdamage = false
anim_tree.set("parameters/conditions/TakeDamage", false)
# Damage stall effect
func stalll():
stall = true
die(2)
await get_tree().create_timer(0.5).timeout
die(2)
await get_tree().create_timer(0.5).timeout
die(2)
await get_tree().create_timer(0.5).timeout
die(2)
# Range checking functions
func _target_in_range1():
return global_position.distance_to(player.global_position) < ATTACK_RANGE
func _target_in_range2():
var distance = global_position.distance_to(player.global_position)
if ATTACK_RANGE < distance and distance <= ATTACK_RANGE + 10:
return true
return false
func _second_condition_met():
return _target_in_range1()
# Hit handling
func _hit_finished():
pass
# Signal handling for hurtbox
func _on_hurtbox_body_entered(body):
if body.is_in_group("aoe"):
print("aoe connected")
# Animation finished signal handler
func _on_animation_player_animation_finished(anim_name):
print("Animation finished:", anim_name)
if anim_name == "takedamage":
# Transition back to the default state (e.g., "wwkalk")
print("Transitioning back to wwkalk")
state_machine.travel("wwkalk")
anim_tree.set("parameters/conditions/takedamage", false)
istakingdamage = false
elif anim_name == "NEWWW_attack":
ATTACK_RANGE = 7
if _target_in_range1() and _second_condition_met():
print("Transitioning to NEWWW_attack_combo1")
state_machine.travel("NEWWW_attack_combo1")
elif anim_name == "NEWWW_attack_combo1":
ATTACK_RANGE = 2
# Hitbox control
func _starthitbox():
$chkn1/Armature_001/Skeleton3D/Cube_005/Cube_005/Area3D.monitoring = true
$chkn1/Armature_001/Skeleton3D/Cube_005/Cube_005/GPUTrail3D.visible = true
func _endhitbox():
$chkn1/Armature_001/Skeleton3D/Cube_005/Cube_005/Area3D.monitoring = false
$chkn1/Armature_001/Skeleton3D/Cube_005/Cube_005/GPUTrail3D.visible = false
# Dash control
func startdash():
can_dash = true
func enddash():
can_dash = false
# Area3D body entered event
func _on_area_3d_body_entered(body):
print("the")
if body.has_method("hit"):
body.hit()
print("player hit")
Node setup:
scene: