diff --git a/Assets/Editor/AndroidBuildFixes.cs.meta b/Assets/Editor/AndroidBuildFixes.cs.meta new file mode 100644 index 0000000..eeab066 --- /dev/null +++ b/Assets/Editor/AndroidBuildFixes.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 030e644cb052c0f4d959e499015370fd \ No newline at end of file diff --git a/Assets/Editor/ApkBuilder.cs.meta b/Assets/Editor/ApkBuilder.cs.meta new file mode 100644 index 0000000..241ecee --- /dev/null +++ b/Assets/Editor/ApkBuilder.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 904233d7647ed024d920bdbbd4058aba \ No newline at end of file diff --git a/Assets/Editor/SceneListFixer.cs b/Assets/Editor/SceneListFixer.cs index 818a736..dc353c8 100644 --- a/Assets/Editor/SceneListFixer.cs +++ b/Assets/Editor/SceneListFixer.cs @@ -3,11 +3,13 @@ using UnityEditor; // Следит, чтобы сцена карты мира (WorldMap, от Саши) была в Build Settings -- // иначе переход город -> карта не работает. Срабатывает сам после каждой компиляции. +// Стартовая сцена (05.11): 3D-поселение City3D, если оно есть в проекте, иначе 2D-город MVP1. [InitializeOnLoad] public static class SceneListFixer { const string CityScene = "Assets/Scenes/MVP1.unity"; const string WorldScene = "Assets/Scenes/WorldMap.unity"; + const string City3DScene = "Assets/Scenes/City3D.unity"; static SceneListFixer() { EditorApplication.delayCall += Ensure; } @@ -15,15 +17,16 @@ public static class SceneListFixer { var scenes = new List(EditorBuildSettings.scenes); bool changed = false; - foreach (var path in new[] { CityScene, WorldScene }) + string start = AssetDatabase.LoadAssetAtPath(City3DScene) != null ? City3DScene : CityScene; + foreach (var path in new[] { start, CityScene, WorldScene }) { if (AssetDatabase.LoadAssetAtPath(path) == null) continue; if (scenes.Exists(s => s.path == path)) continue; scenes.Add(new EditorBuildSettingsScene(path, true)); changed = true; } - // город должен быть первым (с него стартует игра) - int city = scenes.FindIndex(s => s.path == CityScene); + // стартовый город должен быть первым (с него стартует игра) + int city = scenes.FindIndex(s => s.path == start); if (city > 0) { var c = scenes[city]; scenes.RemoveAt(city); scenes.Insert(0, c); changed = true; } if (changed) { diff --git a/Assets/Prefab/UI/HUD_Canvas.prefab b/Assets/Prefab/UI/HUD_Canvas.prefab index 7cfa41b..dd5f17b 100644 --- a/Assets/Prefab/UI/HUD_Canvas.prefab +++ b/Assets/Prefab/UI/HUD_Canvas.prefab @@ -574,11 +574,11 @@ RectTransform: - {fileID: 8073695889979356888} m_Father: {fileID: 3982763195980837839} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 432, y: 0} + m_AnchorMin: {x: 0.416667, y: 1} + m_AnchorMax: {x: 0.416667, y: 1} + m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 216, y: 190} - m_Pivot: {x: 0, y: 1} + m_Pivot: {x: 0.5, y: 1} --- !u!222 &1161890866068155973 CanvasRenderer: m_ObjectHideFlags: 0 @@ -949,11 +949,11 @@ RectTransform: - {fileID: 6625169345854146367} m_Father: {fileID: 3982763195980837839} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 1625, y: 0} + m_AnchorMin: {x: 0.75, y: 1} + m_AnchorMax: {x: 0.75, y: 1} + m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 216, y: 190} - m_Pivot: {x: 0, y: 1} + m_Pivot: {x: 0.5, y: 1} --- !u!222 &1574865706497193506 CanvasRenderer: m_ObjectHideFlags: 0 @@ -2083,11 +2083,11 @@ RectTransform: - {fileID: 5819281947737217065} m_Father: {fileID: 3982763195980837839} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 1409, y: 0} + m_AnchorMin: {x: 0.583333, y: 1} + m_AnchorMax: {x: 0.583333, y: 1} + m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 216, y: 190} - m_Pivot: {x: 0, y: 1} + m_Pivot: {x: 0.5, y: 1} --- !u!222 &8054631941258821217 CanvasRenderer: m_ObjectHideFlags: 0 @@ -2724,11 +2724,11 @@ RectTransform: - {fileID: 6422401267007934049} m_Father: {fileID: 3982763195980837839} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} + m_AnchorMin: {x: 0.083333, y: 1} + m_AnchorMax: {x: 0.083333, y: 1} m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 216, y: 190} - m_Pivot: {x: 0, y: 1} + m_Pivot: {x: 0.5, y: 1} --- !u!222 &1319220892576480966 CanvasRenderer: m_ObjectHideFlags: 0 @@ -3692,11 +3692,11 @@ RectTransform: - {fileID: 4996814669716176554} m_Father: {fileID: 3982763195980837839} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 216, y: 0} + m_AnchorMin: {x: 0.25, y: 1} + m_AnchorMax: {x: 0.25, y: 1} + m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 216, y: 190} - m_Pivot: {x: 0, y: 1} + m_Pivot: {x: 0.5, y: 1} --- !u!222 &5060908328969132528 CanvasRenderer: m_ObjectHideFlags: 0 @@ -4111,13 +4111,14 @@ RectTransform: - {fileID: 3561707029477629692} - {fileID: 3476476116216033849} - {fileID: 628544459168404126} + - {fileID: 113684291289998490} m_Father: {fileID: 2090086157864901368} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 1, y: 1} m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: -145, y: -425} + m_AnchoredPosition: {x: -145, y: -190} m_SizeDelta: {x: 0, y: 0} - m_Pivot: {x: 0.5, y: 0.5} + m_Pivot: {x: 0.5, y: 1} --- !u!114 &4213699917549184054 MonoBehaviour: m_ObjectHideFlags: 0 @@ -9582,13 +9583,13 @@ RectTransform: - {fileID: 8503115147530003650} - {fileID: 3734242786053216068} - {fileID: 1570549891241898707} - m_Father: {fileID: 3982763195980837839} + m_Father: {fileID: 4178416176766117917} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 1, y: 1} - m_AnchorMax: {x: 1, y: 1} - m_AnchoredPosition: {x: -162, y: 172.02252} - m_SizeDelta: {x: 128.34, y: 102.34} - m_Pivot: {x: 0, y: 1} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 118, y: 118} + m_Pivot: {x: 1, y: 1} --- !u!222 &2919605703939985733 CanvasRenderer: m_ObjectHideFlags: 0 @@ -10263,11 +10264,11 @@ RectTransform: - {fileID: 8771264060587801238} m_Father: {fileID: 3982763195980837839} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 1} - m_AnchorMax: {x: 0, y: 1} - m_AnchoredPosition: {x: 1808, y: 0} + m_AnchorMin: {x: 0.916667, y: 1} + m_AnchorMax: {x: 0.916667, y: 1} + m_AnchoredPosition: {x: 0, y: 0} m_SizeDelta: {x: 216, y: 190} - m_Pivot: {x: 0, y: 1} + m_Pivot: {x: 0.5, y: 1} --- !u!222 &7841802503944609977 CanvasRenderer: m_ObjectHideFlags: 0 @@ -14658,7 +14659,6 @@ RectTransform: - {fileID: 3980605506120029191} - {fileID: 6797326426102539044} - {fileID: 6246972527393936552} - - {fileID: 113684291289998490} m_Father: {fileID: 2090086157864901368} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} diff --git a/Assets/Scripts/City3D/City3DCamera.cs b/Assets/Scripts/City3D/City3DCamera.cs index 653ab9b..b46a694 100644 --- a/Assets/Scripts/City3D/City3DCamera.cs +++ b/Assets/Scripts/City3D/City3DCamera.cs @@ -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) { diff --git a/Assets/Scripts/City3D/City3DController.cs b/Assets/Scripts/City3D/City3DController.cs index 82b72a5..3ba2a3e 100644 --- a/Assets/Scripts/City3D/City3DController.cs +++ b/Assets/Scripts/City3D/City3DController.cs @@ -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 ? "Готово" : "Редактировать")) diff --git a/Assets/Scripts/City3D/City3DGameplay.cs b/Assets/Scripts/City3D/City3DGameplay.cs index b1889fa..12b22c6 100644 --- a/Assets/Scripts/City3D/City3DGameplay.cs +++ b/Assets/Scripts/City3D/City3DGameplay.cs @@ -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(true)) + sr.enabled = false; + } + // Награда за расчистку (решение 04.11): +10 дерева за дерево или +10 камня за валун, один раз, в пределах склада public static void RewardClearing(bool tree) { diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset index 73db522..877b17e 100644 --- a/ProjectSettings/EditorBuildSettings.asset +++ b/ProjectSettings/EditorBuildSettings.asset @@ -5,12 +5,12 @@ EditorBuildSettings: m_ObjectHideFlags: 0 serializedVersion: 2 m_Scenes: - - enabled: 1 - path: Assets/Scenes/MVP1.unity - guid: beae4025d64976c4f93af3b9233183da - enabled: 1 path: Assets/Scenes/City3D.unity guid: c1c34719f0605c247a3575d077f3d656 + - enabled: 1 + path: Assets/Scenes/MVP1.unity + guid: beae4025d64976c4f93af3b9233183da - enabled: 1 path: Assets/Scenes/WorldMap.unity guid: baa48fafda29f4247b2910dc9622c97a