Files
2026-02-21 16:45:37 +08:00

167 lines
3.1 KiB
C#

using UnityEngine;
namespace S_SnapTools
{
public class S_SnapToWorld : MonoBehaviour
{
[SerializeField]
private LayerMask m_snapToLayers = 1;
[SerializeField]
private Vector3 m_snapDirection = Vector3.down;
[SerializeField]
private int m_snapFrameRate = 5;
[SerializeField]
private bool m_isRotationSnap = true;
[SerializeField]
private float m_maxSnapDistanceAgainstDirection = 1000f;
private int m_snapCounter = -1;
public LayerMask SnapToLayers
{
get
{
return m_snapToLayers;
}
set
{
m_snapToLayers = value;
}
}
public Vector3 SnapDirection
{
get
{
return m_snapDirection;
}
set
{
m_snapDirection = value;
}
}
public int SnapFrameRate
{
get
{
return m_snapFrameRate;
}
set
{
m_snapFrameRate = value;
}
}
public bool IsRotationSnap
{
get
{
return m_isRotationSnap;
}
set
{
m_isRotationSnap = value;
}
}
public float MaxSnapDistanceAgainstDirection
{
get
{
return m_maxSnapDistanceAgainstDirection;
}
set
{
m_maxSnapDistanceAgainstDirection = value;
}
}
public void DoSnap()
{
Vector3 origin = base.transform.position - m_snapDirection * m_maxSnapDistanceAgainstDirection;
RaycastHit hitInfo;
if (((1 << base.gameObject.layer) & m_snapToLayers.value) != 0)
{
RaycastHit[] array = Physics.RaycastAll(origin, m_snapDirection, float.PositiveInfinity, m_snapToLayers.value);
RaycastHit? raycastHit = null;
float num = float.PositiveInfinity;
for (int i = 0; i < array.Length; i++)
{
if (!array[i].transform.IsChildOf(base.transform) && num > array[i].distance)
{
num = array[i].distance;
raycastHit = array[i];
}
}
if (raycastHit.HasValue)
{
SnapToHit(raycastHit.Value);
}
}
else if (Physics.Raycast(origin, m_snapDirection, out hitInfo, float.PositiveInfinity, m_snapToLayers.value))
{
SnapToHit(hitInfo);
}
}
private void SnapToHit(RaycastHit p_hit)
{
base.transform.position = p_hit.point;
if (!m_isRotationSnap)
{
return;
}
Vector3 forward = base.transform.forward;
base.transform.up = p_hit.normal;
forward -= base.transform.up * Vector3.Dot(base.transform.up, forward);
forward.Normalize();
if (Vector3.Dot(Vector3.Cross(base.transform.forward, forward), p_hit.normal) > 0f)
{
float num = 0f - Vector3.Angle(base.transform.forward, forward);
if (!float.IsNaN(num))
{
base.transform.Rotate(Vector3.down, num);
}
}
else
{
float num2 = 0f - Vector3.Angle(base.transform.forward, forward);
if (!float.IsNaN(num2))
{
base.transform.Rotate(Vector3.up, num2);
}
}
}
private void Update()
{
if (m_snapFrameRate != -1)
{
if (m_snapCounter <= 0)
{
m_snapCounter = m_snapFrameRate;
DoSnap();
}
else
{
m_snapCounter--;
}
}
}
private static void MoveToLayer(Transform p_root, int p_layer)
{
p_root.gameObject.layer = p_layer;
foreach (Transform item in p_root)
{
MoveToLayer(item, p_layer);
}
}
}
}