using UnityEngine; namespace Ashwild.Building { /// /// Connection category of a snap socket — two sockets link only when their categories match. /// Authored so that connectable sockets share a value (e.g. a floor's edge and a wall's foot /// are both Floor, so a wall snaps onto a floor edge; walls meet side-to-side as Wall). /// public enum SnapCategory { Floor, Wall, Roof, Pillar, Custom } /// /// One connection socket on a buildable, placed as a child transform at an edge/corner. Its /// world position is where a matching socket clicks into place; its category decides what may /// connect. Built pieces carry an enabled trigger collider on the snap layer so the placement /// controller finds them by overlap; the ghost's own snap colliders are disabled with the rest /// of the ghost, so the ghost never snaps to itself. /// /// Once another piece connects here the socket is marked occupied — the placement snapping skips /// occupied sockets (so two pieces never stack on the same connection) and its gizmo turns red /// in the Scene view; while free it takes the colour of its category, so a glance at a prefab /// tells which sockets can ever link together. /// [DisallowMultipleComponent] public class BuildSnapPoint : MonoBehaviour { #region Serialized Fields [Tooltip("What may connect here — a socket links only to another of the same category.")] [SerializeField] private SnapCategory category; #endregion #region State private bool occupied; #endregion #region Public API public SnapCategory Category => category; /// /// Whether another piece is already connected to this socket. /// public bool IsOccupied => occupied; /// /// Flags the socket as taken (or freed) — set when a piece connects/disconnects here. /// public void SetOccupied(bool value) => occupied = value; #endregion #region Gizmos private static readonly Color OccupiedColor = new Color(1f, 0.3f, 0.3f, 0.9f); private static readonly Color FloorColor = new Color(0.3f, 0.8f, 1f, 0.9f); private static readonly Color WallColor = new Color(0.4f, 1f, 0.5f, 0.9f); private static readonly Color RoofColor = new Color(1f, 0.75f, 0.25f, 0.9f); private static readonly Color PillarColor = new Color(0.8f, 0.5f, 1f, 0.9f); private static readonly Color CustomColor = new Color(1f, 1f, 1f, 0.9f); /// /// Draws the socket in the editor: a sphere plus a ray along its forward (Z) axis — the /// direction the connecting piece attaches. Two sockets link only when their forwards face /// each other, so orient each empty's arrow outward toward where the neighbour should sit. /// private void OnDrawGizmos() { Gizmos.color = occupied ? OccupiedColor : GetCategoryColor(category); Gizmos.DrawWireSphere(transform.position, 0.12f); Gizmos.DrawRay(transform.position, transform.forward * 0.35f); } /// /// Maps a connection category to its Scene-view colour. Sockets that can link share a /// category, so same-coloured gizmos are exactly the ones that may ever snap together — /// mismatched colours on two pieces mean they will never connect. /// private static Color GetCategoryColor(SnapCategory value) { switch (value) { case SnapCategory.Floor: return FloorColor; case SnapCategory.Wall: return WallColor; case SnapCategory.Roof: return RoofColor; case SnapCategory.Pillar: return PillarColor; default: return CustomColor; } } #endregion } }