Spisu treści:
- Krok 1: Rozpocznij nowy projekt Unity
- Krok 2: Skonfiguruj scenę
- Krok 3: Zróbmy trochę cząstek
- Krok 4: Spowolnienie cząstek
- Krok 5: Tworzenie portalu
- Krok 6: Shadery cząstek
- Krok 7: Utwórz Skybox
- Krok 8: Logika portalu
- Krok 9: Prawie gotowe
- Krok 10: Umieść aplikację na swoim telefonie
Wideo: Portal AR do góry nogami od Stranger Things: 10 kroków (ze zdjęciami)
2024 Autor: John Day | [email protected]. Ostatnio zmodyfikowany: 2024-01-30 11:32
Ten Instructable przejdzie przez tworzenie aplikacji mobilnej rzeczywistości rozszerzonej na iPhone'a z portalem, który prowadzi do góry nogami od Stranger Things. Możesz wejść do portalu, obejść się i wyjść. Wszystko w portalu można zobaczyć tylko przez portal, dopóki nie wejdziesz do środka. Gdy znajdziesz się w środku, wszystko będzie renderowane wszędzie, dopóki nie wrócisz do prawdziwego świata. Wykorzystamy silnik gier wideo Unity 3D z wtyczką Apple ARKit. Całe oprogramowanie, z którego będziemy korzystać, można pobrać i używać za darmo. Nie musisz być ekspertem, aby podążać dalej, przejdziemy przez każdy krok!
Krok 1: Rozpocznij nowy projekt Unity
Najpierw pobierz Unity3D i upewnij się, że zainstalowałeś pliki kompilacji dla platformy IOS. Będziesz także musiał pobrać Xcode i założyć bezpłatne konto programisty Apple. Twój iPhone będzie również musiał mieć system IOS 11 lub nowszy. Od dzisiaj 5 lutego 2018 r. IOS 11.3 jest dostępny, ale xCode 9.2 nie ma jeszcze plików obsługi dla niego. Jeśli więc korzystasz z najnowszej wersji IOS, pobierz najnowszą wersję beta Xcode ze strony Apple. Developer.com.
Gdy masz już wszystkie potrzebne programy, otwórz Unity i rozpocznij nowy projekt, nazwij go, jak chcesz. Będziemy potrzebować wtyczki Apple ARKit, abyśmy mogli używać kamery naszego telefonu do wykrywania podłoża i umieszczania obiektów na podłodze. Zaimportujmy to teraz, przechodząc do zakładki Asset Store i wyszukaj „ARKit”. Będziesz musiał utworzyć darmowe konto Unity, jeśli jeszcze go nie masz, a następnie kliknij importuj, aby pobrać wtyczkę.
Przejdź do folderu przykładów w folderze ARKit i znajdź „UnityARKitScene”. Kliknij dwukrotnie, aby go otworzyć. Wykorzystamy tę scenę jako punkt wyjścia i stąd będziemy budować. Ta scena domyślnie pozwoli ci wykryć ziemię, a po dotknięciu ekranu kostka zostanie umieszczona w tej pozycji.
Najpierw ustalmy nasze ustawienia budowania, abyśmy nie zapomnieli zrobić tego później. Kliknij plik, zbuduj ustawienia i usuń wszystkie sceny z tej listy. Kliknij dodaj otwarte sceny, aby dodać naszą aktualną. Ostatnią rzeczą, którą musimy tutaj ustawić, jest przejście w ustawieniach odtwarzacza do identyfikatora pakietu, a format tego ciągu to com. NazwaTwojejFirmy. NazwaTwojejAplikacji, więc w moim przypadku robię coś takiego jak com. MatthewHallberg. PortalTest.
Krok 2: Skonfiguruj scenę
Najpierw spójrz w lewo i znajdź obiekt gry o nazwie „GeneratePlanes”. Mając to podświetlone, spójrz teraz w prawo i kliknij pole wyboru, aby je wyłączyć. W ten sposób nie mamy brzydkich niebieskich kwadratów generowanych, gdy ARKit wykryje płaszczyznę uziemienia. Następnie usuń obiekt gry „RandomCube”, ponieważ nie chcemy go widzieć w naszej scenie.
Teraz musimy najpierw stworzyć drzwi naszego portalu. Usuń kostkę, która jest elementem podrzędnym „HitCubeParent”. Kliknij prawym przyciskiem myszy i wybierz utwórz pusty obiekt gry. Zmień jego nazwę na „Portal”. Teraz kliknij prawym przyciskiem myszy na ten obiekt i utwórz sześcian, dzięki czemu będzie on dzieckiem portalu. Zmień jego nazwę na "PostLeft", a będzie to lewy post naszego portalu. Przeskaluj go tak, aby x to 1, y to 28, a z to jeden. Zrób to samo dla właściwego posta. Teraz utwórz górny słupek i przeskaluj y do 14. Obróć go na bok i przesuń tak, aby łączył inne słupki. Zrób cały portal w skali 1,3 x 1,4 x 1.
Przejdź do google i wpisz teksturę drewna lub kory. Pobierz jeden z tych obrazów i przeciągnij go do folderu zasobów w Unity. Teraz przeciągnij ten obraz na wszystkie swoje posty na portalu.
Kliknij ponownie obiekt "Portal" i kliknij dodaj komponent po prawej stronie. Dodaj do niego skrypt „UnityARHitTestExample”. Jest tam pusty slot dla "Hit Transform", przeciągnij obiekt "HitCubeParent" do tego slotu.
Krok 3: Zróbmy trochę cząstek
Teraz użyjemy systemu Unity Particle do stworzenia efektu dymu i unoszących się cząsteczek wewnątrz naszego portalu. Przejdź do zasobów na górnym pasku menu, standardowych zasobów i importu systemów cząstek.
Utwórz dwa puste obiekty w swoim portalu i nazwij jeden „SmokeParticles”, a drugi „FloatingParticles”.
Dodaj składnik systemu cząstek do cząstek dymu.
Ten komponent ma wiele opcji, ale musimy zmienić tylko kilka.
Zmień kolor początkowy na ciemnoniebieski z około 50% przezroczystością. Ustaw wskaźnik emisji 100. Wewnątrz kształtu ustaw promień.01. W dolnej części renderera zmień minimalny rozmiar na.8, a maksymalny rozmiar na 5. W komponencie materialnym po prostu wybierz materiał dymny z listy, ale zmienimy to później.
Dodaj teraz system cząstek do pływającego obiektu gry i ustaw emisję na 500. Ustaw początkowy czas życia na 2, promień na 10, minimalny rozmiar cząstek na 0,01 i maksymalny rozmiar cząstek na 0,015. Na razie ustaw materiał na domyślną cząsteczkę.
Na koniec weź oba obiekty w grze i obróć je o 90 stopni na osi x i podnieś je w powietrze, aby emitowały w dół do drzwi portalu.
Krok 4: Spowolnienie cząstek
Ponieważ chcemy, aby te cząstki pokryły duży obszar, ale także poruszały się powoli, musimy stworzyć własną funkcję próbkowania. Kliknij prawym przyciskiem myszy w folderze zasobów i utwórz nowy skrypt C# i nazwij go „ParticleSample”. Skopiuj i wklej w tym kodzie:
za pomocą System. Collections;
za pomocą System. Collections. Generic; za pomocą UnityEngine; public class ParticleSample: MonoBehaviour { private ParticleSystem ps; // Użyj tego do inicjalizacji void Start () { ps = GetComponent (); StartCoroutine (Procedura Cząstek ()); } IEnumerator SampleParticleRoutine(){ var main = ps.main; główna.symulacjaPrędkość = 1000f; ps. Graj (); wydajność zwraca nowe WaitForSeconds (.1f); główna.symulacjaPrędkość = 0,05f; } }
Teraz przeciągnij ten skrypt na każdy z obiektów gry systemu cząstek.
Krok 5: Tworzenie portalu
Teraz musimy stworzyć portal, więc kliknij prawym przyciskiem myszy obiekt gry portalu i utwórz quad. Przeskaluj quad tak, aby obejmował cały portal, to stanie się naszym oknem portalu. Pierwszą rzeczą, którą musimy dodać, jest shader portalu, który wyrenderuje tylko obiekty z innym konkretnym shaderem. Kliknij prawym przyciskiem myszy w folderze zasobów i utwórz nowy niepodświetlony shader. Usuń wszystko i wklej ten kod:
Shader „Portal/Okno portalu”
{ SubShader { Zwrite off Colormask 0 anulowanie szablonu{ Ref 1 Pass zastąpić } Pass { } } }
Kliknij prawym przyciskiem myszy w hierarchii i utwórz nowy materiał, nazwij go PortalWindowMat, w menu rozwijanym tego materiału znajdź sekcję portalu i wybierz okno portalu. Przeciągnij ten materiał na swój quad portalu.
Krok 6: Shadery cząstek
Ponownie kliknij prawym przyciskiem myszy folder zasobów i utwórz nowy moduł cieniujący. Musimy stworzyć shadery dla cząstek, które wejdą do portalu. Zastąp cały kod następującym:
Shader „Portal/cząsteczki” {
Właściwości { _TintColor („Kolor odcienia”, Kolor) = (0,5, 0,5, 0,5, 0,5) _MainTex („Tekstura cząstek”, 2D) = „biały” {} _InvFade („Współczynnik miękkich cząstek”, Zakres (0,01, 3,0)) = 1.0 _Stencil("stencil", int) = 6 } Kategoria { Tagi { "Kolejka"="Przezroczysty" "IgnoreProjector"="True" "RenderType"="Przezroczysty" "PreviewType"="Płaszczyzna" } Mieszaj SrcAlpha OneMinusSrcAlpha ColorMask RGB Cull Off Lighting Off ZWrite Off SubShader { Stencil{ Ref 1 Comp[_Stencil] } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 2.0 #pragma multi_compile_particles #pragma multi_compile_fog #include "UnityCG.cginc" sampleMainTex2D; naprawiono4 _TintKolor; struct appdata_t { float4 wierzchołek: POZYCJA; stały4 kolor: KOLOR; float2 texcoord: TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct v2f { float4 wierzchołek: SV_POSITION; stały4 kolor: KOLOR; float2 texcoord: TEXCOORD0; UNITY_FOG_COORDS(1) #ifdef SOFTPARTICLES_ON float4 projPos: TEXCOORD2; #endif UNITY_VERTEX_OUTPUT_STEREO }; float4 _MainTex_ST; v2f vert (appdata_t v) { v2f o; UNITY_SETUP_INSTANCE_ID(v); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); o.wierzchołek = UnityObjectToClipPos(v.wierzchołek); #ifdef SOFTPARTICLES_ON o.projPos = ComputeScreenPos (o.vertex); COMPUTE_EYEDEPTH(o.projPos.z); #endif o.color = v.color * _TintColor; o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); UNITY_TRANSFER_FOG(o, o.wierzchołek); powrót o; } UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture); float _InvFade; fixed4 frag (v2f i): SV_Target { #ifdef SOFTPARTICLES_ON float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos))); część zmiennoprzecinkowa Z = i.projPos.z; float fade = nasycenie (_InvFade * (sceneZ-partZ)); i.kolor.a *= zanika; #endif fixed4 col = 2.0f * i.color * tex2D(_MainTex, i.texcoord); UNITY_APPLY_FOG(i.fogCoord, col); powrót kol; } ENDCG } } } }
Utwórz dwa nowe materiały, jeden o nazwie portalSmoke, a drugi o nazwie portalParticles.
Dla każdego wybierz ten shader, z listy rozwijanej, w portalach, cząsteczkach. Dla cząstek dymu wybierz teksturę dymu, a dla cząstek wybierz teksturę cząstek. Zmień kolor dymu na ciemniejszy niebieski z około 50% przezroczystością. Przejdź do komponentu renderującego każdego systemu cząsteczek w swoim portalu i wybierz odpowiednie materiały, które właśnie stworzyliśmy.
Krok 7: Utwórz Skybox
Teraz, aby naprawdę stworzyć wygląd do góry nogami, musimy zabarwić wszystko na ciemnoniebieski. W tym celu użyjemy przezroczystego skyboxa, więc utwórz nowy shader i wklej ten kod:
Shader „Portal/portalSkybox” {
Właściwości { _Tint ("Kolor Odcień", Kolor) = (.5,.5,.5,.5) [Gamma] _Ekspozycja ("Ekspozycja", Zakres(0, 8))) = 1.0 _Obrót ("Obrót", Zakres (0, 360)) = 0 [NoScaleOffset] _Tex ("Cubemap (HDR)", Cube) = "szary" {} _Stencil("StencilNum", int) = 6 } SubShader { Tagi { "Kolejka"="Tło" "RenderType"="Tło" "PreviewType"="Skybox" } Odrzuć ZWrite Wyłącz Mieszaj SrcAlpha OneMinusSrcAlpha Stencil{ Ref 1 Comp[_Stencil] } Przekaż { CGPROGRAM #pragma vertex vert #frag fragment pragma #pragma target 2.0 #include "UnityCG.cginc" samplerCUBE _Tex; połowa4 _Tex_HDR; pół4 _Odcień; połowa _Ekspozycja; float _Obrót; float3 RotateAroundYInDegrees (wierzchołek float3, stopnie zmiennoprzecinkowe) { float alfa = stopnie * UNITY_PI / 180.0; pływać sina, cosa; sincos(alfa, sina, cosa); float2x2 m = float2x2(cosa, -sina, sina, cosa); return float3(mul(m, wierzchołek.xz), wierzchołek.y).xzy; } struct appdata_t { float4 wierzchołek: POZYCJA; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct v2f { float4 vertex: SV_POSITION; float3 texcoord: TEXCOORD0; UNITY_VERTEX_OUTPUT_STEREO }; v2f vert (appdata_t v) { v2f o; UNITY_SETUP_INSTANCE_ID(v); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); float3 obrócony = RotateAroundYInDegrees(v.vertex, _Rotation); o.vertex = UnityObjectToClipPos(obrócony); o.texcoord = v.wierzchołek.xyz; powrót o; } fixed4 frag (v2f i): SV_Target { half4 tex = texCUBE (_Tex, i.texcoord); half3 c = DecodeHDR (tex, _Tex_HDR); c = c * _Odcień.rgb * unity_ColorSpaceDouble.rgb; c *= _Ekspozycja; zwróć połowę4(c,.5); } ENDCG } } Wyłączenie awaryjne }
Teraz utwórz nowy materiał skybox, nazwij go „PortalSkybox” i wybierz ten moduł cieniujący portalSkybox z menu portalu. Przejdź do Window, Lighting na górze i wybierz ten skybox, który właśnie stworzyliśmy. Podejdź do głównej kamery i ustaw jasne flagi na skybox. Skoro już tu jesteśmy, dodajmy kilka komponentów do naszego aparatu, abyśmy mogli wykryć kolizje. Dodaj do kamery komponent ciała sztywnego i usuń zaznaczenie opcji Użyj grawitacji. Dodaj zderzacz pudełek i sprawdź, czy jest wyzwalacz. Ustaw rozmiar zderzaczy pudełek.5 x 1 x 4. Ustaw płaszczyznę przycinania w aparacie na.01.
Krok 8: Logika portalu
Ostatnią rzeczą, którą musimy zrobić, to stworzyć logikę kontrolującą nasz portal. Utwórz nowy skrypt C# i nazwij go PortalController.
za pomocą System. Collections;
za pomocą System. Collections. Generic; za pomocą UnityEngine; przestrzeń nazw UnityEngine. XR.iOS{ public class PortalController: MonoBehaviour { public Material materials; public MeshRenderer meshRenderer; publiczne UnityARVideo UnityARVideo; private bool isInside = false; private bool isOutside = true; // Użyj tego do inicjalizacji void Start () { OutsidePortal (); } void OnTriggerStay(Collider col){ Vector3 playerPos = Camera.main.transform.position + Camera.main.transform.forward * (Camera.main.nearClipPlane * 4); if (transform. InverseTransformPoint(playerPos).z <= 0){ if (isOutside) { isOutside = false; isInside = prawda; WewnątrzPortalu (); } } else { if (isInside) { isInside = false; isOutside = prawda; Portal zewnętrzny (); } } } void OutsidePortal(){ StartCoroutine (DelayChangeMat (3)); } void InsidePortal(){ StartCoroutine (DelayChangeMat (6)); } IEnumerator DelayChangeMat(int stencilNum){ UnityARVideo.shouldRender = false; plon zwraca nowy WaitForEndOfFrame (); meshRenderer.enabled = fałsz; foreach (Material mat w materiałach) { mat. SetInt ("_Stencil", stencilNum); } plon zwracać new WaitForEndOfFrame (); meshRenderer.enabled = prawda; UnityARVideo.shouldRender = prawda; } } }
Przeciągnij ten nowy skrypt do okna portalu. Spowoduje to przejście nas do i z portalu za każdym razem, gdy zderzacz w naszej kamerze zderzy się z oknem portalu. Teraz w funkcji zmieniającej wszystkie materiały mówimy wtyczce ARkit, aby nie renderowała klatki, więc przejdź do głównej kamery i otwórz skrypt UnityARVideo. Utwórz public bool shouldRender na górze i ustaw go na wartość true. Down w funkcji OnPreRender() zapakuj wszystko w instrukcję if, w której wszystko wewnątrz będzie działać tylko wtedy, gdy shouldRender ma wartość true. Cały skrypt powinien wyglądać tak:
korzystanie z Systemu;
za pomocą System. Runtime. InteropServices; za pomocą UnityEngine; za pomocą UnityEngine. Rendering; przestrzeń nazw UnityEngine. XR.iOS { public class UnityARVideo: MonoBehaviour { public Material m_ClearMaterial; [HideInInspector] public bool shouldRender = true; prywatny bufor poleceń m_VideoCommandBuffer; prywatne Texture2D _videoTextureY; prywatne Texture2D _videoTextureCbCr; prywatne Matrix4x4 _displayTransform; private bool bCommandBufferInitialized; public void Start() { UnityARSessionNativeInterface. ARFrameUpdatedEvent += UpdateFrame; bCommandBufferInitialized = false; } void UpdateFrame(UnityARCamera cam) { _displayTransform = new Matrix4x4(); _displayTransform. SetColumn(0, cam.displayTransform.column0); _displayTransform. SetColumn(1, cam.displayTransform.column1); _displayTransform. SetColumn(2, cam.displayTransform.column2); _displayTransform. SetColumn(3, cam.displayTransform.column3); } void InitializeCommandBuffer() { m_VideoCommandBuffer = new CommandBuffer(); m_VideoCommandBuffer. Blit(null, BuiltinRenderTextureType. CurrentActive,m_ClearMaterial); GetComponent(). AddCommandBuffer(CameraEvent. BeforeForwardOpaque, m_VideoCommandBuffer); bCommandBufferInitialized = prawda; } void OnDestroy() { GetComponent(). RemoveCommandBuffer(CameraEvent. BeforeForwardOpaque, m_VideoCommandBuffer); UnityARSessionNativeInterface. ARFrameUpdatedEvent -= UpdateFrame; bCommandBufferInitialized = false; } #if !UNITY_EDITOR public void OnPreRender() { if (shouldRender){ Uchwyty ARTextureHandles = UnityARSessionNativeInterface. GetARSessionNativeInterface (). GetARVideoTextureHandles(); if (handles.textureY == System. IntPtr. Zero || handles.textureCbCr == System. IntPtr. Zero) { return; } if (!bCommandBufferInitialized) { InitializeCommandBuffer (); } Rozdzielczość currentResolution = Screen.currentResolution; // Tekstura Y if (_videoTextureY == null) { _videoTextureY = Texture2D. CreateExternalTexture(currentResolution.width, currentResolution.height, TextureFormat. R8, false, false, (System. IntPtr)handles.textureY); _videoTextureY.filterMode = Tryb filtru. Bilinear; _videoTextureY.wrapMode = Tryb teksturowania. Powtórz; m_ClearMaterial. SetTexture("_textureY", _videoTextureY); } // Tekstura CbCr if (_videoTextureCbCr == null) { _videoTextureCbCr = Texture2D. CreateExternalTexture(currentResolution.width, currentResolution.height, TextureFormat. RG16, false, false, (System. IntPtr)handles.textureCbCr); _videoTextureCbCr.filterMode = FilterMode. Bilinear; _videoTextureCbCr.wrapMode = Tryb teksturowania. Powtórz; m_ClearMaterial. SetTexture("_textureCbCr", _videoTextureCbCr); } _videoTextureY. UpdateExternalTexture(handles.textureY); _videoTextureCbCr. UpdateExternalTexture(uchwyty.textureCbCr); m_ClearMaterial. SetMatrix("_DisplayTransform", _displayTransform); } } #else public void SetYTexure(Texture2D YTex) { _videoTextureY = YTex; } public void SetUVTexure(Texture2D UVTex) { _videoTextureCbCr = UVTex; } public void OnPreRender() { if (!bCommandBufferInitialized) { InitializeCommandBuffer (); } m_ClearMaterial. SetTexture("_textureY", _videoTextureY); m_ClearMaterial. SetTexture("_textureCbCr", _videoTextureCbCr); m_ClearMaterial. SetMatrix("_DisplayTransform", _displayTransform); } #endif } }
Krok 9: Prawie gotowe
Wreszcie, gdy klikniemy w ekran i umieścimy portal, chcemy, aby zawsze był zwrócony do nas. Aby to zrobić, przejdź do skryptu „UnityARHitTestExample” w portalu. Zastąp wszystko w środku tym:
korzystanie z Systemu;
za pomocą System. Collections. Generic; przestrzeń nazw UnityEngine. XR.iOS { public class UnityARHitTestPrzykład: MonoBehaviour { public Transform m_HitTransform; public float maxRayDistance = 30.0f; public LayerMaskcollisionLayer = 1 < 0) { foreach (var hitResult w hitResults) { Debug. Log ("Got hit!"); m_HitTransform.position = UnityARMatrixOps. GetPosition (hitResult.worldTransform); m_HitTransform.rotation = UnityARMatrixOps. GetRotation (hitResult.worldTransform); Debug. Log (string. Format ("x:{0:0.######} y:{1:0.######} z:{2:0.###### }", m_HitTransform.position.x, m_HitTransform.position.y, m_HitTransform.position.z)); Vector3 currAngle = transform.eulerAngles; transform. LookAt (Kamera.main.transform); transform.eulerAngles = new Vector3 (currAngle.x, transform.eulerAngles.y, currAngle.z); zwróć prawdę; } } return false; } // Aktualizacja jest wywoływana raz na klatkę void Update() { #if UNITY_EDITOR //będziemy używać tego skryptu tylko po stronie edytora, chociaż nic nie uniemożliwiłoby jego pracy na urządzeniu if (Input. GetMouseButtonDown (0)) { Promień promienia = Camera.main. ScreenPointToRay (Input.mousePosition); Trafienie RaycastHit; //spróbujemy trafić w jeden z obiektów gry zderzających samoloty, które zostały wygenerowane przez wtyczkę //skutecznie podobne do wywołania HitTest za pomocą ARHitTestResultType. ARHitTestResultTypeExistingPlaneUsingExtent if (Physics. Raycast (promień, trafienie wychodzące, maxRayDistance, kolizja/warstwa)) { / pozycję uzyskamy z punktu kontaktowego m_HitTransform.position = hit.point; Debug. Log (string. Format ("x:{0:0.######} y:{1:0.######} z:{2:0.###### }", m_HitTransform.position.x, m_HitTransform.position.y, m_HitTransform.position.z)); //i obrót z transformacji zderzacza płaskiego m_HitTransform.rotation = hit.transform.rotation; } } #else if (Input.touchCount > 0 && m_HitTransform != null) { var touch = Input. GetTouch(0); if (touch.phase == TouchPhase. Began || touch.phase == TouchPhase. Moved) { var screenPosition = Camera.main. ScreenToViewportPoint(touch.position); ARPoint point = new ARPoint { x = screenPosition.x, y = screenPosition.y }; // Prioritize rodzaje reults ARHitTestResultType = {ARHitTestResultType. ARHitTestResultTypeExistingPlaneUsingExtent resultTypes, // jeśli chcesz używać nieskończone samoloty użyj: //ARHitTestResultType. ARHitTestResultTypeExistingPlane, ARHitTestResultType. ARHitTestResultTypeHorizontalPlane, ARHitTestResultType. ARHitTestResultTypeFeaturePoint}; foreach (ARHitTestResultType resultType w typach wyników) { if (HitTestWithResultType (punkt, typ wyniku)) { return; } } } } #endif } } }
Krok 10: Umieść aplikację na swoim telefonie
Wreszcie skończyliśmy. Przejdź do pliku, ustawienia kompilacji i kliknij kompiluj. Otwórz Xcode i wybierz folder, który został utworzony z kompilacji. Wybierz swój zespół programistów i umieść aplikację na swoim telefonie! Możesz zmienić kolory cząsteczek i skyboxa, aby dopasować je do swoich potrzeb. Dajcie znać w komentarzach, jeśli macie jakieś pytania i dziękujemy za obejrzenie!
Zalecana:
Programowalna bluza z kapturem Stranger Things: 9 kroków (ze zdjęciami)
Programowalna bluza z kapturem Stranger Things: Być może nigdy nie będziesz musiał spędzać czasu w koszmarnym świecie potworów, ale czasami po prostu chcesz nosić koszulkę, która mówi, że możesz tam mieszkać, jeśli chcesz. Ponieważ taka koszula nie istnieje na wolnym rynku, postanowiliśmy zrobić nasz o
Żarówki reagujące na dźwięk Wyświetlacze + Stranger Things : 8 kroków (ze zdjęciami)
Żarówki reagujące na dźwięk Wyświetlacze + Stranger Things …: Więcej zdjęć i aktualizacje projektu: @capricorn_one
Ściana Stranger Things w ramce (napisz własne wiadomości!): 8 kroków (ze zdjęciami)
Ściana Stranger Things w ramce (pisz własne wiadomości!): Miałem zamiar to zrobić od miesięcy po obejrzeniu samouczka z lampkami świątecznymi (wyglądało to świetnie, ale po co nie pokazywać żadnych wiadomości, prawda?). Więc zrobiłem tę ścianę Stranger Things jakiś czas temu i zajęło mi to dość dużo czasu
Koszulka Stranger Things LED: 8 kroków (ze zdjęciami)
Koszulka LED Stranger Things: Materiały, których będziesz potrzebować: 1x Plain White T-Shirt Matowa czarna farba do tkanin (Amazon) 26x Adresowalne diody LED RGB (Polulu) Lut i rurka termokurczliwa przewodu elektrycznego (Maplin) 1x Arduino Uno 1x Akumulator USB 1x kabel USB-A 1x igła i amp; Biała groźba
Ćśś… (u góry): 3 kroki (ze zdjęciami)
Ćśś… (do góry): Szeptem „Ćśśśś” nie jest najskuteczniejszym sposobem na uciszenie ludzi. Zwłaszcza w miejscach publicznych, a zwłaszcza w bibliotekach publicznych. Zamknijmy więc usta z poczuciem winy. To światło jest zainstalowane w bibliotece