Przewodnik przyciągania do krawędzi i narożników
LCC Unity SDK obsługuje wykrywanie krawędzi i narożników oraz podgląd przyciągania na powierzchniach 3DGS, co można wykorzystać w scenariuszach interakcji wymagających precyzyjnego pozycjonowania, takich jak pomiary, adnotacje i umieszczanie. Poniżej opisano kompletne kroki implementacji wykrywania krawędzi/narożników i przyciągania.
Uwaga:
Funkcja przyciągania (wykrywanie krawędzi/narożników, podgląd przyciągania i raycasting z przyciąganiem) jest obsługiwana tylko na platformach PC / Mac. Wywoływanie powiązanych API na platformach mobilnych / VR nie ma efektu i wyświetla ostrzeżenie.
Krok 1: Utwórz scenę i GameObjects
Utwórz zupełnie nową scenę w Unity. Unity domyślnie tworzy Kamerę główną i Światło kierunkowe.
Skonfiguruj Kamerę główną
Wybierz Kamerę główną w oknie Hierarchia i ustaw jej właściwości w oknie Inspektor, jak pokazano poniżej.

Ustaw właściwości Kamery głównej
Utwórz LCCManager
Kliknij prawym przyciskiem myszy pusty obszar w oknie Hierarchia, wybierz Utwórz pusty z menu podręcznego, aby utworzyć pusty GameObject, nazwij go LCCManager, znormalizuj jego Transform i dodaj do niego skrypt LCCManager przez Dodaj komponent.

Utwórz GameObject LCCManager i dodaj skrypt LCCManager
Utwórz LCCRenderer
Kliknij prawym przyciskiem myszy pusty obszar w oknie Hierarchia, wybierz Utwórz pusty, aby utworzyć pusty GameObject, nazwij go LCCRenderer i ustaw jego Transform na Rotation.x = -90 i Scale.x = -1.

Utwórz LCCRenderer i ustaw jego Transform (Rotation.x = -90, Scale.x = -1)
Uwaga:
Ustawienia Transform GameObject LCCRenderer (Rotation.x = -90, Scale.x = -1) wyrównują go z układem współrzędnych danych LCC. Szczegóły wyrównania układu współrzędnych znajdziesz w sekcji „Układ współrzędnych danych LCC" w Wprowadzenie do Unity SDK.
Krok 2: Dodaj Render Feature
- Na pasku menu Unity wybierz Plik → Ustawienia projektu, po lewej stronie wybierz Grafika i potwierdź bieżący Domyślny zasób potoku renderowania. Ten przykład używa URP (Universal Render Pipeline Asset).

Potwierdź Domyślny zasób potoku renderowania w ustawieniach Grafiki
Kliknij ten zasób, zlokalizuj odpowiedni plik zasobu w oknie Projekt i znajdź jego powiązany Renderer (
URP_Renderer.assetw tym przykładzie).Wybierz ten plik zasobu Renderer, kliknij Dodaj Render Feature w oknie Inspektor i dodaj Snap Frame Capture Feature.

Dodaj funkcję Snap Frame Capture Feature do renderera URP
Krok 3: Napisz skrypt, aby włączyć przyciąganie
Utwórz nowy skrypt C# o nazwie Snap.cs z następującym kodem:
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("Uruchomiono ");
m_renderer = m_manager.GetRender(this.transform);
m_renderer.Load(m_FilePath, onProgress, onComplete);
}
private void onProgress(float _progress)
{
Debug.Log($"[LCCRenderer] postęp ładowania pliku: {_progress:P1}");
}
private void onComplete()
{
Debug.Log($"[LCCRenderer] plik załadowany");
m_loaded = true;
// Włącz wykrywanie krawędzi/narożników i podgląd przyciągania
m_manager.SetSnapEnabled(true);
m_manager.SetSnapPreviewEnabled(true);
}
private void Update()
{
if (!m_loaded) return;
// Aktualizuj podgląd przyciągania w czasie rzeczywistym na podstawie bieżącej pozycji myszy
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);
}
}
}
}
Uwaga:
Wykrywanie krawędzi/narożników (
SetSnapEnabled) i podgląd przyciągania (SetSnapPreviewEnabled) muszą być włączone po zakończeniu ładowania sceny LCC, więc oba są wywoływane w wywołaniu zwrotnymonComplete. Podgląd przyciągania musi być również stale aktualizowany przezUpdateSnapPreviewwUpdate.
Powyższy przykład demonstruje następujące punkty:
- Włącz wykrywanie krawędzi i narożników:
m_manager.SetSnapEnabled(true) - Włącz podgląd przyciągania:
m_manager.SetSnapPreviewEnabled(true) - Aktualizuj podgląd przyciągania w czasie rzeczywistym:
m_manager.UpdateSnapPreview(Input.mousePosition, m_camera) - Wykonaj raycast w punkcie przyciągania i utwórz kulę w punkcie trafienia:
m_manager.RaycastWithSnap(...); przy trafieniu wresult.hitPostworzona jest czerwona kula
Krok 4: Dołącz skrypt i ustaw ścieżkę danych
- Dołącz skrypt
Snap.csdo GameObject LCCRenderer w oknie Hierarchia. - W oknie Inspektor przeciągnij GameObject LCCManager na właściwość Manager skryptu.
- Wpisz ścieżkę pliku LCC we właściwości File Path skryptu.
Krok 5: Uruchom
Kliknij przycisk Odtwórz w oknie Gra, aby zobaczyć krawędzie i narożniki wykryte w czasie rzeczywistym oraz ikonę podglądu celu przyciągania. Gdy poruszasz myszą, ikona podglądu podąża za najbliższym celem przyciągania w czasie rzeczywistym; kliknięcie prawym przyciskiem wykonuje raycast w punkcie przyciągania i tworzy czerwoną kulę.

Krawędzie, narożniki i ikona podglądu przyciągania wykryte w czasie rzeczywistym po uruchomieniu
FAQ: Wyłącz tryb zgodności
Jeśli okno Konsola w Unity zgłasza błędy i nie pojawia się ikona podglądu przyciągania, wyłącz tryb zgodności: otwórz panel ustawień przez Edycja → Ustawienia projektu → Grafika, wybierz kartę URP i nie zaznaczaj pola wyboru po Render Graph → Tryb zgodności (Render Graph wyłączony).

Nie zaznaczaj trybu zgodności Render Graph (Render Graph wyłączony)
Kluczowe kroki
Kluczowe kroki implementacji wykrywania krawędzi/narożników i przyciągania:
- Upewnij się, że Snap Frame Capture Feature została dodana do renderera URP.
- Upewnij się, że wykrywanie krawędzi/narożników (
SetSnapEnabled(true)) i podgląd przyciągania (SetSnapPreviewEnabled(true)) są włączone w kodzie po zakończeniu ładowania sceny LCC. - Upewnij się, że
UpdateSnapPreviewjest wywoływane w czasie rzeczywistym wUpdate, aby aktualizować ikonę podglądu.
API powiązane z przyciąganiem
LCC Unity SDK udostępnia poniższe API powiązane z przyciąganiem przez LCCManager. Są one obsługiwane tylko na platformach PC / Mac — wywoływanie ich na platformach mobilnych / VR nie ma efektu i wyświetla ostrzeżenie — i wszystkie muszą być wywoływane po zakończeniu ładowania sceny LCC.
SetSnapEnabled
// Wartość zwracana: void
public void SetSnapEnabled(bool enable)
Przełącza funkcję przyciągania. Po włączeniu RaycastWithSnap automatycznie wyszukuje pobliskie krawędzie/narożniki do przyciągnięcia.
| Parametr | Typ | Opis |
|---|---|---|
enable | bool | Czy włączyć przyciąganie |
Przykład użycia:
m_manager.SetSnapEnabled(true);
Uwagi:
- Domyślnie wyłączone.
- Obsługiwane tylko na PC / Mac; wywołanie na mobilnych / VR nie ma efektu i wyświetla ostrzeżenie.
- Po włączeniu alokowane są zasoby GPU (EdgeDetect / CornerDetect / SnapSearch).
SetSnapRadius
// Wartość zwracana: void
public void SetSnapRadius(float pixels)
Ustawia promień wyszukiwania przyciągania. Najbliższa krawędź/narożnik jest wyszukiwana w tym zakresie pikseli.
| Parametr | Typ | Opis |
|---|---|---|
pixels | float | Promień wyszukiwania przyciągania (piksele) |
Przykład użycia:
m_manager.SetSnapRadius(30f);
Uwagi:
- Domyślnie 20 pikseli.
- Im większa wartość, tym szerszy zakres wyszukiwania, ale może przyciągać do niezamierzonych celów.
- Obsługiwane tylko na PC / Mac.
SetEdgeThreshold
// Wartość zwracana: void
public void SetEdgeThreshold(float threshold)
Ustawia próg wykrywania krawędzi Sobel. Im mniejsza wartość, tym więcej krawędzi jest wykrywanych.
| Parametr | Typ | Opis |
|---|---|---|
threshold | float | Próg wykrywania krawędzi |
Przykład użycia:
m_manager.SetEdgeThreshold(0.2f);
Uwagi:
- Domyślnie 0.3.
- Zalecany zakres
[0.1, 0.8]. - Zbyt mała wartość daje dużo zaszumionych krawędzi.
- Obsługiwane tylko na PC / Mac.
SetSnapPreviewEnabled
// Wartość zwracana: void
public void SetSnapPreviewEnabled(bool enable)
Przełącza funkcję podglądu przyciągania. Po włączeniu wskaźnik najbliższego celu przyciągania jest wyświetlany w czasie rzeczywistym podczas ruchu myszy.
| Parametr | Typ | Opis |
|---|---|---|
enable | bool | Czy włączyć podgląd przyciągania |
Przykład użycia:
m_manager.SetSnapPreviewEnabled(true);
Uwagi:
- Wymaga wcześniejszego wywołania
SetSnapEnabled(true). - Podgląd stale zużywa zasoby GPU (wykrywanie co klatkę).
- Obsługiwane tylko na PC / Mac.
UpdateSnapPreview
// Wartość zwracana: void
public void UpdateSnapPreview(Vector2 mousePos, Camera cam)
Aktualizuje stan podglądu przyciągania. Wywołuj podczas ruchu myszy, aby zaktualizować pozycję wskaźnika podglądu.
| Parametr | Typ | Opis |
|---|---|---|
mousePos | Vector2 | Bieżąca współrzędna ekranowa myszy |
cam | Camera | Kamera |
Przykład użycia:
void Update()
{
m_manager.UpdateSnapPreview(Input.mousePosition, Camera.main);
}
Uwagi:
- Wymaga wcześniejszego wywołania
SetSnapPreviewEnabled(true). - Zaleca się wywoływanie w sposób ciągły w
Update. - Obsługiwane tylko na PC / Mac.
GetSnapPreviewState
// Wartość zwracana: SnapPreviewState (screenPos jest we współrzędnych ekranu)
public SnapPreviewState GetSnapPreviewState()
Pobiera bieżący stan podglądu przyciągania, w tym informację o tym, czy istnieje cel przyciągania, typ celu, pozycję ekranową celu i odległość w pikselach do myszy.
Przykład użycia:
var state = m_manager.GetSnapPreviewState();
if (state.hasTarget)
{
// state.snapType: Narożnik / Krawędź
// state.screenPos: pozycja ekranowa celu przyciągania
// state.distanceToMouse: odległość w pikselach
}
Uwagi:
- Wymaga wcześniejszego wywołania
SetSnapPreviewEnabled(true)iUpdateSnapPreview. - Zwraca
default(SnapPreviewState), gdy nie ma celu. screenPosto współrzędna ekranowa, a nie współrzędna świata; jeśli potrzebujesz współrzędnej świata, użyjRaycastWithSnap, aby uzyskaćHitResult.hitPos.- Obsługiwane tylko na PC / Mac.
RaycastWithSnap
// Wartość zwracana: bool (true = trafienie)
public bool RaycastWithSnap(Vector2 screenPos, Camera cam, out HitResult result)
Raycasting z przyciąganiem. Najpierw wykonuje normalny Raycast, a następnie wyszukuje krawędzie/narożniki w pobliżu punktu trafienia do przyciągnięcia.
| Parametr | Typ | Opis |
|---|---|---|
screenPos | Vector2 | Współrzędna ekranowa |
cam | Camera | Kamera |
result | out HitResult | Wynik trafienia (w tym informacje o przyciąganiu) |
Przykład użycia:
if (m_manager.RaycastWithSnap(Input.mousePosition, m_camera, out HitResult hit))
{
// hit.snapType: Narożnik / Krawędź / Brak
// hit.hitPos: pozycja świata po przyciągnięciu
// hit.originalHitPos: pierwotny punkt trafienia przed przyciągnięciem
}
Uwagi:
- Wymaga wcześniejszego wywołania
SetSnapEnabled(true). - Priorytet przyciągania: Narożnik > Krawędź > Brak.
- Ten punkt wejścia synchronicznie blokuje wątek główny (czekając na wynik odczytu z GPU); zaleca się wywoływanie tylko przy zdarzeniach interakcji (takich jak kliknięcia), a nie co klatkę.
- W trybie podglądu (
SetSnapPreviewEnabled(true)), jeśli cel przyciągania już istnieje, używana jest bezpośrednio pamięć podręczna podglądu bez ponownego obliczania; w przeciwnym razie używany jest normalny przepływ przyciągania. - Obsługiwane tylko na PC / Mac.
Powiązane struktury danych
SnapType
public enum SnapType { None, Edge, Corner }
Typ celu przyciągania: brak / krawędź / narożnik.
SnapPreviewState
public struct SnapPreviewState {
public bool hasTarget; // czy istnieje cel przyciągania
public SnapType snapType; // Brak / Krawędź / Narożnik
public Vector2 screenPos; // pozycja ekranowa celu przyciągania (nie pozycja świata)
public float distanceToMouse; // odległość w pikselach do pozycji myszy
}
⚠️
screenPosto współrzędna pikselowa ekranu, a nie współrzędna świata. Jeśli potrzebujesz współrzędnej świata, użyjRaycastWithSnap, aby uzyskaćHitResult.hitPos.
HitResult
public struct HitResult {
public bool isHit; // czy trafiono
public float distance; // odległość
public Vector3 hitPos; // pozycja świata punktu trafienia (nazwa pola to hitPos, nie position)
public Vector3 normal; // normalna trafienia
public float hitAlpha; // alfa trafionej elipsoidy
public float dist2Origin; // odległość do początku promienia
public float scale; // skala elipsoidy
public SnapType snapType; // typ przyciągania (Brak / Krawędź / Narożnik)
public Vector3 originalHitPos; // pierwotny punkt trafienia przed przyciągnięciem
}
⚠️ Różnica w nazewnictwie pól: pole pozycji świata punktu trafienia to
hitPos(a nieposition); wywołujący powinni uzyskiwać do niego dostęp przy użyciu rzeczywistej nazwy pola.