74 lines
2.1 KiB
GDScript
74 lines
2.1 KiB
GDScript
extends RigidBody3D
|
||
|
||
## 移動の基準となるカメラ
|
||
@export var camera: Camera3D
|
||
|
||
## 移動加速度
|
||
@export var move_force: float = 10.0
|
||
|
||
## ジャンプ力
|
||
@export var jump_force: float = 8.0
|
||
|
||
## 空中での移動制御(0.0-1.0、1.0で地上と同じ)
|
||
@export var air_control: float = 0.3
|
||
|
||
## 地面判定用のレイキャスト距離
|
||
@export var ground_check_distance: float = 0.6
|
||
|
||
# 内部変数
|
||
var _is_on_ground: bool = false
|
||
var _ground_check_ray: RayCast3D
|
||
|
||
|
||
func _ready() -> void:
|
||
# 地面判定用のレイキャストを作成
|
||
_ground_check_ray = RayCast3D.new()
|
||
_ground_check_ray.target_position = Vector3(0, -ground_check_distance, 0)
|
||
_ground_check_ray.enabled = true
|
||
add_child(_ground_check_ray)
|
||
|
||
|
||
func _physics_process(delta: float) -> void:
|
||
# レイキャストをグローバル座標系で下向きに固定
|
||
_ground_check_ray.global_rotation = Vector3.ZERO
|
||
|
||
# 地面判定
|
||
_is_on_ground = _ground_check_ray.is_colliding()
|
||
|
||
# 入力取得
|
||
var input_dir = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
|
||
|
||
# カメラ基準の移動方向を計算
|
||
var move_direction = _get_camera_relative_direction(input_dir)
|
||
|
||
# 移動力を適用
|
||
if move_direction.length() > 0:
|
||
var control_factor = air_control if not _is_on_ground else 1.0
|
||
var force = move_direction * move_force * control_factor
|
||
apply_central_force(force)
|
||
|
||
# ジャンプ
|
||
if Input.is_action_just_pressed("ui_accept") and _is_on_ground:
|
||
linear_velocity.y = jump_force
|
||
|
||
|
||
func _get_camera_relative_direction(input_dir: Vector2) -> Vector3:
|
||
|
||
if not camera:
|
||
# カメラが設定されていない場合はワールド座標基準
|
||
return Vector3(input_dir.x, 0, input_dir.y).normalized()
|
||
|
||
# カメラの前方向と右方向を取得(Y軸は無視して水平面に射影)
|
||
var cam_forward = -camera.global_transform.basis.z
|
||
cam_forward.y = 0
|
||
cam_forward = cam_forward.normalized()
|
||
|
||
var cam_right = camera.global_transform.basis.x
|
||
cam_right.y = 0
|
||
cam_right = cam_right.normalized()
|
||
|
||
# 入力方向をカメラ基準に変換
|
||
var direction = (cam_right * input_dir.x + cam_forward * -input_dir.y).normalized()
|
||
|
||
return direction
|