diff --git a/Assets/Scripts/Grid Units.meta b/Assets/Scripts/Grid Units.meta new file mode 100644 index 0000000..9d559bb --- /dev/null +++ b/Assets/Scripts/Grid Units.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d181bf8b664de9e4cb7f81dad16d3f50 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Grid Units/Grid.cs b/Assets/Scripts/Grid Units/Grid.cs new file mode 100644 index 0000000..92685c6 --- /dev/null +++ b/Assets/Scripts/Grid Units/Grid.cs @@ -0,0 +1,89 @@ +using Unity.Mathematics; +using UnityEngine; +using static Unity.Mathematics.math; +using RigidTransform = Unity.Mathematics.RigidTransform; +using quaternion = Unity.Mathematics.quaternion; + +public static class Grid +{ + + public static float CellSize = 0.25f; + public static float HalfCellSize => CellSize / 2; + + public static int3 ToSnappedDirection(this float3 direction) + { + float3 absDirection = abs(direction); + int axisIndex = absDirection.x >= absDirection.y + ? absDirection.x >= absDirection.z ? 0 : 2 + : absDirection.y >= absDirection.z ? 1 : 2; + + int3 snappedDirection = 0; + snappedDirection[axisIndex] = direction[axisIndex] > 0f ? 1 : -1; + return snappedDirection; + } + + public static int3x3 ToSnappedOrientation(this quaternion rotation) + { + float3x3 orientation = float3x3(rotation); + + int3 snappedRight = ToSnappedDirection(orientation.c0); + + int3 upMask = (int3)(snappedRight == 0); + int3 snappedUp = ToSnappedDirection(orientation.c1 * upMask); + + int3 forwardMask = upMask * (int3)(snappedUp == 0); + int3 snappedForward = ToSnappedDirection(orientation.c2 * forwardMask); + + return int3x3(snappedRight, snappedUp, snappedForward); + } + + public static float3 ToMeters(int3 size) => (float3)size * HalfCellSize; + + private static RigidTransform GetParentSpace(Transform t) + { + Transform parent = t.parent; + GridUnit parentUnit = parent != null ? parent.GetComponentInParent() : null; + if (parentUnit == null) + { + return RigidTransform.identity; + } + + Transform parentTransform = parentUnit.transform; + RigidTransform parentSpace = RigidTransform(parentTransform.rotation, parentTransform.position); + + float3 corner = parentUnit.CenterOffset - ToMeters(parentUnit.Size); + parentSpace.pos = transform(parentSpace, corner); + return parentSpace; + } + + public static void SnapUnit(Transform t, int3 size, float3 centerOffset) + { + RigidTransform parentSpace = GetParentSpace(t); + + RigidTransform rt = RigidTransform(t.rotation, t.position); + + rt = mul(inverse(parentSpace), rt); + + int3x3 snappedOrientation = rt.rot.ToSnappedOrientation(); + rt.rot = quaternion.LookRotation(snappedOrientation.c2, snappedOrientation.c1); + + float3 nudge = float3(1f); + if (size.x % 2 == 0) + nudge += snappedOrientation.c0; + if (size.y % 2 == 0) + nudge += snappedOrientation.c1; + if (size.z % 2 == 0) + nudge += snappedOrientation.c2; + nudge *= 0.5f; + + float3 centerOffsetW = mul(rt.rot, centerOffset); + float3 centerW = rt.pos + centerOffsetW; + centerW = (round(centerW / CellSize - nudge) + nudge) * CellSize; + rt.pos = centerW - centerOffsetW; + + rt = mul(parentSpace, rt); + + t.SetPositionAndRotation(rt.pos, rt.rot); + } + +} \ No newline at end of file diff --git a/Assets/Scripts/Grid Units/Grid.cs.meta b/Assets/Scripts/Grid Units/Grid.cs.meta new file mode 100644 index 0000000..0552f9b --- /dev/null +++ b/Assets/Scripts/Grid Units/Grid.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 742f76c1bb9643469274cdb6fceee9ac +timeCreated: 1723893723 \ No newline at end of file diff --git a/Assets/Scripts/Grid Units/GridUnit.cs b/Assets/Scripts/Grid Units/GridUnit.cs new file mode 100644 index 0000000..679c41d --- /dev/null +++ b/Assets/Scripts/Grid Units/GridUnit.cs @@ -0,0 +1,58 @@ +using UnityEngine; +using UnityEditor; +using Unity.Mathematics; +using static Unity.Mathematics.math; +using static Grid; +using Color = UnityEngine.Color; + +#if UNITY_EDITOR + +[ExecuteAlways] +[SelectionBase] +[DisallowMultipleComponent] +public class GridUnit : MonoBehaviour +{ + + public int3 Size = new (1, 1, 1); + private Vector3 SizeInMeters => new (Size.x * CellSize, Size.y * CellSize, Size.z * CellSize); + + public float3 CenterOffset; + + [SerializeField, HideInInspector] + private int3 cachedSize = new (1, 1, 1); + [SerializeField, HideInInspector] + private float3 cachedOffset; + + private bool isDirty => transform.hasChanged || + !all(cachedOffset != CenterOffset) || + !all(cachedSize == Size); + + public void Update() + { + if (!isDirty) + { + return; + } + + SnapUnit(transform, Size, CenterOffset); + + transform.hasChanged = false; + + cachedOffset = CenterOffset; + cachedSize = Size; + } + + [DrawGizmo(GizmoType.InSelectionHierarchy)] + private static void DrawGizmo(GridUnit unit, GizmoType type) + { + Transform t = unit.transform; + quaternion rotation = t.rotation; + var position = (float3)t.position + mul(rotation, unit.CenterOffset); + + Gizmos.color = Color.white; + Gizmos.matrix = Matrix4x4.TRS(position, rotation, Vector3.one); + Gizmos.DrawWireCube(Vector3.zero, unit.SizeInMeters); + } +} + +#endif diff --git a/Assets/Scripts/Grid Units/GridUnit.cs.meta b/Assets/Scripts/Grid Units/GridUnit.cs.meta new file mode 100644 index 0000000..dcb89cf --- /dev/null +++ b/Assets/Scripts/Grid Units/GridUnit.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: af3e57595c24e7b4dbb6f7f44db23525 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/manifest.json b/Packages/manifest.json index 7986c7f..e22734a 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -2,6 +2,7 @@ "dependencies": { "com.unity.ide.rider": "3.0.31", "com.unity.ide.visualstudio": "2.0.22", + "com.unity.mathematics": "1.2.6", "com.unity.textmeshpro": "3.0.6", "com.unity.ugui": "1.0.0", "com.unity.modules.ai": "1.0.0", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 775d141..d56a407 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -25,6 +25,13 @@ }, "url": "https://packages.unity.com" }, + "com.unity.mathematics": { + "version": "1.2.6", + "depth": 0, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, "com.unity.test-framework": { "version": "1.1.33", "depth": 1,