Reputation: 1
This is My Character controller
extends CharacterBody3D
#crosshair
@onready var crosshair = $Head/Camera3D/Crosshair
#rocketman
#gun
var damage = 10
var current_weapon = 1
#gun
@onready var gun_anim = $Head/Camera3D/Hand/Gun1/AnimationPlayer
@onready var gun_anim2 = $Head/Camera3D/Hand/Gun2/AnimationPlayer
@onready var gun_anim3 = $Head/Camera3D/Hand/Gun3/AnimationPlayer
@onready var camera = $Head/Camera3D
@onready var raycast = $Head/Camera3D/RayCast3D
@onready var muzzle = $Head/Camera3D/Hand/lefthand/Hand_Cartoon_Hand/muzzle
@onready var head = $Head
@onready var gun1 = $Head/Camera3D/Hand/Gun1
@onready var gun2 = $Head/Camera3D/Hand/Gun2
@onready var gun3 = $Head/Camera3D/Hand/Gun3
@onready var bullet = preload("res://bullet.tscn")
#jumping
var jump_num = 0
var max_jump_num = 2
# Movement
const MAX_VELOCITY_AIR = 1.0
const MAX_VELOCITY_GROUND = 10.0
const MAX_ACCELERATION = 10 * MAX_VELOCITY_GROUND
const GRAVITY = 15.34
const STOP_SPEED = 1.5
const JUMP_IMPULSE = sqrt(2 * GRAVITY * 0.85)
const PLAYER_WALKING_MULTIPLIER = 0.666
var direction = Vector3()
var friction = 4
var wish_jump
var walking = false
# Camera
var sensitivity = 0.05
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
$bullet.connect("bullet_collision",self,"_on_bullet_collision")
func _on_bullet_collision(body):
var explosion_instance = load("res://explosion.tscn").instantiate()
explosion_instance.global_transform.origin = body.global_transform.origin
get_tree().current_scene.add_child(explosion_instance)
func _input(event):
# Camera rotation
if event is InputEventMouseMotion and Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
_handle_camera_rotation(event)
if event is InputEventMouseButton:
if event.is_pressed():
if event.button_index == MOUSE_BUTTON_WHEEL_UP:
if current_weapon < 3:
current_weapon += 1
else:
current_weapon = 1
if event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
if current_weapon > 1:
current_weapon -= 1
else:
current_weapon = 3
func _handle_camera_rotation(event: InputEvent):
# Rotate the camera based on the mouse movement
rotate_y(deg_to_rad(-event.relative.x * sensitivity))
$Head.rotate_x(deg_to_rad(-event.relative.y * sensitivity))
# Stop the head from rotating to far up or down
$Head.rotation.x = clamp($Head.rotation.x, deg_to_rad(-60), deg_to_rad(90))
func weapon_select():
if Input.is_action_just_pressed("weapon1"):
current_weapon = 1
elif Input.is_action_just_pressed("weapon2"):
current_weapon = 2
elif Input.is_action_just_pressed("weapon3"):
current_weapon = 3
if current_weapon == 1:
gun1.visible = true
else:
gun1.visible = false
if current_weapon == 2:
gun2.visible = true
damage = 100
else:
gun2.visible = false
if current_weapon == 3:
gun3.visible = true
damage = 200
else:
gun3.visible = false
#crosshair
randomize()
crosshair.position.x = get_viewport().size.x / 2 - 32
crosshair.position.y = get_viewport().size.y / 2 - 32
#shootin time
func fire():
if Input.is_action_just_pressed("fire"):
if current_weapon == 1 and !gun_anim.is_playing():
gun_anim.play("PistolFire")
elif current_weapon == 2 and !gun_anim2.is_playing():
gun_anim2.play("PistolFire_2")
elif current_weapon == 3 and !gun_anim3.is_playing():
gun_anim3.play("PistolFire_3")
if raycast.is_colliding():
var target = raycast.get_collider()
if target.is_in_group("Enemy"):
target.health -= damage
func _physics_process(delta):
process_input()
process_movement(delta)
weapon_select()
fire()
func process_input():
direction = Vector3()
# Movement directions
if Input.is_action_pressed("move_forward"):
direction -= transform.basis.z
elif Input.is_action_pressed("move_backward"):
direction += transform.basis.z
if Input.is_action_pressed("move_left"):
direction -= transform.basis.x
elif Input.is_action_pressed("move_right"):
direction += transform.basis.x
# Jumping
wish_jump = Input.is_action_just_pressed("jump")
# Walking
#AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
if Input.is_action_just_pressed("sec_fire"):
if raycast.is_colliding():
var b = bullet.instantiate()
muzzle.add_child(b)
b.look_at(raycast.get_collision_point(), Vector3.UP)
b.shoot = true
func process_movement(delta):
# Get the normalized input direction so that we don't move faster on diagonals
var wish_dir = direction.normalized()
if is_on_floor():
# If wish_jump is true then we won't apply any friction and allow the
# player to jump instantly, this gives us a single frame where we can
# perfectly bunny hop
if wish_jump:
velocity.y = JUMP_IMPULSE
# Update velocity as if we are in the air
velocity = update_velocity_air(wish_dir, delta)
wish_jump = false
else:
if walking:
velocity.x *= PLAYER_WALKING_MULTIPLIER
velocity.z *= PLAYER_WALKING_MULTIPLIER
velocity = update_velocity_ground(wish_dir, delta)
else:
# Only apply gravity while in the air
velocity.y -= GRAVITY * delta
velocity = update_velocity_air(wish_dir, delta)
# Move the player once velocity has been calculated
move_and_slide()
func accelerate(wish_dir: Vector3, max_speed: float, delta):
# Get our current speed as a projection of velocity onto the wish_dir
var current_speed = velocity.dot(wish_dir)
# How much we accelerate is the difference between the max speed and the current speed
# clamped to be between 0 and MAX_ACCELERATION which is intended to stop you from going too fast
var add_speed = clamp(max_speed - current_speed, 0, MAX_ACCELERATION * delta)
return velocity + add_speed * wish_dir
func update_velocity_ground(wish_dir: Vector3, delta):
# Apply friction when on the ground and then accelerate
var speed = velocity.length()
if speed != 0:
var control = max(STOP_SPEED, speed)
var drop = control * friction * delta
# Scale the velocity based on friction
velocity *= max(speed - drop, 0) / speed
return accelerate(wish_dir, MAX_VELOCITY_GROUND, delta)
func update_velocity_air(wish_dir: Vector3, delta):
# Do not apply any friction
return accelerate(wish_dir, MAX_VELOCITY_AIR, delta)
# Apply impulse to the character
func apply_impulse(_position: Vector3, impulse: Vector3):
# Apply the impulse to the character's velocity
velocity += impulse
This is my projectile
extends RigidBody3D
signal bullet_collision
var shoot = false
const DAMAGE = 50
const SPEED = 10
var explosion = preload("res://explosion.tscn")
func _ready():
set_as_top_level(true)
func _physics_process(_delta):
if shoot:
apply_impulse(-transform.basis.z, transform.basis.z)
func _on_body_entered(body):
emit_signal("bullet_collision", body)
queue_free
func _on_area_3d_body_entered(body):
if body.is_in_group("Enemy"):
#smth smth spawn explosion
body.health -= DAMAGE
queue_free()
else:
queue_free()
if body.is_in_group("Player"):
#smth smth spawn explosion
pass
This is my explosion script
extends Area3D
@export var speed = 10.0
func _on_body_entered(body):
var vector = body.global_transform.origin - global_transform.origin
var direction = vector.normalized()
var distance_squared = vector.length_squared()
var velocity = direction * speed/distance_squared
if body.is_in_group("Player"):
body.velocity += velocity
this is my scene for reference enter image description here
Further note: the explosion script comes from a stackoverflow (how do you make rocket jumping in godot) response about rocket jumping.
The difficulties arise when trying to make this part "When the projectile collides with the scenario or another character, you will spawn the explosion scene, and queue_free the projectile"
I've tried with chatgpt, a lot. Most of the time it works and I just need to change around a few things to work. However this time it won't work. this is the response I get:
"The error message indicates that the second argument in the connect() function should be a callable, but you've passed a file path (res://Player-copy.gd). This typically happens when you have an erroneous or incomplete path for the function to connect to.
Ensure that the path is correct, and also make sure the function _on_bullet_collision is properly defined in your script. If it's defined but the error persists, double-check the path you're providing in the connect() function.
If the issue persists, please provide the relevant section of your code where the connect() function is called so I can assist you further."
For reference
And the code block I added from chat gpt is this for the script: Player-copy.gd
$bullet.connect("bullet_collision",self,"_on_bullet_collision")
func _on_bullet_collision(body):
var explosion_instance = load("res://explosion.tscn").instantiate()
explosion_instance.global_transform.origin = body.global_transform.origin
get_tree().current_scene.add_child(explosion_instance)
Upvotes: 0
Views: 63
Reputation: 1729
The problem should be this line:
$bullet.connect("bullet_collision",self,"_on_bullet_collision")
First Problem: The $ does not make sense, because its just a shortcut for get_node. And you do not have a node bullet in your scene as far as I see. So this line should actually be called with a $ nor should it be called on your resource variable "bullet". Instead it should be connected in your process_input function when you create an instance of the bullet.
Second Problem: Looking at your tags i assume your using Godot 4. The syntax for connecting signals have changed from Godot 3 to 4.
To connect correctly to the signal your process_input code should look like this:
#character controller
func process_input():
#other code
...
if Input.is_action_just_pressed("sec_fire"):
if raycast.is_colliding():
var b = bullet.instantiate()
b.bullet_collision.connect(_on_bullet_collision) # connect the signal here
muzzle.add_child(b)
b.look_at(raycast.get_collision_point(), Vector3.UP)
b.shoot = true
if you are not on godot 4 replace the newly added line with:
b.connect("bullet_collision",self,"_on_bullet_collision")
Upvotes: 1