3D: камера как на карте мира, расчистка только в зоне, почта под Наградами, старт с City3D

This commit is contained in:
2026-11-05 17:46:42 +03:00
parent e26eeaffaf
commit 413c627d5c
8 changed files with 86 additions and 50 deletions
+16 -7
View File
@@ -20,7 +20,6 @@ public class City3DCamera : MonoBehaviour
bool focusing;
Vector3 lastPointer;
bool panning;
float lastPinch;
// Перемещение камеры пальцем можно выключить на время перетаскивания здания
public bool AllowPan { get; set; } = true;
@@ -43,6 +42,10 @@ public class City3DCamera : MonoBehaviour
public void BeginPan(Vector3 screen) { panning = AllowPan; lastPointer = screen; focusing = false; }
public void EndPan() { panning = false; }
// Палец ещё не сдвинулся настолько, чтобы считать это перетаскиванием: камера стоит, но точка запоминается --
// когда перетаскивание начнётся, карта не прыгнет (как на карте мира, 05.11)
public void Track(Vector3 screen) { lastPointer = screen; }
public void Pan(Vector3 screen)
{
if (!panning || cam == null) return;
@@ -50,6 +53,7 @@ public class City3DCamera : MonoBehaviour
target += a - b;
lastPointer = screen;
Clamp();
Apply(); // сразу: иначе следующий шаг считался бы от старого положения камеры -- камера дёргалась (05.11)
}
public void Zoom(float delta)
@@ -65,14 +69,19 @@ public class City3DCamera : MonoBehaviour
if (UIBlocker.IsPointerOverUI()) wheel = 0f; // колесо над окнами HUD -- не приближать камеру (05.11)
if (Mathf.Abs(wheel) > 0.01f) Zoom(wheel * 0.1f);
// Два пальца -- приближение
if (Input.touchCount == 2)
// Два пальца -- приближение, как на карте мира: расстояние камеры меняется во столько раз,
// во сколько изменилось расстояние между пальцами за кадр (не зависит от того, увидели ли касание) (05.11)
if (Input.touchCount >= 2)
{
float d = Vector2.Distance(Input.GetTouch(0).position, Input.GetTouch(1).position);
if (Input.GetTouch(1).phase == TouchPhase.Began) lastPinch = d;
else if (lastPinch > 0) { Zoom((d - lastPinch) / Mathf.Max(200f, Screen.height)); lastPinch = d; }
Touch a = Input.GetTouch(0), b = Input.GetTouch(1);
float previous = ((a.position - a.deltaPosition) - (b.position - b.deltaPosition)).magnitude;
float current = (a.position - b.position).magnitude;
if (previous > 0.01f && current > 0.01f)
{
focusing = false;
distance = Mathf.Clamp(distance * previous / current, minDistance, maxDistance);
}
}
else lastPinch = 0;
if (focusing)
{
+15 -5
View File
@@ -677,7 +677,8 @@ public class City3DController : MonoBehaviour, City3DSave.ILive
{
if ((pos - pointerDown).magnitude > Screen.height * 0.015f) pointerMoved = true;
if (draggingGhost) DragGhost(pos);
else cameraRig.Pan(pos);
else if (pointerMoved) cameraRig.Pan(pos); // карта едет только при настоящем перетаскивании
else cameraRig.Track(pos); // а мелкое дрожание пальца при тапе её не трогает
}
else if (up && !pointerOverGui)
{
@@ -730,6 +731,12 @@ public class City3DController : MonoBehaviour, City3DSave.ILive
}
selectedBuilding = building;
selectedObstacle = building == null ? map.ObstacleAt(cx, cy) : null;
// Расчищать можно только в открытой зоне стройки (за её пределами -- после улучшения Ратуши) (05.11)
if (selectedObstacle != null && !map.IsOpen(cx, cy, townHallLevel))
{
selectedObstacle = null;
Say("Это за пределами зоны стройки -- откроется после улучшения Ратуши");
}
}
// Клетка под пальцем. groundOnly -- только земля (перетаскивание призрака); иначе здание под пальцем -- его клетка
@@ -845,10 +852,13 @@ public class City3DController : MonoBehaviour, City3DSave.ILive
// Окно HUD открыто -- временные кнопки сцены не показываем (и не ловим нажатия)
if (UIPanelManager.Instance != null && UIPanelManager.Instance.CurrentId != "") return;
// Под верхней панелью HUD, справа: Ратуша (тест), редактирование
Box(new Rect(w - 480, HudTop, 290, 44), $"3D (прототип) • Ратуша {townHallLevel} ур.");
if (Button(new Rect(w - 185, HudTop, 55, 44), "−")) ChangeTownHall(-1);
if (Button(new Rect(w - 125, HudTop, 55, 44), "+")) ChangeTownHall(+1);
// Под верхней панелью HUD, справа: Ратуша −/+ -- только в редакторе и отладочной сборке (тест зон), редактирование
if (Application.isEditor || Debug.isDebugBuild)
{
Box(new Rect(w - 480, HudTop, 290, 44), $"3D (тест) • Ратуша {townHallLevel} ур.");
if (Button(new Rect(w - 185, HudTop, 55, 44), "−")) ChangeTownHall(-1);
if (Button(new Rect(w - 125, HudTop, 55, 44), "+")) ChangeTownHall(+1);
}
if (mode == Mode.View || mode == Mode.Edit)
{
if (Button(new Rect(w - 250, HudTop + 50, 240, 44), mode == Mode.Edit ? "Готово" : "Редактировать"))
+10
View File
@@ -187,9 +187,19 @@ public static class City3DGameplay
if (!canvas.isRootCanvas || canvas.renderMode != RenderMode.ScreenSpaceCamera) continue;
canvas.worldCamera = cam;
canvas.planeDistance = cam.nearClipPlane + 0.05f;
HideWorldSprites(canvas);
}
}
// В HUD есть картинка-спрайт мира (SpriteRenderer) -- плашка с мечом по центру нижней панели. На холсте у
// камеры она рисуется поверх всего HUD, даже поверх открытых окон, а сама картинка без прозрачности
// ("шахматка"). Решение 05.11 (Миша, Володя): в 3D-сцене её убираем, пока не будет новой картинки или кнопки.
static void HideWorldSprites(Canvas canvas)
{
foreach (var sr in canvas.GetComponentsInChildren<SpriteRenderer>(true))
sr.enabled = false;
}
// Награда за расчистку (решение 04.11): +10 дерева за дерево или +10 камня за валун, один раз, в пределах склада
public static void RewardClearing(bool tree)
{