相机系统更新

This commit is contained in:
RedisTKey 2026-01-08 22:39:39 +08:00
parent 0c9376baa2
commit d296b96d9b
17 changed files with 232 additions and 102 deletions

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1767878611929" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4918" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M426.666667 298.666667v85.333333H256v341.333333h512V384h-170.666667V298.666667h-170.666666zM341.333333 298.666667V213.333333h341.333334v85.333334h170.666666v512H170.666667V298.666667h170.666666z m170.666667 384c-72.533333 0-128-55.466667-128-128s55.466667-128 128-128 128 55.466667 128 128-55.466667 128-128 128z m0-85.333334c25.6 0 42.666667-17.066667 42.666667-42.666666s-17.066667-42.666667-42.666667-42.666667-42.666667 17.066667-42.666667 42.666667 17.066667 42.666667 42.666667 42.666666z" fill="#8da5f3" p-id="4919"></path></svg>

After

Width:  |  Height:  |  Size: 869 B

View File

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bsdmq0essfmpk"
path="res://.godot/imported/camera_anchor_icon.svg-bc0c9f7b183031f0db701d2e858a9063.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://_asset/icon/camera_anchor_icon.svg"
dest_files=["res://.godot/imported/camera_anchor_icon.svg-bc0c9f7b183031f0db701d2e858a9063.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@ -1,8 +1,6 @@
extends Node2D extends Node2D
func _ready() -> void: func _ready() -> void:
CameraSystem.register_player_camera(self)
$L1_S1.switch_act_by_id(1) $L1_S1.switch_act_by_id(1)
get_tree().call_group(&"PLAYER_RESPAWN",&"respawn_avatar") get_tree().call_group(&"PLAYER_RESPAWN",&"respawn_avatar")

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=41 format=3 uid="uid://gwhff4qaouxy"] [gd_scene load_steps=37 format=3 uid="uid://gwhff4qaouxy"]
[ext_resource type="Script" uid="uid://dq1g1qp66chwy" path="res://_player/avatar.gd" id="1_rkqpu"] [ext_resource type="Script" uid="uid://dq1g1qp66chwy" path="res://_player/avatar.gd" id="1_rkqpu"]
[ext_resource type="Script" uid="uid://isu8onknb75o" path="res://_player/states/character_state_machine.gd" id="1_wvs5h"] [ext_resource type="Script" uid="uid://isu8onknb75o" path="res://_player/states/character_state_machine.gd" id="1_wvs5h"]
@ -23,7 +23,6 @@
[ext_resource type="Script" uid="uid://ca88urm45gx2c" path="res://_player/states/dead.gd" id="17_5r2pj"] [ext_resource type="Script" uid="uid://ca88urm45gx2c" path="res://_player/states/dead.gd" id="17_5r2pj"]
[ext_resource type="Script" uid="uid://bqrel2r5hcmxk" path="res://_player/states/grapping.gd" id="19_u7cua"] [ext_resource type="Script" uid="uid://bqrel2r5hcmxk" path="res://_player/states/grapping.gd" id="19_u7cua"]
[ext_resource type="PackedScene" uid="uid://blm8q46h3v2im" path="res://addons/reedcomponent/locomotion/wall_detector.tscn" id="20_air0b"] [ext_resource type="PackedScene" uid="uid://blm8q46h3v2im" path="res://addons/reedcomponent/locomotion/wall_detector.tscn" id="20_air0b"]
[ext_resource type="Script" uid="uid://8umksf8e80fw" path="res://addons/phantom_camera/scripts/resources/tween_resource.gd" id="21_5r2pj"]
[ext_resource type="Script" uid="uid://bkkkyugppu7sl" path="res://addons/reedcomponent/grap_hook/spawn_hook_component.gd" id="21_p14kj"] [ext_resource type="Script" uid="uid://bkkkyugppu7sl" path="res://addons/reedcomponent/grap_hook/spawn_hook_component.gd" id="21_p14kj"]
[ext_resource type="Script" uid="uid://ta2r2bc1nrwe" path="res://addons/reedfx/vfx/VFXManager.gd" id="24_mwlgv"] [ext_resource type="Script" uid="uid://ta2r2bc1nrwe" path="res://addons/reedfx/vfx/VFXManager.gd" id="24_mwlgv"]
[ext_resource type="Script" uid="uid://lp1ge1qbyfr3" path="res://addons/reedfx/sfx/SFXManager.gd" id="24_x5g5e"] [ext_resource type="Script" uid="uid://lp1ge1qbyfr3" path="res://addons/reedfx/sfx/SFXManager.gd" id="24_x5g5e"]
@ -33,8 +32,6 @@
[ext_resource type="Resource" uid="uid://do0bnwse614jw" path="res://_player/effect_binding/land_dust.tres" id="26_s5egm"] [ext_resource type="Resource" uid="uid://do0bnwse614jw" path="res://_player/effect_binding/land_dust.tres" id="26_s5egm"]
[ext_resource type="Script" uid="uid://bijoqygv6tncj" path="res://addons/reedcomponent/SingleComponentRemotor.gd" id="28_mxt3b"] [ext_resource type="Script" uid="uid://bijoqygv6tncj" path="res://addons/reedcomponent/SingleComponentRemotor.gd" id="28_mxt3b"]
[ext_resource type="Resource" uid="uid://bdad4yjv1q0uu" path="res://_player/effect_binding/jump_dust.tres" id="30_hquoe"] [ext_resource type="Resource" uid="uid://bdad4yjv1q0uu" path="res://_player/effect_binding/jump_dust.tres" id="30_hquoe"]
[ext_resource type="Script" uid="uid://bhexx6mj1xv3q" path="res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_2d.gd" id="32_u7cua"]
[ext_resource type="Script" uid="uid://bueehfgv5vnc0" path="res://_player/extra/camera_priority_locker.gd" id="34_1a1t3"]
[sub_resource type="CircleShape2D" id="CircleShape2D_1a1t3"] [sub_resource type="CircleShape2D" id="CircleShape2D_1a1t3"]
radius = 3.0 radius = 3.0
@ -46,9 +43,6 @@ size = Vector2(9, 23)
atlas = ExtResource("2_8nsdm") atlas = ExtResource("2_8nsdm")
region = Rect2(9, 22, 13, 26) region = Rect2(9, 22, 13, 26)
[sub_resource type="Resource" id="Resource_1a1t3"]
script = ExtResource("21_5r2pj")
[sub_resource type="RectangleShape2D" id="RectangleShape2D_ogl63"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_ogl63"]
size = Vector2(10, 25) size = Vector2(10, 25)
@ -68,7 +62,7 @@ collision_mask = 4
[node name="CollisionShape2D" type="CollisionShape2D" parent="GroundCompanion"] [node name="CollisionShape2D" type="CollisionShape2D" parent="GroundCompanion"]
shape = SubResource("CircleShape2D_1a1t3") shape = SubResource("CircleShape2D_1a1t3")
debug_color = Color(0, 0.6363917, 0.4093975, 0.41960785) debug_color = Color(0, 0.63529414, 0.40784314, 0.41960785)
[node name="CollisionShape2D" type="CollisionShape2D" parent="."] [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource("RectangleShape2D_qnulu") shape = SubResource("RectangleShape2D_qnulu")
@ -196,17 +190,6 @@ script = ExtResource("24_mwlgv")
bindings = Array[ExtResource("25_s5egm")]([ExtResource("26_s5egm"), ExtResource("30_hquoe")]) bindings = Array[ExtResource("25_s5egm")]([ExtResource("26_s5egm"), ExtResource("30_hquoe")])
metadata/_custom_type_script = "uid://ta2r2bc1nrwe" metadata/_custom_type_script = "uid://ta2r2bc1nrwe"
[node name="PhantomCamera2D" type="Node2D" parent="."]
position = Vector2(50, -75)
script = ExtResource("32_u7cua")
tween_resource = SubResource("Resource_1a1t3")
draw_limits = true
metadata/_custom_type_script = "uid://bhexx6mj1xv3q"
[node name="Locker" type="Node" parent="PhantomCamera2D" node_paths=PackedStringArray("target_camera")]
script = ExtResource("34_1a1t3")
target_camera = NodePath("..")
[node name="HitBox" type="Area2D" parent="."] [node name="HitBox" type="Area2D" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
collision_layer = 0 collision_layer = 0

View File

@ -28,15 +28,15 @@ func _enter() -> void:
if hook_inst: if hook_inst:
var i = hook_inst.get_direction_id() var i = hook_inst.get_direction_id()
if i >= 0: #if i >= 0:
if i == 0 or i == 4: #if i == 0 or i == 4:
CameraSystem.get_cached_camera().emit_hook_touch_shock(0) #CameraSystem.get_cached_camera().emit_hook_touch_shock(0)
elif i == 1 or i == 5: #elif i == 1 or i == 5:
CameraSystem.get_cached_camera().emit_hook_touch_shock(1) #CameraSystem.get_cached_camera().emit_hook_touch_shock(1)
elif i == 2 or i == 6: #elif i == 2 or i == 6:
CameraSystem.get_cached_camera().emit_hook_touch_shock(2) #CameraSystem.get_cached_camera().emit_hook_touch_shock(2)
elif i == 3 or i == 7: #elif i == 3 or i == 7:
CameraSystem.get_cached_camera().emit_hook_touch_shock(3) #CameraSystem.get_cached_camera().emit_hook_touch_shock(3)
if root.grap_hook_state._jump_grace_timer > 0: if root.grap_hook_state._jump_grace_timer > 0:
_hook_to_jump() _hook_to_jump()

View File

@ -0,0 +1,3 @@
[gd_scene format=3 uid="uid://cpbaoqfc2kq80"]
[node name="PathDriveMovePlateform" type="Node2D"]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -78,7 +78,12 @@ script = ExtResource("7_pawhc")
[node name="CameraAnchor" parent="Props" instance=ExtResource("8_x0ktb")] [node name="CameraAnchor" parent="Props" instance=ExtResource("8_x0ktb")]
position = Vector2(1403, -480) position = Vector2(1403, -480)
use_blend = true
zoom = Vector2(0.76, 0.76) zoom = Vector2(0.76, 0.76)
limit_top = -10000000
limit_bottom = 10000000
limit_left = -10000000
limit_right = 10000000
[node name="[Prop_0000]" type="Node" parent="Props/CameraAnchor"] [node name="[Prop_0000]" type="Node" parent="Props/CameraAnchor"]
script = ExtResource("9_03jph") script = ExtResource("9_03jph")

View File

@ -1,28 +1,67 @@
@tool @tool
@icon("uid://bsdmq0essfmpk")
class_name CameraAnchor extends Node2D class_name CameraAnchor extends Node2D
## 该priority不会直接修改Anchor的priority @export_group("Anchor Config")
##该priority不会直接修改Anchor的priority只用作初始化
@export var priority: int = 0 @export var priority: int = 0
##此Anchor是否有效
@export var enabled: bool = true @export var enabled: bool = true
##是否要存在相機過渡時間
@export var use_blend: bool = true
##過度時間
@export var blend_time: float = 0.3 @export var blend_time: float = 0.3
@export_group("Phantom Camera Config") @export_group("Camera Config")
@export_subgroup("Sizing")
@export var zoom: Vector2 = Vector2.ONE: @export var zoom: Vector2 = Vector2.ONE:
set(value): set(value):
zoom = value zoom = value
if Engine.is_editor_hint(): if Engine.is_editor_hint():
queue_redraw() queue_redraw()
@export_subgroup("Limit")
@export var use_camera_limit: bool = false:
set(value):
use_camera_limit = value
if Engine.is_editor_hint():
queue_redraw()
@export var limit_top: int = -10000000:
set(value):
limit_top = value
if Engine.is_editor_hint():
queue_redraw()
@export var limit_bottom: int = 10000000:
set(value):
limit_bottom = value
if Engine.is_editor_hint():
queue_redraw()
@export var limit_left: int = -10000000:
set(value):
limit_left = value
if Engine.is_editor_hint():
queue_redraw()
@export var limit_right: int = 10000000:
set(value):
limit_right = value
if Engine.is_editor_hint():
queue_redraw()
@export_subgroup("Follow")
@export var follow_player: bool = false
var _pcam_manager: Node = null var _pcam_manager: Node = null
# =====================================================
# ================ Editor Preview =====================
# =====================================================
## 编辑器预览面板设置 ## 编辑器预览面板设置
@export_group("Editor Preview") @export_group("Editor Preview")
@export var show_frame_preview: bool = true @export var show_camera_preview: bool = true
@export var preview_color: Color = Color(0.2, 0.9, 0.4, 0.8) @export var preview_color: Color = Color(0.2, 0.9, 0.4, 0.8)
@export var preview_line_width: float = 2.0 @export var preview_line_width: float = 2.0
@export var show_limit_preview: bool = true
@export var limit_preview_color: Color = Color(0.9, 0.3, 0.3, 0.8)
@export var limit_preview_line_width: float = 2.0
var _priority: int : var _priority: int :
set(value): set(value):
@ -52,11 +91,8 @@ func _exit_tree() -> void:
func _draw() -> void: func _draw() -> void:
if not Engine.is_editor_hint(): if not Engine.is_editor_hint():
return return
if not show_frame_preview:
return
if not is_instance_valid(_pcam_manager):
return
if show_camera_preview and is_instance_valid(_pcam_manager):
draw_rect( draw_rect(
_camera_frame_rect_like_phantom(), _camera_frame_rect_like_phantom(),
preview_color, preview_color,
@ -64,6 +100,23 @@ func _draw() -> void:
preview_line_width preview_line_width
) )
if show_limit_preview and use_camera_limit:
draw_rect(
_camera_limit_rect(),
limit_preview_color,
false,
limit_preview_line_width
)
func _camera_limit_rect() -> Rect2:
var pos := Vector2(limit_left, limit_top)
var size := Vector2(
limit_right - limit_left,
limit_bottom - limit_top
)
return Rect2(pos, size)
func _camera_frame_rect_like_phantom() -> Rect2: func _camera_frame_rect_like_phantom() -> Rect2:
# PhantomCamera 使用的是 manager.screen_size # PhantomCamera 使用的是 manager.screen_size
var screen_size: Vector2 = _pcam_manager.screen_size var screen_size: Vector2 = _pcam_manager.screen_size

View File

@ -4,3 +4,9 @@
[node name="CameraAnchor" type="Node2D"] [node name="CameraAnchor" type="Node2D"]
script = ExtResource("1_dhu66") script = ExtResource("1_dhu66")
use_blend = null
use_camera_limit = true
limit_top = -10000000.0
limit_bottom = 10000000.0
limit_left = -10000000.0
limit_right = 10000000.0

View File

@ -5,10 +5,12 @@
''' '''
extends Node extends Node
var _cached_player_camera: GlobalCamera @onready var camera_2d: Camera2D = %Camera2D
var _cached_anchors: Array[CameraAnchor] = [] var _cached_anchors: Array[CameraAnchor] = []
var _current_anchor: CameraAnchor var _current_anchor: CameraAnchor
var _switch_tween: Tween var _switch_tween: Tween
var _player_remote: RemoteTransform2D
##标记位,用来检测当前帧是否存在相机切换 ##标记位,用来检测当前帧是否存在相机切换
var _switch_scheduled := false var _switch_scheduled := false
@ -16,23 +18,11 @@ var _dirty := false
## 玩家关卡内静态相机 ## 玩家关卡内静态相机
const PLAYER_CAMERA_SCENE:= preload("res://_shared/camera/PlayerStaticCamera.tscn") const PLAYER_CAMERA_SCENE:= preload("res://_shared/camera/PlayerStaticCamera.tscn")
const CAMERA_FOLLOWER:= preload("res://_shared/camera/camera_follower.tscn")
## 注册玩家相机
func register_player_camera(owner: Node) -> GlobalCamera:
if not _cached_player_camera:
_cached_player_camera = PLAYER_CAMERA_SCENE.instantiate() as GlobalCamera
if _cached_player_camera:
owner.add_child(_cached_player_camera)
return _cached_player_camera
## 外部获取玩家全局相机 ## 外部获取玩家全局相机
func get_cached_camera() -> GlobalCamera: func get_cached_camera() -> Camera2D:
return _cached_player_camera return camera_2d
func get_player_camera() -> GlobalCamera:
return _cached_player_camera
## 注册一个相机锚点 ## 注册一个相机锚点
func register_anchor(anchor: CameraAnchor) -> void: func register_anchor(anchor: CameraAnchor) -> void:
@ -42,20 +32,9 @@ func register_anchor(anchor: CameraAnchor) -> void:
anchor.on_priority_change.connect(on_anchor_priority_changed) anchor.on_priority_change.connect(on_anchor_priority_changed)
_request_evaluate() _request_evaluate()
#if anchor in _cached_anchors:
#return
#_cached_anchors.append(anchor)
#anchor.on_priority_change.connect(on_anchor_priority_changed)
#_sort_anchors()
#_try_auto_switch()
## 当相机锚点的权重改变时,向管理器触发事件 ## 当相机锚点的权重改变时,向管理器触发事件
func on_anchor_priority_changed(priority:int, anchor: CameraAnchor) -> void: func on_anchor_priority_changed(priority:int, anchor: CameraAnchor) -> void:
_request_evaluate() _request_evaluate()
#if _current_anchor:
#if _current_anchor._priority < priority:
#_sort_anchors()
#_try_auto_switch()
## 注销一个相机锚点 ## 注销一个相机锚点
func unregister_anchor(anchor: CameraAnchor) -> void: func unregister_anchor(anchor: CameraAnchor) -> void:
@ -70,7 +49,6 @@ func _request_evaluate() -> void:
return return
_switch_scheduled = true _switch_scheduled = true
call_deferred("_commit_camera_anchor") call_deferred("_commit_camera_anchor")
# call_deferred 会在当前调用栈/本帧末尾idle执行一次
func _commit_camera_anchor() -> void: func _commit_camera_anchor() -> void:
_switch_scheduled = false _switch_scheduled = false
@ -81,24 +59,16 @@ func _commit_camera_anchor() -> void:
# 清理无效 # 清理无效
_cached_anchors = _cached_anchors.filter(func(a): return is_instance_valid(a)) _cached_anchors = _cached_anchors.filter(func(a): return is_instance_valid(a))
# 计算 winner只算一次
var winner: CameraAnchor = _pick_best_anchor() var winner: CameraAnchor = _pick_best_anchor()
# winner 为空就不动(或回默认)
if winner == null: if winner == null:
return return
# 如果没变,不切
if winner == _current_anchor: if winner == _current_anchor:
return return
switch_anchor(winner) switch_anchor(winner)
#_cached_anchors.erase(anchor)
#if _current_anchor == anchor:
#_current_anchor = null
#_try_auto_switch()
func _pick_best_anchor() -> CameraAnchor: func _pick_best_anchor() -> CameraAnchor:
var best: CameraAnchor = null var best: CameraAnchor = null
var best_p := -INF var best_p := -INF
@ -131,25 +101,47 @@ func reset_all_camera_priority() -> void:
for a in _cached_anchors: for a in _cached_anchors:
a._priority = 0 a._priority = 0
##应用Anchor的Limit
func _apply_anchor_limits(anchor: CameraAnchor) -> void:
if not camera_2d:
return
camera_2d.limit_left = anchor.global_position.x + anchor.limit_left
camera_2d.limit_right = anchor.global_position.x + anchor.limit_right
camera_2d.limit_top = anchor.global_position.y + anchor.limit_top
camera_2d.limit_bottom = anchor.global_position.y + anchor.limit_bottom
func _clear_camera_limits() -> void:
if not camera_2d:
return
camera_2d.limit_left = -10000000
camera_2d.limit_right = 10000000
camera_2d.limit_top = -10000000
camera_2d.limit_bottom = 10000000
## 切换相机 ## 切换相机
func switch_anchor(target_anchor: CameraAnchor) -> void: func switch_anchor(target_anchor: CameraAnchor) -> void:
if target_anchor == null: if target_anchor == null:
return return
if target_anchor == _current_anchor: if target_anchor == _current_anchor:
return return
if not is_instance_valid(_cached_player_camera): if not is_instance_valid(camera_2d):
return return
#优先清除已有的remote
if _player_remote:
_player_remote.queue_free()
_player_remote = null
# 中断旧 Tween # 中断旧 Tween
if _switch_tween and _switch_tween.is_running(): if _switch_tween and _switch_tween.is_running():
_switch_tween.kill() _switch_tween.kill()
_switch_tween = null _switch_tween = null
var camera := _cached_player_camera var camera := camera_2d
var p_camera : PhantomCamera2D = _cached_player_camera.phantom_camera_2d
var blend_time : float = max(target_anchor.blend_time, 0.001) var blend_time : float = max(target_anchor.blend_time, 0.001)
# 创建 Tween关键ignore time scale _clear_camera_limits()
_switch_tween = get_tree().create_tween() _switch_tween = get_tree().create_tween()
_switch_tween.set_ignore_time_scale(true) _switch_tween.set_ignore_time_scale(true)
_switch_tween.set_trans(Tween.TRANS_CUBIC) _switch_tween.set_trans(Tween.TRANS_CUBIC)
@ -165,7 +157,7 @@ func switch_anchor(target_anchor: CameraAnchor) -> void:
# ===== Zoom ===== # ===== Zoom =====
_switch_tween.parallel().tween_property( _switch_tween.parallel().tween_property(
p_camera, camera,
"zoom", "zoom",
target_anchor.zoom, target_anchor.zoom,
blend_time * 1.5 blend_time * 1.5
@ -174,6 +166,31 @@ func switch_anchor(target_anchor: CameraAnchor) -> void:
# 完成回调 # 完成回调
_switch_tween.finished.connect(func(): _switch_tween.finished.connect(func():
_current_anchor = target_anchor _current_anchor = target_anchor
_update_anchor_follow_state(target_anchor)
_apply_anchor_limits(target_anchor)
) )
_current_anchor = target_anchor _current_anchor = target_anchor
func _update_anchor_follow_state(anchor: CameraAnchor) -> void:
# 先清理旧的 RemoteTransform
if _player_remote and is_instance_valid(_player_remote):
_player_remote.queue_free()
_player_remote = null
if not anchor.follow_player:
return
var p := GlobalEvent.get_player()
if not p or not is_instance_valid(p):
push_warning("CameraAnchor wants to follow player, but player is not registered.")
return
# 创建 RemoteTransform2D
var rt := RemoteTransform2D.new()
rt.name = "__CameraAnchorFollow"
rt.remote_path = camera_2d.get_path()
p.add_child(rt)
_player_remote = rt

View File

@ -1,15 +1,12 @@
[gd_scene load_steps=3 format=3 uid="uid://b8pv5wtbo0y20"] [gd_scene load_steps=2 format=3 uid="uid://b8pv5wtbo0y20"]
[ext_resource type="Script" uid="uid://04mchxkp161a" path="res://_shared/camera/CameraSystem.gd" id="1_xxnab"] [ext_resource type="Script" uid="uid://04mchxkp161a" path="res://_shared/camera/CameraSystem.gd" id="1_xxnab"]
[ext_resource type="Script" uid="uid://bd046eokvcnu2" path="res://addons/phantom_camera/scripts/phantom_camera_host/phantom_camera_host.gd" id="2_385ly"]
[node name="CameraSystem" type="Node"] [node name="CameraSystem" type="Node"]
script = ExtResource("1_xxnab") script = ExtResource("1_xxnab")
[node name="Camera2D" type="Camera2D" parent="."] [node name="Camera2D" type="Camera2D" parent="."]
unique_name_in_owner = true
[node name="PhantomCameraHost" type="Node" parent="Camera2D"] limit_smoothed = true
process_priority = 300 editor_draw_limits = true
process_physics_priority = 300 editor_draw_drag_margin = true
script = ExtResource("2_385ly")
metadata/_custom_type_script = "uid://bd046eokvcnu2"

View File

@ -0,0 +1,8 @@
extends RemoteTransform2D
func _ready() -> void:
var global_camera: Camera2D = CameraSystem.get_cached_camera()
if not global_camera:
push_error("[CameraFollower]:No Global Camera Founded")
return
remote_path = global_camera.get_path()

View File

@ -0,0 +1 @@
uid://1xtjkoufyjlp

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://bmb1en8itine5"]
[ext_resource type="Script" uid="uid://1xtjkoufyjlp" path="res://_shared/camera/camera_follower.gd" id="1_8rvp5"]
[node name="CameraFollower" type="RemoteTransform2D"]
update_rotation = false
update_scale = false
script = ExtResource("1_8rvp5")