55 lines
1.5 KiB
GDScript
55 lines
1.5 KiB
GDScript
class_name PlayerPickup
|
|
extends Node
|
|
## 拾取组件:射线看中的 RigidBody3D 会被吸附到 InteractionPos 前。
|
|
## 只管「拿 / 放 / 拖」,不碰移动与视角。
|
|
##
|
|
## 接法:Player 下挂一个普通 Node,脚本挂上去;由 Player._ready() 注入射线与持握点。
|
|
|
|
## 拖拽力度:物体被拉向持握点的速度系数
|
|
@export var pick_power: float = 10.0
|
|
|
|
var _current: RigidBody3D = null
|
|
var _ray: RayCast3D
|
|
var _hold_pos: Marker3D
|
|
|
|
|
|
## 由 Player 在 _ready() 注入依赖。
|
|
func setup(ray: RayCast3D, hold_pos: Marker3D) -> void:
|
|
_ray = ray
|
|
_hold_pos = hold_pos
|
|
|
|
|
|
func _unhandled_input(event: InputEvent) -> void:
|
|
if event.is_action_pressed("carry"):
|
|
if _current == null:
|
|
_pick()
|
|
else:
|
|
_release()
|
|
|
|
|
|
## 每物理帧由 Player 调用一次,排在 move_and_slide() 之后。
|
|
## 用速度把物体拽向持握点,而不是直接改 global_position ——
|
|
## 这样它仍会和场景里其他刚体正常碰撞,不会被硬塞进墙里。
|
|
func physics_step() -> void:
|
|
if _current == null or _hold_pos == null:
|
|
return
|
|
var to_hold := _hold_pos.global_position - _current.global_position
|
|
_current.set_linear_velocity(to_hold * pick_power)
|
|
|
|
|
|
func _pick() -> void:
|
|
if _ray == null:
|
|
return
|
|
var collider := _ray.get_collider()
|
|
if collider is RigidBody3D:
|
|
_current = collider as RigidBody3D
|
|
|
|
|
|
func _release() -> void:
|
|
_current = null
|
|
|
|
|
|
## 当前是否抓着东西。调试用,也方便以后加「搬运时不能开枪」这类规则。
|
|
func has_object() -> bool:
|
|
return _current != null
|