CanvasLayer: интерфейс независимо от камеры
Отделить HUD от мира и понять, почему ZIndex не заменяет номер слоя.
Создать отдельный canvas для HUD
В полном примере CanvasExample создаёт мир с Camera2D и отдельный CanvasLayer. Синий маркер HUD находится в (24,24) его canvas. FollowViewportEnabled=false отключает следование за canvas мира. Перемещение камеры меняет изображение мира, а HUD сохраняет место в Viewport.
CanvasExample.cs
using Reckfell;
public partial class CanvasExample : Entity2D
{
public Entity2D Rig { get; private set; } = null!;
public LocalMarker Marker { get; private set; } = null!;
public Camera2D Camera { get; private set; } = null!;
public CanvasLayer Hud { get; private set; } = null!;
public LocalMarker HudMarker { get; private set; } = null!;
public override void _Ready()
{
Rig = new Entity2D { Position = new Vector2(64, 48) };
AddChild(Rig);
Marker = new LocalMarker { Position = new Vector2(24, 0) };
Rig.AddChild(Marker);
Camera = new Camera2D { Position = new Vector2(160, 120) };
AddChild(Camera);
Camera.MakeCurrent();
Hud = new CanvasLayer { Layer = 1, FollowViewportEnabled = false };
AddChild(Hud);
HudMarker = new LocalMarker { Position = new Vector2(24, 24) };
HudMarker.SetStyle(8, new Color(0.25f, 0.45f, 1));
Hud.AddChild(HudMarker);
var label = new Label { Position = new Vector2(42, 12), Text = "HUD" };
Hud.AddChild(label);
}
public override void _UnhandledInput(InputEvent input)
{
if (input is InputEventMouseButton { Pressed: true, ButtonIndex: MouseButton.Left })
Marker.Position = Rig.ToLocal(Rig.GetGlobalMousePosition());
}
}Для запуска также нужен LocalMarker.cs из полного примера. Прикрепляйте CanvasExample.cs к Entity2D, а не к CanvasLayer. Скрипт сам создаёт слой и дочерние элементы; второй ручной слой не требуется.
Различать порядок и трансформацию
| Настройка | Назначение |
|---|---|
| CanvasLayer.Layer | Порядок canvas относительно других слоёв |
| CanvasItem.ZIndex | Порядок элементов внутри соответствующего canvas |
| CanvasLayer.Offset, Rotation, Scale | Трансформация слоя |
| FollowViewportEnabled | Следование за canvas мира для эффектов вроде параллакса |
Обычный мир отображается на слое 0. В примере HUD использует Layer=1, поэтому рисуется поверх него. Больший ZIndex объекта мира не переносит его поверх отдельного canvas с большим Layer. Не полагайтесь на случайный порядок нескольких CanvasLayer с одинаковым номером: назначайте явные разные номера, если порядок существенен.
TopLevel решает другую задачу: отключает наследование трансформации родительского CanvasItem. Он не создаёт независимый слой HUD. CanvasLayer — Entity для организации canvas, а не прямоугольник Control и не система anchors.
Что слой не делает автоматически
HUD в координатах Viewport ещё не означает готовую адаптивную вёрстку. Для меню применяйте Control, anchors и контейнеры; отдельно задавайте растяжение и размеры Viewport. Постоянный размер здесь относится к движению камеры, а не к одинаковому физическому размеру на всех дисплеях.
CanvasLayer не является изолированным маршрутизатором ввода. Control может перехватить событие до _UnhandledInput. В примере перенос метки происходит только для необработанного щелчка. Для нескольких окон или SubViewport явно выбирайте целевой Viewport; не считайте один HUD автоматически общим для всех.
Быстрая диагностика
- HUD уезжает за камерой: проверьте его принадлежность CanvasLayer и FollowViewportEnabled.
- HUD перекрывается миром: проверьте Layer; ZIndex в другом canvas не решит проблему.
- Метка сохраняет координату, но окно меняет компоновку: нужны правила Control и растяжения.
- Курсор мира ошибается после добавления HUD: берите позицию мыши через CanvasItem нужного canvas.