Guida allo sviluppo dello snap a bordi e angoli
L'LCC Unity SDK supporta il rilevamento di bordi e angoli e l'anteprima di snap sulle superfici 3DGS, utilizzabili in scenari di interazione che richiedono un posizionamento preciso come misurazione, annotazione e posizionamento. Di seguito vengono descritti i passaggi completi per implementare il rilevamento e lo snap di bordi/angoli.
Nota:
La funzionalità di snap (rilevamento di bordi/angoli, anteprima di snap e raycasting con snap) è supportata solo sulle piattaforme PC / Mac. La chiamata delle API correlate sulle piattaforme mobile / VR non ha effetto e produce un avviso.
Passaggio 1: crea la scena e i GameObject
Crea una scena completamente nuova in Unity. Unity crea Camera principale e Luce direzionale per impostazione predefinita.
Configura la Camera principale
Seleziona Camera principale nella finestra Gerarchia e imposta le sue proprietà nella finestra Inspector come mostrato di seguito.

Imposta le proprietà della Camera principale
Crea LCCManager
Fai clic con il pulsante destro su un'area vuota nella finestra Gerarchia, seleziona Crea vuoto dal menu a comparsa per creare un GameObject vuoto, assegna il nome LCCManager, normalizza il suo Transform e aggiungi lo script LCCManager tramite Aggiungi componente.

Crea il GameObject LCCManager e aggiungi lo script LCCManager
Crea LCCRenderer
Fai clic con il pulsante destro su un'area vuota nella finestra Gerarchia, seleziona Crea vuoto per creare un GameObject vuoto, assegna il nome LCCRenderer e imposta il suo Transform su Rotation.x = -90 e Scale.x = -1.

Crea LCCRenderer e imposta il suo Transform (Rotation.x = -90, Scale.x = -1)
Nota:
Le impostazioni Transform del GameObject LCCRenderer (Rotation.x = -90, Scale.x = -1) lo allineano al sistema di coordinate dei dati LCC. Per i dettagli sull'allineamento del sistema di coordinate, vedi "Sistema di coordinate dei dati LCC" in Introduzione all'Unity SDK.
Passaggio 2: aggiungi una Render Feature
- Nella barra dei menu di Unity, seleziona File → Impostazioni progetto, scegli Graphics a sinistra e conferma il Default Render Pipeline Asset corrente. Questo esempio usa URP (Universal Render Pipeline Asset).

Conferma il Default Render Pipeline Asset nelle impostazioni Graphics
Fai clic su quell'Asset, individua il file asset corrispondente nella finestra Progetto e trova il suo Renderer associato (
URP_Renderer.assetin questo esempio).Seleziona quel file asset Renderer, fai clic su Aggiungi Renderer Feature nella finestra Inspector e aggiungi la Snap Frame Capture Feature.

Aggiungi la Snap Frame Capture Feature al Renderer URP
Passaggio 3: scrivi uno script per abilitare lo snap
Crea un nuovo script C# denominato Snap.cs con il seguente codice:
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("Avviato ");
m_renderer = m_manager.GetRender(this.transform);
m_renderer.Load(m_FilePath, onProgress, onComplete);
}
private void onProgress(float _progress)
{
Debug.Log($"[LCCRenderer] avanzamento caricamento file: {_progress:P1}");
}
private void onComplete()
{
Debug.Log($"[LCCRenderer] file caricato");
m_loaded = true;
// Abilita il rilevamento di bordi/angoli e l'anteprima di snap
m_manager.SetSnapEnabled(true);
m_manager.SetSnapPreviewEnabled(true);
}
private void Update()
{
if (!m_loaded) return;
// Aggiorna l'anteprima di snap in tempo reale in base alla posizione corrente del mouse
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:
Il rilevamento di bordi/angoli (
SetSnapEnabled) e l'anteprima di snap (SetSnapPreviewEnabled) devono essere abilitati dopo che la scena LCC ha terminato il caricamento, quindi entrambi vengono chiamati nel callbackonComplete. L'anteprima di snap deve inoltre essere aggiornata continuamente tramiteUpdateSnapPreviewinUpdate.
L'esempio precedente dimostra i seguenti punti:
- Abilita il rilevamento di bordi e angoli:
m_manager.SetSnapEnabled(true) - Abilita l'anteprima di snap:
m_manager.SetSnapPreviewEnabled(true) - Aggiorna l'anteprima di snap in tempo reale:
m_manager.UpdateSnapPreview(Input.mousePosition, m_camera) - Raycast nel punto di snap e crea una sfera nel punto colpito:
m_manager.RaycastWithSnap(...); in caso di impatto, una sfera rossa viene creata inresult.hitPos
Passaggio 4: associa lo script e imposta il percorso dati
- Associa lo script
Snap.csal GameObject LCCRenderer nella finestra Gerarchia. - Nella finestra Inspector, trascina il GameObject LCCManager sulla proprietà Manager dello script.
- Inserisci il percorso del file LCC nella proprietà File Path dello script.
Passaggio 5: esegui
Fai clic sul pulsante Play nella finestra Game per vedere i bordi e gli angoli rilevati in tempo reale e l'icona di anteprima dell'obiettivo di snap. Mentre muovi il mouse, l'icona di anteprima segue l'obiettivo di snap più vicino in tempo reale; facendo clic con il pulsante destro viene eseguito un raycast nel punto di snap e viene creata una sfera rossa.

Bordi, angoli e icona di anteprima dello snap rilevati in tempo reale dopo l'esecuzione
FAQ: disabilita la modalità di compatibilità
Se la finestra Console di Unity segnala errori e non appare alcuna icona di anteprima dello snap, disabilita la modalità di compatibilità: apri il pannello delle impostazioni tramite Modifica → Impostazioni progetto → Graphics, seleziona la scheda URP e non selezionare la casella dopo Render Graph → Compatibility Mode (Render Graph Disabled).

Non selezionare la modalità di compatibilità Render Graph (Render Graph Disabled)
Punti chiave
I passaggi chiave per implementare il rilevamento e lo snap di bordi/angoli:
- Assicurati che la Snap Frame Capture Feature sia stata aggiunta al Renderer URP.
- Assicurati che il rilevamento di bordi/angoli (
SetSnapEnabled(true)) e l'anteprima di snap (SetSnapPreviewEnabled(true)) siano abilitati nel codice dopo che la scena LCC ha terminato il caricamento. - Assicurati che
UpdateSnapPreviewvenga chiamato in tempo reale inUpdateper aggiornare l'icona di anteprima.
API relative allo snap
L'LCC Unity SDK fornisce le seguenti API relative allo snap tramite LCCManager. Sono supportate solo sulle piattaforme PC / Mac — la loro chiamata sulle piattaforme mobile / VR non ha effetto e produce un avviso — e devono essere tutte chiamate dopo che la scena LCC ha terminato il caricamento.
SetSnapEnabled
// Valore restituito: void
public void SetSnapEnabled(bool enable)
Attiva/disattiva la funzionalità di snap. Quando è abilitata, RaycastWithSnap cerca automaticamente i bordi/angoli vicini a cui agganciarsi.
| Parametro | Tipo | Descrizione |
|---|---|---|
enable | bool | Indica se abilitare lo snap |
Esempio di utilizzo:
m_manager.SetSnapEnabled(true);
Note:
- Disabilitata per impostazione predefinita.
- Supportata solo su PC / Mac; la chiamata su mobile / VR non ha effetto e produce un avviso.
- Quando è abilitata, vengono allocate risorse GPU (EdgeDetect / CornerDetect / SnapSearch).
SetSnapRadius
// Valore restituito: void
public void SetSnapRadius(float pixels)
Imposta il raggio di ricerca dello snap. Il bordo/angolo più vicino viene cercato entro questo intervallo di pixel.
| Parametro | Tipo | Descrizione |
|---|---|---|
pixels | float | Raggio di ricerca dello snap (pixel) |
Esempio di utilizzo:
m_manager.SetSnapRadius(30f);
Note:
- Il valore predefinito è 20 pixel.
- Maggiore è il valore, più ampio è l'intervallo di ricerca, ma potrebbe agganciarsi a obiettivi non voluti.
- Supportata solo su PC / Mac.
SetEdgeThreshold
// Valore restituito: void
public void SetEdgeThreshold(float threshold)
Imposta la soglia di rilevamento dei bordi Sobel. Minore è il valore, maggiore è il numero di bordi rilevati.
| Parametro | Tipo | Descrizione |
|---|---|---|
threshold | float | Soglia di rilevamento dei bordi |
Esempio di utilizzo:
m_manager.SetEdgeThreshold(0.2f);
Note:
- Il valore predefinito è 0.3.
- Intervallo consigliato
[0.1, 0.8]. - Un valore troppo piccolo produce molti bordi rumorosi.
- Supportata solo su PC / Mac.
SetSnapPreviewEnabled
// Valore restituito: void
public void SetSnapPreviewEnabled(bool enable)
Attiva/disattiva la funzionalità di anteprima di snap. Quando è abilitata, l'indicatore dell'obiettivo di snap più vicino viene visualizzato in tempo reale mentre il mouse si muove.
| Parametro | Tipo | Descrizione |
|---|---|---|
enable | bool | Indica se abilitare l'anteprima di snap |
Esempio di utilizzo:
m_manager.SetSnapPreviewEnabled(true);
Note:
- Richiede che
SetSnapEnabled(true)venga chiamato prima. - L'anteprima consuma continuamente risorse GPU (rilevamento a ogni fotogramma).
- Supportata solo su PC / Mac.
UpdateSnapPreview
// Valore restituito: void
public void UpdateSnapPreview(Vector2 mousePos, Camera cam)
Aggiorna lo stato dell'anteprima di snap. Chiamalo mentre il mouse si muove per aggiornare la posizione dell'indicatore di anteprima.
| Parametro | Tipo | Descrizione |
|---|---|---|
mousePos | Vector2 | Coordinata schermo corrente del mouse |
cam | Camera | Camera |
Esempio di utilizzo:
void Update()
{
m_manager.UpdateSnapPreview(Input.mousePosition, Camera.main);
}
Note:
- Richiede che
SetSnapPreviewEnabled(true)venga chiamato prima. - Si consiglia di chiamarlo continuamente in
Update. - Supportata solo su PC / Mac.
GetSnapPreviewState
// Valore restituito: SnapPreviewState (screenPos è in coordinate schermo)
public SnapPreviewState GetSnapPreviewState()
Ottiene lo stato corrente dell'anteprima di snap, incluso se è presente un obiettivo di snap, il tipo di obiettivo, la posizione schermo dell'obiettivo e la distanza in pixel dal mouse.
Esempio di utilizzo:
var state = m_manager.GetSnapPreviewState();
if (state.hasTarget)
{
// state.snapType: Corner / Edge
// state.screenPos: posizione schermo dell'obiettivo di snap
// state.distanceToMouse: distanza in pixel
}
Note:
- Richiede che
SetSnapPreviewEnabled(true)eUpdateSnapPreviewvengano chiamati prima. - Restituisce
default(SnapPreviewState)quando non è presente alcun obiettivo. screenPosè una coordinata schermo, non una coordinata mondo; se hai bisogno della coordinata mondo, usaRaycastWithSnapper ottenereHitResult.hitPos.- Supportata solo su PC / Mac.
RaycastWithSnap
// Valore restituito: bool (true = impatto)
public bool RaycastWithSnap(Vector2 screenPos, Camera cam, out HitResult result)
Raycasting con snap. Prima esegue un Raycast normale, poi cerca i bordi/angoli vicino al punto colpito a cui agganciarsi.
| Parametro | Tipo | Descrizione |
|---|---|---|
screenPos | Vector2 | Coordinata schermo |
cam | Camera | Camera |
result | out HitResult | Risultato dell'impatto (incluse le informazioni di snap) |
Esempio di utilizzo:
if (m_manager.RaycastWithSnap(Input.mousePosition, m_camera, out HitResult hit))
{
// hit.snapType: Corner / Edge / None
// hit.hitPos: posizione mondo dopo lo snap
// hit.originalHitPos: punto colpito originale prima dello snap
}
Note:
- Richiede che
SetSnapEnabled(true)venga chiamato prima. - Priorità di snap: Corner > Edge > None.
- Questo punto di ingresso blocca in modo sincrono il thread principale (in attesa del risultato di readback GPU); si consiglia di chiamarlo solo sugli eventi di interazione (come i clic), non a ogni fotogramma.
- In modalità anteprima (
SetSnapPreviewEnabled(true)), se esiste già un obiettivo di snap, la cache di anteprima viene riutilizzata direttamente senza ricalcolo; in caso contrario viene usato il normale flusso di snap. - Supportata solo su PC / Mac.
Strutture dati correlate
SnapType
public enum SnapType { None, Edge, Corner }
Tipo di obiettivo di snap: nessuno / bordo / angolo.
SnapPreviewState
public struct SnapPreviewState {
public bool hasTarget; // se è presente un obiettivo di snap
public SnapType snapType; // None / Edge / Corner
public Vector2 screenPos; // posizione schermo dell'obiettivo di snap (non posizione mondo)
public float distanceToMouse; // distanza in pixel dalla posizione del mouse
}
⚠️
screenPosè una coordinata pixel dello schermo, non una coordinata mondo. Se hai bisogno della coordinata mondo, usaRaycastWithSnapper ottenereHitResult.hitPos.
HitResult
public struct HitResult {
public bool isHit; // se ha colpito
public float distance; // distanza
public Vector3 hitPos; // posizione mondo del punto colpito (il nome del campo è hitPos, non position)
public Vector3 normal; // normale del punto colpito
public float hitAlpha; // alfa dell'ellissoide colpito
public float dist2Origin; // distanza dall'origine del raggio
public float scale; // scala dell'ellissoide
public SnapType snapType; // tipo di snap (None / Edge / Corner)
public Vector3 originalHitPos; // punto colpito originale prima dello snap
}
⚠️ Differenza di denominazione del campo: il campo per la posizione mondo del punto colpito è
hitPos(nonposition); i chiamanti devono accedervi usando il nome effettivo del campo.