XGRIDSDocumentación
  • 简体中文
  • English
  • 繁體中文
  • 日本語
  • Deutsch
  • Español
  • Italiano
  • Français
  • Русский
  • Polski
  • Nederlands
  • 简体中文
  • English
  • 繁體中文
  • 日本語
  • Deutsch
  • Español
  • Italiano
  • Français
  • Русский
  • Polski
  • Nederlands
  • Serie Lixel PortalCam

    • PortalCam P1

      • Descripción del producto
      • Operaciones básicas
      • Uso de la LCC Scan App
      • Mantenimiento y cuidado
      • FAQ
  • Serie Lixel K

    • Lixel K1

      • Descripción del producto
      • Operaciones básicas
      • Activación y conexión del dispositivo
      • Flujo de escaneo
      • Obtener nube de puntos con coordenadas absolutas
      • Fusión de mapas
      • Recomendaciones de planificación de rutas para escenas típicas
      • Precauciones
      • FAQ
    • Lixel K2

      • Descripción del producto
      • Operaciones básicas
      • Activación y conexión
      • Flujo de escaneo
      • Obtener nube de puntos con coordenadas absolutas
      • Fusión de mapas
      • Recomendaciones de planificación de rutas para escenas típicas
      • Precauciones
      • FAQ
  • Serie Lixel L

    • Lixel L2 Pro

      • Descripción del producto
      • Operaciones básicas
      • Activación y conexión del dispositivo
      • Flujo de escaneo
      • Obtener nube de puntos con coordenadas absolutas
      • Punto de medición
      • Apéndice
      • FAQ
    • Lixel L3

      • Descripción del producto
      • Operaciones básicas
      • Activación y conexión del dispositivo
      • Flujo de escaneo
      • Obtener nube de puntos con coordenadas absolutas
      • Apéndice
  • Accesorios

    • Stick Light

      • Guía de instalación
      • Operaciones básicas
      • Preguntas frecuentes
  • Lixel Studio

    • Versión y derechos de autor
    • Instalación y activación
    • Interfaz del software
    • Operaciones de archivo
    • Procesamiento de proyectos
    • Herramientas
    • Dibujo 2D
    • Aplicaciones
    • Ajustes
    • Conexión de dispositivo
    • Preguntas Frecuentes
  • Lixel CyberColor

    • LCC Studio

      • Primeros pasos
      • Versión y actualizaciones
      • Descarga e instalación
      • Descripción general de la interfaz y navegación
      • Antes de la reconstrucción
      • Reconstrucción de modelos
      • Reconstrucción de modelo único
      • Fusión de mapas
      • Fusión aire-tierra
      • Reconstrucción aérea
      • Mis modelos
      • Otras funciones
      • Ajustes y cuenta
      • Converter
      • Reconstrucción por vídeo
      • Preguntas frecuentes
    • LCC Scene Editor

      • Versión y actualizaciones
      • Cuenta e inicio de sesión
      • Descripción general del producto y página de inicio
      • Interfaz del editor
      • Modos de navegación
      • Archivo
      • Configuración
      • Editar
      • Ventana
      • Barra de herramientas global
      • Activos y propiedades
      • Barra de herramientas izquierda
      • Puntos de vista
      • Portal
      • Skybox
      • Anotaciones
      • Medición
      • Flythrough
      • Informe de escena
      • 3D Layout
      • Minimapa
      • Modo Vista previa (Viewer)
      • Ayuda
      • Preguntas frecuentes (FAQ)
      • Punto de inicio
    • LCC Model Editor

      • Versión y actualizaciones
      • Guía del usuario
      • Visión general e interfaz
      • Operaciones de archivo
      • Selectores
      • Edición de modelos
      • Medición
      • Corrección de color
      • Gestión de activos
      • Configuración y ayuda
      • Preguntas frecuentes
    • Capture Guide

      • Descripción general
      • Descripción general de los dispositivos de captura
      • Principios generales de captura
      • Captura de escenas interiores
      • Captura de escenas exteriores
      • Captura a gran escala (Map Fusion)
      • Captura con aerial-ground map fusion
      • Captura de objetos
      • Captura de personas
      • Captura para reconstrucción a partir de vídeo
      • HD Enhancement
      • Puntos de control (Lixel P1)
      • Preguntas frecuentes y resolución de problemas
    • Buenas Prácticas

      • Fusión de varios modelos 3DGS de gran tamaño
    • Historial de versiones
  • Plugins y SDK

    • Unreal

      • Introducción
      • Inicio rápido - Windows
      • Inicio rápido - Linux
      • Inicio rápido - Quest3
      • Ediciones y licencias
      • Renderizado
      • Rasterización Tiled (experimental)
      • Ajustes visuales
      • Normales e iluminación
      • Edición de escenas
      • Parámetros de rendimiento
      • Guía de rendimiento
      • Integración con plugins de terceros y del motor
      • Proxy Mesh
      • Animación de carga
      • Colisión
      • Compatibilidad con Navigation System
      • Compatibilidad con Single Layer Water
      • Localización
      • Preguntas frecuentes
      • Resolución de problemas
      • Logs y diagnóstico
      • Contacto
      • Buenas prácticas

        • Reiluminar 3DGS con una malla de LixelStudio
      • Referencia de API

        • ALCCActorBase
        • ULCCComponentBase
        • ULCCComponent
        • ULCC2Component
        • Actors SOG / SPZ / PLY
        • ALCC2ProxyMesh
        • ALCCClippingVolume
        • ALCCSectionPlane
        • ALCCLoadVolume
        • ULCCUtilLibrary
        • Enumeraciones
        • Structs
      • Registro de cambios

        • v3.4.0
        • v3.3.1
        • v3.0.0
        • v2.2.1
        • v1.0.0
        • v0.9.0
        • v0.8.0
        • v0.7.1
        • v0.6.1
        • v0.5.2
        • v0.4.1
        • v0.4.0
        • v0.3.0
        • v0.0.5
        • v0.0.4
        • v0.0.3
        • v0.0.2
        • v0.0.1
    • Unity

      • Introducción al SDK de Unity
      • Funciones técnicas
      • Requisitos del entorno de desarrollo
      • Guía de inicio rápido para PC
      • Guía de optimización de ajustes del proyecto
      • Guía de desarrollo para Pico 4 Ultra
      • Guía de streaming desde PC para Pico 4 Ultra
      • Guía de desarrollo para Quest 3
      • Guía de streaming desde PC para Quest 3
      • Guía de desarrollo con OpenXR
      • Guía de Business Streaming para Pico 4 Ultra
      • Glosario
      • Preguntas frecuentes
      • Contáctanos
      • Guía de desarrollo de funciones

        • Guía de desarrollo de renderizado mixto de varias escenas
        • Guía de desarrollo de recepción de sombras
        • Guía de desarrollo de iluminación en tiempo real
        • Guía de desarrollo de renderizado multicámara
        • Guía de desarrollo de renderizado de imágenes de alta resolución
        • Guía de desarrollo de compatibilidad de formatos de datos LCC y LCC2
        • Guía de desarrollo del efecto de carga
        • Guía de desarrollo de cambio de modo de renderizado Mip
        • Guía de desarrollo de ajuste a bordes y esquinas
        • Guía de desarrollo de decal proyectado
        • Guía de desarrollo de decal proyectado de vídeo
        • Guía de desarrollo de resaltado
        • Guía de desarrollo de recorte en tiempo real
        • Guía de desarrollo de ajuste de color
        • Guía de desarrollo para obtener los datos de malla de la escena
        • Guía de desarrollo del modo Editor
        • Guía de configuración de parámetros de rendimiento de renderizado
        • Guía de desarrollo de co-empaquetado de aplicación y datos
        • Guía de desarrollo del sistema de colisiones
        • Guía de problemas de permisos de desarrollo en macOS
        • Guía de desarrollo de compilación y empaquetado para dispositivos iOS
      • Referencia de API

        • LCCManager
        • Renderer
        • Tipos de datos
      • Registro de cambios

        • v2.3.0
        • v2.2.10
        • v2.2.0
        • v2.1.19
        • v2.0.14
    • Web

      • Introducción
      • Guía de optimización del rendimiento de renderizado
      • Configuración de gráficos
      • Preguntas frecuentes
      • Referencia de API

        • LCCRender::clearIndexDB
        • LCCRender::dispose
        • LCCRender::load
        • LCCRender::setCamera
        • LCCRender::unload
        • LCCRender::update
        • LCCObject::checkRenderNextFrame
        • LCCObject::clearRenderNextFrame
        • LCCObject::ecef2Prj
        • LCCObject::getBounds
        • LCCObject::getEnvInstancedMesh
        • LCCObject::getInstancedMesh
        • LCCObject::getLodInfos
        • LCCObject::getOriginPosition
        • LCCObject::getProjectionCoordinateSystemInfos
        • LCCObject::hasCollision
        • LCCObject::hasEnvironment
        • LCCObject::hasShcoef
        • LCCObject::intersectsCapsule
        • LCCObject::intersectsRayExt
        • LCCObject::intersectsRayFromOriginExt
        • LCCObject::intersectsSphere
        • LCCObject::lowerToBottom
        • LCCObject::prj2Ecef
        • LCCObject::raiseToTop
        • LCCObject::raycast
        • LCCObject::raycastFromOrigin
        • LCCObject::setAlpha
        • LCCObject::setClipBox
        • LCCObject::setClipPlane
        • LCCObject::setEndLod
        • LCCObject::setLodAutoLevelUp
        • LCCObject::setMaxDistance
        • LCCObject::setMaxNodeSplats
        • LCCObject::setMaxSplats
        • LCCObject::setOriginPosition
        • LCCObject::setPointsColor
        • LCCObject::setRenderState
        • LCCObject::setRotation
        • LCCObject::setScale
        • LCCObject::setSemantic
        • LCCObject::setSemanticColor
        • LCCObject::setSmooth
        • LCCObject::setStartLod
        • LCCObject::setTranslation
        • LCCObject::setVisible
        • LCCObject::togglePointsDisplayMode
        • LCCObject::useEnvironment
        • LCCObject::useShcoef
      • Registro de cambios

        • v0.6.3
        • v0.6.2
        • v0.6.1
        • v0.6.0
        • v0.5.5
        • v0.5.4
        • v0.5.3
        • v0.5.2
        • v0.5.1
        • v0.5.0
        • v0.4.1
        • v0.4.0
        • v0.3.1
        • v0.3.0
        • v0.2.0

Guía de desarrollo de ajuste a bordes y esquinas

El LCC Unity SDK admite la detección de bordes y esquinas y la previsualización de ajuste en superficies 3DGS, que pueden usarse en escenarios de interacción que requieren un posicionamiento preciso, como medición, anotación y colocación. A continuación se describen los pasos completos para implementar la detección y el ajuste de bordes/esquinas.

Nota:

La función de ajuste (detección de bordes/esquinas, previsualización de ajuste y raycasting con ajuste) solo es compatible con plataformas PC / Mac. Llamar a las API relacionadas en plataformas móviles / VR no surte efecto y emite una advertencia.

Paso 1: Crear la escena y los GameObjects

Crea una escena completamente nueva en Unity. Unity crea Main Camera y Directional Light por defecto.

Configurar Main Camera

Selecciona Main Camera en la ventana Jerarquía y establece sus propiedades en la ventana Inspector como se muestra a continuación.

Establecer las propiedades de Main Camera

Establecer las propiedades de Main Camera

Crear LCCManager

Haz clic con el botón derecho en un área vacía de la ventana Jerarquía, selecciona Create Empty en el menú emergente para crear un GameObject vacío, nómbralo LCCManager, normaliza su Transform y añádele el script LCCManager mediante Agregar componente.

Crear el GameObject LCCManager y añadir el script LCCManager

Crear el GameObject LCCManager y añadir el script LCCManager

Crear LCCRenderer

Haz clic con el botón derecho en un área vacía de la ventana Jerarquía, selecciona Create Empty para crear un GameObject vacío, nómbralo LCCRenderer y establece su Transform como Rotation.x = -90 y Scale.x = -1.

Crear LCCRenderer y establecer su Transform

Crear LCCRenderer y establecer su Transform (Rotation.x = -90, Scale.x = -1)

Nota:

Los ajustes de Transform del GameObject LCCRenderer (Rotation.x = -90, Scale.x = -1) lo alinean con el sistema de coordenadas de los datos LCC. Para más detalles sobre la alineación del sistema de coordenadas, consulta "Sistema de coordenadas de los datos LCC" en Introducción al SDK de Unity.

Paso 2: Añadir un Render Feature

  1. En la barra de menús de Unity, selecciona Archivo → Ajustes del proyecto, elige Gráficos a la izquierda y confirma el Default Render Pipeline Asset actual. Este ejemplo usa URP (Universal Render Pipeline Asset).
Confirmar el Default Render Pipeline Asset en los ajustes de Gráficos

Confirmar el Default Render Pipeline Asset en los ajustes de Gráficos

  1. Haz clic en ese Asset, localiza el archivo de asset correspondiente en la ventana Proyecto y encuentra su Renderer asociado (URP_Renderer.asset en este ejemplo).

  2. Selecciona ese archivo de asset del Renderer, haz clic en Add Renderer Feature en la ventana Inspector y añade el Snap Frame Capture Feature.

Añadir el Snap Frame Capture Feature al URP Renderer

Añadir el Snap Frame Capture Feature al URP Renderer

Paso 3: Escribir un script para activar el ajuste

Crea un nuevo script C# llamado Snap.cs con el siguiente código:

using LCCCore;
using UnityEngine;

public class Snap : MonoBehaviour
{
    public LCCManager m_manager;
    public string m_FilePath;
    private LCCCore.Renderer m_renderer;
    private bool m_loaded = false;
    private Camera m_camera;

    void Start()
    {
        m_camera = Camera.main;
        m_manager.SetPlatformType(PlatformType.PC);
        Debug.Log("Iniciado ");
        m_renderer = m_manager.GetRender(this.transform);
        m_renderer.Load(m_FilePath, onProgress, onComplete);
    }

    private void onProgress(float _progress)
    {
        Debug.Log($"[LCCRenderer] progreso de carga del archivo: {_progress:P1}");
    }

    private void onComplete()
    {
        Debug.Log($"[LCCRenderer] archivo cargado");
        m_loaded = true;
        // Activa la detección de bordes/esquinas y la previsualización de ajuste
        m_manager.SetSnapEnabled(true);
        m_manager.SetSnapPreviewEnabled(true);
    }

    private void Update()
    {
        if (!m_loaded) return;
        // Actualiza la previsualización de ajuste en tiempo real según la posición actual del ratón
        m_manager.UpdateSnapPreview(Input.mousePosition, m_camera);
        if (Input.GetMouseButtonDown(1))
        {
            m_manager.RaycastWithSnap(Input.mousePosition, m_camera, out HitResult result);
            if (result.isHit)
            {
                GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                sphere.transform.position = result.hitPos;
                sphere.GetComponent<UnityEngine.Renderer>().material.color = Color.red;
                sphere.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
            }
        }
    }
}

Nota:

La detección de bordes/esquinas (SetSnapEnabled) y la previsualización de ajuste (SetSnapPreviewEnabled) deben activarse después de que la escena LCC termine de cargarse, por lo que ambas se llaman en la devolución de llamada onComplete. La previsualización de ajuste también necesita actualizarse continuamente mediante UpdateSnapPreview en Update.

El ejemplo anterior demuestra los siguientes puntos:

  • Activar la detección de bordes y esquinas: m_manager.SetSnapEnabled(true)
  • Activar la previsualización de ajuste: m_manager.SetSnapPreviewEnabled(true)
  • Actualizar la previsualización de ajuste en tiempo real: m_manager.UpdateSnapPreview(Input.mousePosition, m_camera)
  • Hacer raycast en el punto de ajuste y crear una esfera en el punto de impacto: m_manager.RaycastWithSnap(...); al impactar, se crea una esfera roja en result.hitPos

Paso 4: Adjuntar el script y establecer la ruta de datos

  1. Adjunta el script Snap.cs al GameObject LCCRenderer en la ventana Jerarquía.
  2. En la ventana Inspector, arrastra el GameObject LCCManager a la propiedad Manager del script.
  3. Rellena la ruta del archivo LCC en la propiedad File Path del script.

Paso 5: Ejecutar

Haz clic en el botón Play de la ventana Game para ver los bordes y esquinas detectados en tiempo real y el icono de previsualización del objetivo de ajuste. Al mover el ratón, el icono de previsualización sigue al objetivo de ajuste más cercano en tiempo real; al hacer clic derecho se realiza un raycast en el punto de ajuste y se crea una esfera roja.

Bordes, esquinas e icono de previsualización de ajuste detectados en tiempo real tras la ejecución

Bordes, esquinas e icono de previsualización de ajuste detectados en tiempo real tras la ejecución

Preguntas frecuentes: desactivar el modo de compatibilidad

Si la ventana Console de Unity informa de errores y no aparece ningún icono de previsualización de ajuste, desactiva el modo de compatibilidad: abre el panel de ajustes mediante Editar → Ajustes del proyecto → Gráficos, selecciona la pestaña URP y no marques la casilla situada después de Render Graph → Compatibility Mode (Render Graph Disabled).

No marcar el modo de compatibilidad de Render Graph

No marcar el modo de compatibilidad de Render Graph (Render Graph Disabled)

Pasos clave

Los pasos clave para implementar la detección y el ajuste de bordes/esquinas:

  1. Asegúrate de que el Snap Frame Capture Feature se ha añadido al URP Renderer.
  2. Asegúrate de que la detección de bordes/esquinas (SetSnapEnabled(true)) y la previsualización de ajuste (SetSnapPreviewEnabled(true)) se activan en el código después de que la escena LCC termine de cargarse.
  3. Asegúrate de que UpdateSnapPreview se llama en tiempo real en Update para actualizar el icono de previsualización.

API relacionadas con el ajuste

El LCC Unity SDK proporciona las siguientes API relacionadas con el ajuste a través de LCCManager. Solo son compatibles con plataformas PC / Mac — llamarlas en plataformas móviles / VR no surte efecto y emite una advertencia — y todas deben llamarse después de que la escena LCC termine de cargarse.

SetSnapEnabled

// Valor de retorno: void
public void SetSnapEnabled(bool enable)

Activa o desactiva la función de ajuste. Cuando está activada, RaycastWithSnap busca automáticamente bordes/esquinas cercanos a los que ajustarse.

ParámetroTipoDescripción
enableboolSi se habilita el ajuste

Ejemplo de uso:

m_manager.SetSnapEnabled(true);

Notas:

  • Desactivado por defecto.
  • Solo compatible con PC / Mac; llamarla en móvil / VR no surte efecto y emite una advertencia.
  • Cuando está activada, se asignan recursos de GPU (EdgeDetect / CornerDetect / SnapSearch).

SetSnapRadius

// Valor de retorno: void
public void SetSnapRadius(float pixels)

Establece el radio de búsqueda del ajuste. El borde/esquina más cercano se busca dentro de este rango de píxeles.

ParámetroTipoDescripción
pixelsfloatRadio de búsqueda del ajuste (píxeles)

Ejemplo de uso:

m_manager.SetSnapRadius(30f);

Notas:

  • El valor por defecto es 20 píxeles.
  • Cuanto mayor es el valor, más amplio es el rango de búsqueda, pero puede ajustarse a objetivos no deseados.
  • Solo compatible con PC / Mac.

SetEdgeThreshold

// Valor de retorno: void
public void SetEdgeThreshold(float threshold)

Establece el umbral de detección de bordes de Sobel. Cuanto menor es el valor, más bordes se detectan.

ParámetroTipoDescripción
thresholdfloatUmbral de detección de bordes

Ejemplo de uso:

m_manager.SetEdgeThreshold(0.2f);

Notas:

  • El valor por defecto es 0.3.
  • Rango recomendado [0.1, 0.8].
  • Un valor demasiado pequeño produce muchos bordes ruidosos.
  • Solo compatible con PC / Mac.

SetSnapPreviewEnabled

// Valor de retorno: void
public void SetSnapPreviewEnabled(bool enable)

Activa o desactiva la función de previsualización de ajuste. Cuando está activada, el indicador del objetivo de ajuste más cercano se muestra en tiempo real a medida que se mueve el ratón.

ParámetroTipoDescripción
enableboolSi se habilita la previsualización de ajuste

Ejemplo de uso:

m_manager.SetSnapPreviewEnabled(true);

Notas:

  • Requiere que SetSnapEnabled(true) se llame primero.
  • La previsualización consume continuamente recursos de GPU (detección cada fotograma).
  • Solo compatible con PC / Mac.

UpdateSnapPreview

// Valor de retorno: void
public void UpdateSnapPreview(Vector2 mousePos, Camera cam)

Actualiza el estado de la previsualización de ajuste. Llámala a medida que se mueve el ratón para actualizar la posición del indicador de previsualización.

ParámetroTipoDescripción
mousePosVector2Coordenada de pantalla actual del ratón
camCameraCámara

Ejemplo de uso:

void Update()
{
    m_manager.UpdateSnapPreview(Input.mousePosition, Camera.main);
}

Notas:

  • Requiere que SetSnapPreviewEnabled(true) se llame primero.
  • Se recomienda llamarla continuamente en Update.
  • Solo compatible con PC / Mac.

GetSnapPreviewState

// Valor de retorno: SnapPreviewState (screenPos está en coordenadas de pantalla)
public SnapPreviewState GetSnapPreviewState()

Obtiene el estado actual de la previsualización de ajuste, incluido si hay un objetivo de ajuste, el tipo de objetivo, la posición en pantalla del objetivo y la distancia en píxeles al ratón.

Ejemplo de uso:

var state = m_manager.GetSnapPreviewState();
if (state.hasTarget)
{
    // state.snapType: Corner / Edge
    // state.screenPos: posición en pantalla del objetivo de ajuste
    // state.distanceToMouse: distancia en píxeles
}

Notas:

  • Requiere que SetSnapPreviewEnabled(true) y UpdateSnapPreview se llamen primero.
  • Devuelve default(SnapPreviewState) cuando no hay objetivo.
  • screenPos es una coordenada de pantalla, no una coordenada de mundo; si necesitas la coordenada de mundo, usa RaycastWithSnap para obtener HitResult.hitPos.
  • Solo compatible con PC / Mac.

RaycastWithSnap

// Valor de retorno: bool (true = impacto)
public bool RaycastWithSnap(Vector2 screenPos, Camera cam, out HitResult result)

Raycasting con ajuste. Primero realiza un raycast normal y luego busca bordes/esquinas cerca del punto de impacto a los que ajustarse.

ParámetroTipoDescripción
screenPosVector2Coordenada de pantalla
camCameraCámara
resultout HitResultResultado del impacto (incluye información de ajuste)

Ejemplo de uso:

if (m_manager.RaycastWithSnap(Input.mousePosition, m_camera, out HitResult hit))
{
    // hit.snapType: Corner / Edge / None
    // hit.hitPos: posición en el mundo después del ajuste
    // hit.originalHitPos: punto de impacto original antes del ajuste
}

Notas:

  • Requiere que SetSnapEnabled(true) se llame primero.
  • Prioridad de ajuste: Corner > Edge > None.
  • Este punto de entrada bloquea síncronamente el hilo principal (esperando el resultado de lectura de la GPU); se recomienda llamarlo solo en eventos de interacción (como clics), no en cada fotograma.
  • En modo de previsualización (SetSnapPreviewEnabled(true)), si ya existe un objetivo de ajuste, se reutiliza la caché de previsualización directamente sin recalcular; de lo contrario, se usa el flujo de ajuste normal.
  • Solo compatible con PC / Mac.

Estructuras de datos relacionadas

SnapType

public enum SnapType { None, Edge, Corner }

Tipo de objetivo de ajuste: ninguno / borde / esquina.

SnapPreviewState

public struct SnapPreviewState {
    public bool hasTarget;          // si hay un objetivo de ajuste
    public SnapType snapType;       // None / Edge / Corner
    public Vector2 screenPos;       // posición en pantalla del objetivo de ajuste (no es posición de mundo)
    public float distanceToMouse;   // distancia en píxeles a la posición del ratón
}

⚠️ screenPos es una coordenada de píxel en pantalla, no una coordenada de mundo. Si necesitas la coordenada de mundo, usa RaycastWithSnap para obtener HitResult.hitPos.

HitResult

public struct HitResult {
    public bool isHit;             // si hubo impacto
    public float distance;         // distancia
    public Vector3 hitPos;         // posición en el mundo del punto de impacto (el nombre del campo es hitPos, no position)
    public Vector3 normal;         // normal del impacto
    public float hitAlpha;         // alfa del elipsoide impactado
    public float dist2Origin;      // distancia al origen del rayo
    public float scale;            // escala del elipsoide
    public SnapType snapType;      // tipo de ajuste (None / Edge / Corner)
    public Vector3 originalHitPos; // punto de impacto original antes del ajuste
}

⚠️ Diferencia en el nombre del campo: el campo de la posición en el mundo del punto de impacto es hitPos (no position); los llamadores deben acceder a él usando el nombre de campo real.