extends Camera3D ## ターゲットとなるNode3Dオブジェクト @export var target: Node3D ## カメラの回転感度 @export var mouse_sensitivity: float = 0.003 ## ターゲットからの距離 @export var distance: float = 5.0 ## 最小・最大距離 @export var min_distance: float = 2.0 @export var max_distance: float = 20.0 ## ズーム速度 @export var zoom_speed: float = 0.5 ## 縦方向の回転制限(ラジアン) @export var min_pitch: float = -PI / 2 + 0.1 @export var max_pitch: float = PI / 2 - 0.1 ## マウスボタン(右クリックでカメラ操作) @export var rotate_button: MouseButton = MOUSE_BUTTON_RIGHT # 内部変数 var _yaw: float = 0.0 # 水平回転 var _pitch: float = 0.0 # 垂直回転 var _is_rotating: bool = false func _ready() -> void: # 初期角度を設定 if target: var direction = global_position - target.global_position _yaw = atan2(direction.x, direction.z) _pitch = asin(direction.y / direction.length()) func _unhandled_input(event: InputEvent) -> void: # マウスボタンの押下/離す if event is InputEventMouseButton: if event.button_index == rotate_button: _is_rotating = event.pressed # マウスホイールでズーム elif event.button_index == MOUSE_BUTTON_WHEEL_UP: distance = clamp(distance - zoom_speed, min_distance, max_distance) elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN: distance = clamp(distance + zoom_speed, min_distance, max_distance) # マウス移動で回転 elif event is InputEventMouseMotion and _is_rotating: _yaw -= event.relative.x * mouse_sensitivity _pitch += event.relative.y * mouse_sensitivity _pitch = clamp(_pitch, min_pitch, max_pitch) func _process(_delta: float) -> void: if not target: return # 球面座標系でカメラ位置を計算 var offset = Vector3( cos(_pitch) * sin(_yaw), sin(_pitch), cos(_pitch) * cos(_yaw) ) * distance # カメラ位置を設定 global_position = target.global_position + offset # ターゲットを見る look_at(target.global_position, Vector3.UP)