using UnityEngine; namespace Vanguard.Board3D { /// /// Настройка 3D-поля: геометрия кругов, высоты, скорости анимаций, /// камера и палитра. Один общий ассет на Classic; раскладка не зависит /// от того, за какое место играет локальный игрок. /// [CreateAssetMenu( menuName = "Vanguard/Playmat Layout", fileName = "PlaymatLayoutConfig")] public sealed class PlaymatLayoutConfig : ScriptableObject { [Header("Карта")] public float cardWidth = 0.63f; public float cardHeight = 0.88f; public float cardThickness = 0.006f; [Header("Поле")] [Tooltip("Расстояние между центрами соседних кругов по X.")] public float circleSpacingX = 1.42f; [Tooltip("Z переднего ряда в локальных координатах игрока.")] public float frontRowZ = 1.55f; [Tooltip("Z заднего ряда в локальных координатах игрока.")] public float backRowZ = 3.0f; public float boardHalfWidth = 4.6f; public float boardHalfLength = 4.0f; [Header("Высоты")] public float cardLift = 0.02f; public float guardianLift = 0.008f; public float damageLift = 0.012f; public float pileLift = 0.018f; public float dragLift = 0.14f; [Header("Взаимодействие")] public float snapRadius = 0.66f; public float dragThresholdPixels = 7f; public float smoothMoveSpeed = 16f; public float smoothRotateSpeed = 14f; public float handHoverLift = 0.08f; [Header("Рука на столе (fallback без камеры)")] public float handCenterZ = -5.3f; public float handHeight = 1.12f; [Range(0f, 85f)] public float handTilt = 58f; public float handSpacing = 0.42f; public float handMaxWidth = 7.4f; public float handArc = 0.035f; [Header("Рука в поле зрения")] [Tooltip("Доля ширины экрана для центра карт: 0 — левый край, 0.5 — середина.")] [Range(0.05f, 0.95f)] public float handViewportX = 0.44f; [Tooltip("Доля высоты экрана для центра карт: 0 — низ, 0.5 — середина.")] [Range(0.05f, 0.45f)] public float handViewportY = 0.10f; [Tooltip("Расстояние от камеры до веера руки, метры.")] public float handViewDistance = 4.0f; public float handViewMaxWidth = 1.4f; public float handViewScale = 0.5f; public float handViewRoll = 3.2f; public float handViewArc = 0.02f; [Header("Рука противника")] public bool opponentHandEnabled = true; public float opponentHandZ = 4.3f; public float opponentHandHeight = 0.75f; public float opponentHandSpacing = 0.42f; public float opponentHandMaxWidth = 2.4f; public float opponentHandScale = 0.8f; public float opponentHandRoll = 2.5f; [Header("Круг защиты")] public float guardianRowGap = 0.55f; public float guardianSpacing = 0.62f; public float guardianMaxWidth = 3.6f; [Header("Стопки")] [Tooltip("Расстояние от центра стола до зоны урона.")] public float damageX = 3.0f; [Tooltip("Расстояние от центра стола до колоды и дропа.")] public float pileX = 2.95f; [Header("Отладка")] [Tooltip("Показывать подписи зон на 3D-столе.")] public bool showZoneLabels = false; [Header("Камера")] [Tooltip("Фиксированная камера над полем. Не двигается игроком.")] public Vector3 cameraPosition = new Vector3(0f, 4.2f, -8f); public Vector3 cameraTarget = new Vector3(0f, 0f, 0f); public float cameraFov = 46f; [Header("Палитра")] public Color tableColor = new Color(0.045f, 0.04f, 0.055f); public Color matSelfColor = new Color(0.055f, 0.095f, 0.16f); public Color matOpponentColor = new Color(0.13f, 0.065f, 0.075f); public Color lineColor = new Color(0.62f, 0.45f, 0.18f); public Color ringColor = new Color(0.18f, 0.28f, 0.44f); public Color vanguardRingColor = new Color(0.78f, 0.60f, 0.24f); public Color guardianColor = new Color(0.18f, 0.58f, 0.70f); public Color damageColor = new Color(0.58f, 0.16f, 0.18f); public Color soulColor = new Color(0.42f, 0.25f, 0.68f); public Color highlightColor = new Color(1f, 0.78f, 0.24f); public Color selectedColor = new Color(0.35f, 0.95f, 0.56f); [Header("Необязательный prefab карты")] public Card3D cardPrefab; private static PlaymatLayoutConfig _default; /// Рантайм-конфиг, если в сцене нет ассета. public static PlaymatLayoutConfig Default { get { if (_default == null) { _default = CreateInstance(); _default.name = "PlaymatLayoutConfig (runtime)"; _default.hideFlags = HideFlags.DontSave; } return _default; } } public static PlaymatLayoutConfig CreateDefault() { var config = CreateInstance(); config.name = "PlaymatLayoutConfig"; return config; } public float CardCenterY => cardLift + (cardThickness * 0.5f); public float GuardianCenterY => guardianLift + (cardThickness * 0.5f); public float DamageCenterY => damageLift + (cardThickness * 0.5f); private void OnValidate() { cardWidth = Mathf.Max(0.1f, cardWidth); cardHeight = Mathf.Max(0.1f, cardHeight); cardThickness = Mathf.Max(0.001f, cardThickness); circleSpacingX = Mathf.Max(0.4f, circleSpacingX); frontRowZ = Mathf.Max(0.2f, frontRowZ); backRowZ = Mathf.Max(frontRowZ + 0.2f, backRowZ); boardHalfWidth = Mathf.Max(2f, boardHalfWidth); boardHalfLength = Mathf.Max(backRowZ + 0.5f, boardHalfLength); dragLift = Mathf.Max(cardLift + 0.02f, dragLift); snapRadius = Mathf.Clamp(snapRadius, 0.2f, 1.5f); handMaxWidth = Mathf.Max(1f, handMaxWidth); guardianMaxWidth = Mathf.Max(1f, guardianMaxWidth); handViewportY = Mathf.Clamp(handViewportY, 0.05f, 0.45f); handViewportX = Mathf.Clamp(handViewportX, 0.05f, 0.95f); handViewDistance = Mathf.Max(1f, handViewDistance); handViewMaxWidth = Mathf.Max(0.5f, handViewMaxWidth); handViewScale = Mathf.Clamp(handViewScale, 0.3f, 1.5f); handViewRoll = Mathf.Clamp(handViewRoll, 0f, 20f); handViewArc = Mathf.Max(0f, handViewArc); opponentHandZ = Mathf.Max(1f, opponentHandZ); opponentHandHeight = Mathf.Max(0.2f, opponentHandHeight); opponentHandSpacing = Mathf.Max(0.1f, opponentHandSpacing); opponentHandMaxWidth = Mathf.Max(0.5f, opponentHandMaxWidth); opponentHandScale = Mathf.Clamp(opponentHandScale, 0.3f, 1.5f); opponentHandRoll = Mathf.Clamp(opponentHandRoll, 0f, 20f); } } }