Initial commit

This commit is contained in:
HussienX72u
2026-07-21 08:56:10 +03:00
commit 4017028111
9410 changed files with 2150500 additions and 0 deletions
@@ -0,0 +1,10 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public interface IValidator
{
bool IsValidPlacement(GameObject objToPlace);
void SetLayerMask(LayerMask cLayerMask);
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ba9fdb21db901e7448c9bcf92b1bf1e1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,138 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MultipleColliderValidator : MonoBehaviour, IValidator
{
[SerializeField] private LayerMask collisionLayerMask;
[SerializeField] private float toleranceSkin = 0.05f; // Shrinks the check box slightly
public void SetLayerMask(LayerMask cLayerMask) => collisionLayerMask = cLayerMask;
public bool IsValidPlacement(GameObject objToPlace)
{
// Get all colliders of the object we are moving
Collider[] objColliders = objToPlace.GetComponentsInChildren<Collider>();
if (objColliders.Length == 0) return true;
foreach (Collider objCollider in objColliders)
{
if (objCollider.isTrigger) continue;
if (objCollider.gameObject.layer == LayerMask.NameToLayer("Gizmos")) continue;
if (!CheckCollider(objCollider, objToPlace.transform.root))
return false;
}
return true; // Valid placement if all colliders are clear
}
private bool CheckCollider(Collider objCollider, Transform root)
{
Collider[] hits = new Collider[0];
if (objCollider is BoxCollider box)
{
Vector3 center = objCollider.transform.TransformPoint(box.center);
Vector3 lossyScale = objCollider.transform.lossyScale;
Vector3 scale = new Vector3(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z));
Vector3 size = Vector3.Scale(box.size, scale);
// Apply tolerance (shrink on both sides of each axis)
Vector3 overlapSize = new Vector3(
Mathf.Max(size.x - toleranceSkin * 2f, size.x * 0.8f),
Mathf.Max(size.y - toleranceSkin * 2f, size.y * 0.8f),
Mathf.Max(size.z - toleranceSkin * 2f, size.z * 0.8f)
);
hits = Physics.OverlapBox(center, overlapSize * 0.5f, objCollider.transform.rotation, collisionLayerMask);
}
else if (objCollider is SphereCollider sphere)
{
Vector3 center = objCollider.transform.TransformPoint(sphere.center);
Vector3 lossyScale = objCollider.transform.lossyScale;
float maxScale = Mathf.Max(Mathf.Abs(lossyScale.x), Mathf.Max(Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z)));
float radius = sphere.radius * maxScale;
float overlapRadius = Mathf.Max(0f, radius - toleranceSkin);
hits = Physics.OverlapSphere(center, overlapRadius, collisionLayerMask);
}
else if (objCollider is CapsuleCollider capsule)
{
Vector3 center = objCollider.transform.TransformPoint(capsule.center);
Vector3 lossyScale = objCollider.transform.lossyScale;
float scaleX = Mathf.Abs(lossyScale.x);
float scaleY = Mathf.Abs(lossyScale.y);
float scaleZ = Mathf.Abs(lossyScale.z);
float radiusScale = Mathf.Max(scaleX, scaleZ);
float heightScale = scaleY;
Vector3 dir = objCollider.transform.up;
if (capsule.direction == 0) // X-axis
{
radiusScale = Mathf.Max(scaleY, scaleZ);
heightScale = scaleX;
dir = objCollider.transform.right;
}
else if (capsule.direction == 2) // Z-axis
{
radiusScale = Mathf.Max(scaleX, scaleY);
heightScale = scaleZ;
dir = objCollider.transform.forward;
}
float radius = capsule.radius * radiusScale;
float height = capsule.height * heightScale;
float overlapRadius = Mathf.Max(0f, radius - toleranceSkin);
float overlapHeight = Mathf.Max(0f, height - (toleranceSkin * 2f));
float pointOffset = Mathf.Max(0f, (overlapHeight * 0.5f) - overlapRadius);
Vector3 point0 = center + dir * pointOffset;
Vector3 point1 = center - dir * pointOffset;
hits = Physics.OverlapCapsule(point0, point1, overlapRadius, collisionLayerMask);
}
else if (objCollider is MeshCollider mc && mc.sharedMesh != null)
{
Bounds localBounds = mc.sharedMesh.bounds;
Vector3 center = objCollider.transform.TransformPoint(localBounds.center);
Vector3 lossyScale = objCollider.transform.lossyScale;
Vector3 scale = new Vector3(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z));
Vector3 size = Vector3.Scale(localBounds.size, scale);
Vector3 overlapSize = new Vector3(
Mathf.Max(size.x - toleranceSkin * 2f, size.x * 0.8f),
Mathf.Max(size.y - toleranceSkin * 2f, size.y * 0.8f),
Mathf.Max(size.z - toleranceSkin * 2f, size.z * 0.8f)
);
hits = Physics.OverlapBox(center, overlapSize * 0.5f, objCollider.transform.rotation, collisionLayerMask);
}
else
{
// Fallback: AABB check
Vector3 center = objCollider.bounds.center;
Vector3 size = objCollider.bounds.size;
Vector3 overlapSize = new Vector3(
Mathf.Max(size.x - toleranceSkin * 2f, size.x * 0.8f),
Mathf.Max(size.y - toleranceSkin * 2f, size.y * 0.8f),
Mathf.Max(size.z - toleranceSkin * 2f, size.z * 0.8f)
);
hits = Physics.OverlapBox(center, overlapSize * 0.5f, Quaternion.identity, collisionLayerMask);
}
foreach (Collider hit in hits)
{
if (hit.transform.root == root) continue;
if (hit.isTrigger) continue;
return false;
}
return true;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b0f0c40b7649c4b45a67e5876bbd3d9a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,129 @@
using UnityEngine;
using System.Collections.Generic;
public class PlacementValidator : MonoBehaviour, IValidator
{
[SerializeField] private LayerMask collisionLayerMask;
[SerializeField] private float toleranceSkin = 0.05f; // Shrinks the check box slightly
public void SetLayerMask(LayerMask cLayerMask) => collisionLayerMask = cLayerMask;
public bool IsValidPlacement(GameObject objToPlace)
{
Collider objCollider = objToPlace.GetComponent<Collider>();
if (objCollider == null) return true;
if (objCollider.isTrigger) return true;
if (objCollider.gameObject.layer == LayerMask.NameToLayer("Gizmos")) return true;
return CheckCollider(objCollider, objToPlace.transform.root);
}
private bool CheckCollider(Collider objCollider, Transform root)
{
Collider[] hits = new Collider[0];
if (objCollider is BoxCollider box)
{
Vector3 center = objCollider.transform.TransformPoint(box.center);
Vector3 lossyScale = objCollider.transform.lossyScale;
Vector3 scale = new Vector3(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z));
Vector3 size = Vector3.Scale(box.size, scale);
// Apply tolerance (shrink on both sides of each axis), but never shrink below 80% of original size
Vector3 overlapSize = new Vector3(
Mathf.Max(size.x - toleranceSkin * 2f, size.x * 0.8f),
Mathf.Max(size.y - toleranceSkin * 2f, size.y * 0.8f),
Mathf.Max(size.z - toleranceSkin * 2f, size.z * 0.8f)
);
hits = Physics.OverlapBox(center, overlapSize * 0.5f, objCollider.transform.rotation, collisionLayerMask);
}
else if (objCollider is SphereCollider sphere)
{
Vector3 center = objCollider.transform.TransformPoint(sphere.center);
Vector3 lossyScale = objCollider.transform.lossyScale;
float maxScale = Mathf.Max(Mathf.Abs(lossyScale.x), Mathf.Max(Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z)));
float radius = sphere.radius * maxScale;
float overlapRadius = Mathf.Max(0f, radius - toleranceSkin);
hits = Physics.OverlapSphere(center, overlapRadius, collisionLayerMask);
}
else if (objCollider is CapsuleCollider capsule)
{
Vector3 center = objCollider.transform.TransformPoint(capsule.center);
Vector3 lossyScale = objCollider.transform.lossyScale;
float scaleX = Mathf.Abs(lossyScale.x);
float scaleY = Mathf.Abs(lossyScale.y);
float scaleZ = Mathf.Abs(lossyScale.z);
float radiusScale = Mathf.Max(scaleX, scaleZ);
float heightScale = scaleY;
Vector3 dir = objCollider.transform.up;
if (capsule.direction == 0) // X-axis
{
radiusScale = Mathf.Max(scaleY, scaleZ);
heightScale = scaleX;
dir = objCollider.transform.right;
}
else if (capsule.direction == 2) // Z-axis
{
radiusScale = Mathf.Max(scaleX, scaleY);
heightScale = scaleZ;
dir = objCollider.transform.forward;
}
float radius = capsule.radius * radiusScale;
float height = capsule.height * heightScale;
float overlapRadius = Mathf.Max(0f, radius - toleranceSkin);
float overlapHeight = Mathf.Max(0f, height - (toleranceSkin * 2f));
float pointOffset = Mathf.Max(0f, (overlapHeight * 0.5f) - overlapRadius);
Vector3 point0 = center + dir * pointOffset;
Vector3 point1 = center - dir * pointOffset;
hits = Physics.OverlapCapsule(point0, point1, overlapRadius, collisionLayerMask);
}
else if (objCollider is MeshCollider mc && mc.sharedMesh != null)
{
Bounds localBounds = mc.sharedMesh.bounds;
Vector3 center = objCollider.transform.TransformPoint(localBounds.center);
Vector3 lossyScale = objCollider.transform.lossyScale;
Vector3 scale = new Vector3(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.y), Mathf.Abs(lossyScale.z));
Vector3 size = Vector3.Scale(localBounds.size, scale);
Vector3 overlapSize = new Vector3(
Mathf.Max(size.x - toleranceSkin * 2f, size.x * 0.8f),
Mathf.Max(size.y - toleranceSkin * 2f, size.y * 0.8f),
Mathf.Max(size.z - toleranceSkin * 2f, size.z * 0.8f)
);
hits = Physics.OverlapBox(center, overlapSize * 0.5f, objCollider.transform.rotation, collisionLayerMask);
}
else
{
// Fallback: AABB check
Vector3 center = objCollider.bounds.center;
Vector3 size = objCollider.bounds.size;
Vector3 overlapSize = new Vector3(
Mathf.Max(size.x - toleranceSkin * 2f, size.x * 0.8f),
Mathf.Max(size.y - toleranceSkin * 2f, size.y * 0.8f),
Mathf.Max(size.z - toleranceSkin * 2f, size.z * 0.8f)
);
hits = Physics.OverlapBox(center, overlapSize * 0.5f, Quaternion.identity, collisionLayerMask);
}
foreach (Collider hit in hits)
{
if (hit.transform.root == root) continue;
if (hit.isTrigger) continue;
return false;
}
return true;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8245c6e3d94e025439b7ccced75276db
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,3 @@
{
"name": "Scripts.Validators"
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c16923da89c230b46a6c01482752a2ba
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: