Sadržaj:

AR portal naopako od čudnih stvari: 10 koraka (sa slikama)
AR portal naopako od čudnih stvari: 10 koraka (sa slikama)

Video: AR portal naopako od čudnih stvari: 10 koraka (sa slikama)

Video: AR portal naopako od čudnih stvari: 10 koraka (sa slikama)
Video: Моя работа наблюдать за лесом и здесь происходит что-то странное 2024, Studeni
Anonim
AR portal naopako od čudnih stvari
AR portal naopako od čudnih stvari
AR portal naopako od čudnih stvari
AR portal naopako od čudnih stvari

Ovaj Instructable proći će kroz stvaranje mobilne aplikacije proširene stvarnosti za iPhone s portalom koji vodi naopako od Stranger Things. Možete ući u portal, prošetati i izaći. Sve unutar portala može se vidjeti samo kroz portal dok ne uđete unutra. Kad jednom uđete, sve će se renderirati posvuda, sve dok se ne vratite u stvarni svijet. Koristit ćemo Unity 3D engine za video igre s Apple ARKit dodatkom. Sav softver koji ćemo koristiti može se besplatno preuzeti i koristiti. Ne morate biti stručnjak da biste to pratili, proći ćemo svaki korak!

Korak 1: Pokrenite novi projekt Unity

Pokrenite novi projekt Unity
Pokrenite novi projekt Unity

Prije svega, preuzmite Unity3D i instalirajte datoteke za izgradnju za IOS platformu. Također ćete morati preuzeti Xcode i prijaviti se za besplatni Appleov račun za programere. Vaš iPhone će također morati imati IOS 11 ili noviji. Od dana 5. veljače 2018. IOS 11.3 je izašao, ali xCode 9.2 još nema datoteke podrške za njega. Stoga, ako koristite najnoviju verziju IOS -a, preuzmite najnoviju beta verziju Xcodea s Apple. Developer.com.

Nakon što imate sve potrebne programe, otvorite Unity i pokrenite novi projekt, nazovite ga kako želite. Trebat će nam dodatak Apple ARKit kako bismo mogli pomoću kamere našeg telefona otkriti tlo i postaviti predmete na pod. Uvezimo to sada tako da odemo na karticu Asset Store i pretražimo "ARKit". Morat ćete stvoriti besplatni Unity račun ako ga već nemate, a zatim kliknite uvoz da biste dobili dodatak.

Idite do mape primjera u mapi ARKit i pronađite "UnityARKitScene". Dvaput kliknite na nju da biste je otvorili. Ovu scenu ćemo koristiti kao polazište i odavde ćemo graditi. Ova scena prema zadanim postavkama omogućit će vam otkrivanje tla, a kada dodirnete zaslon, kocka će biti postavljena u taj položaj.

Idemo prvo izravnati naše postavke gradnje kako ne bismo zaboravili to učiniti kasnije. Pritisnite datoteku, izradite postavke i uklonite sve scene s tog popisa. Kliknite Dodaj otvorene scene da biste dodali našu trenutnu. Posljednje što ovdje moramo postaviti je da se postavke playera spuste na identifikator paketa, a format za ovaj niz je com. YourCompanyName. YourAppName, pa u mom slučaju radim nešto poput com. MatthewHallberg. PortalTest.

Korak 2: Postavite scenu

Postavite scenu
Postavite scenu

Prvo pogledajte lijevo i pronađite objekt igre pod nazivom "GeneratePlanes". Kad je to istaknuto, pogledajte desno sada i kliknite potvrdni okvir da biste ga onemogućili. Na ovaj način nemamo generirane ružne plave kvadrate kada ARKit detektira ravninu tla. Zatim izbrišite objekt igre "RandomCube" jer to ne želimo vidjeti u našoj sceni.

Sada moramo prvo stvoriti vrata našeg portala. Izbrišite kocku koja je podređena od "HitCubeParent". Desnom tipkom miša kliknite i odaberite stvoriti prazan objekt igre. Preimenujte ga u "Portal". Sada desnom tipkom miša kliknite na taj objekt i stvorite kocku, to će je učiniti podređenom za portal. Preimenujte ga u "PostLeft" i ovo će biti lijevi post našeg portala. Mjerite ga tako da x bude 1, y je 28, a z jedno. Učinite isto za pravi post. Sada stvorite gornji stup i skalirajte y na 14. Okrenite ovo bočno i pomaknite ga tako da povezuje ostale stupove. Učinite cijelo mjerilo portala 1,3 x 1,4 x 1.

Idite na google i upišite teksturu drva ili kore. Preuzmite jednu od tih slika i povucite je u mapu svojstva u programu Unity. Sada povucite tu sliku na sve svoje postove na portalu.

Ponovno kliknite objekt "Portal" i kliknite Dodaj komponentu s desne strane. Dodajte mu skriptu "UnityARHitTestExample". Tamo je prazan utor za "Hit Transform", povucite objekt "HitCubeParent" u taj utor.

Korak 3: Napravimo neke čestice

Napravimo neke čestice
Napravimo neke čestice

Sada ćemo koristiti sustav Unity Particle za stvaranje efekta dima i plutajućih čestica unutar našeg portala. Idite na Sredstva na gornjoj traci izbornika, Standardna sredstva i uvezite sustave čestica.

Napravite dva prazna objekta igre na svom portalu i jedan nazovite "SmokeParticles", a drugi "FloatingParticles".

Česticama dima dodajte komponentu sustava čestica.

Ova komponenta ima hrpu mogućnosti, ali samo moramo promijeniti par.

Promijenite početnu boju u nešto tamno plavo s oko 50% prozirnosti. Učinite stopu emisije 100. Unutar oblika, napravite radijus.01. U dijelu za prikazivanje na dnu promijenite minimalnu veličinu na.8, a najveću na 5. Na komponenti materijala samo odaberite dimni materijal s popisa, ali to ćemo promijeniti kasnije.

Sada dodajte sustav čestica objektu igre s plutajućim česticama i postavite emisiju na 500. Namjestite životni vijek početka na 2, radijus na 10, minimalnu veličinu čestica na.01, a najveću veličinu čestica na.015. Za sada postavite materijal na zadane čestice.

Na kraju uzmite oba predmeta igre i okrenite ih za 90 stupnjeva na x te ih podignite u zrak tako da emitiraju prema dolje na portalu.

Korak 4: Usporavanje čestica

Usporavanje čestica
Usporavanje čestica

Budući da želimo da ove čestice pokrivaju veliko područje, ali i da se sporo kreću, moramo stvoriti vlastitu funkciju uzorka. Dakle, desnom tipkom miša kliknite u folderu imovine i stvorite novu C# skriptu i nazovite je "ParticleSample". Kopirajte i zalijepite ovaj kod:

pomoću System. Collections;

pomoću System. Collections. Generic; koristeći UnityEngine; javna klasa ParticleSample: MonoBehaviour {private ParticleSystem ps; // Koristi ovo za inicijalizaciju void Start () {ps = GetComponent (); StartCoroutine (SampleParticleRoutine ()); } IEnumerator SampleParticleRoutine () {var main = ps.main; main.simulationSpeed = 1000f; ps. Play (); yield return new WaitForSeconds (.1f); main.simulationSpeed =.05f; }}

Sada povucite ovu skriptu na svaki od objekata igre u sustavu čestica.

Korak 5: Izrada portala

Izrada portala!
Izrada portala!

Sada moramo stvoriti portal pa desnom tipkom miša kliknite objekt igre na portalu i stvorite četverokut. Povećajte quad tako da pokriva cijeli portal, ovo će postati naš prozor portala. Prvo što mu moramo dodati je zasjenjivač portala, koji će prikazati samo objekte s drugim određenim sjenilom. Desnom tipkom miša kliknite u mapi imovina i stvorite novi neosvijetljeni zasjenjivač. Uklonite sve unutra i zalijepite ovaj kod:

Shader "Portal/portalWindow"

{SubShader {Zwrite off Colormask 0 cull off Stencil {Ref 1 Pass replace} Pass {}}}

Desnom tipkom miša kliknite hijerarhiju i stvorite novi materijal, nazovite ga PortalWindowMat, u padajućem izborniku za ovaj materijal pronađite odjeljak portala i odaberite prozor portala. Povucite ovaj materijal na svoj četverostruki portal.

Korak 6: Uređivači čestica

Shaders Shaders
Shaders Shaders

Ponovno desnom tipkom miša kliknite u mapi imovine i stvorite novu sjenčanju. Moramo napraviti sjenila za čestice koje ulaze unutar portala. Zamijenite sav kôd ovim:

Shader "Portal/čestice" {

Svojstva {_TintColor ("Boja nijanse", Boja) = (0,5, 0,5, 0,5, 0,5) _MainTex ("Tekstura čestica", 2D) = "bijela" {} _InvFade ("Faktor mekih čestica", Raspon (0,01, 3,0)) = 1.0 _Stencil ("stencil", int) = 6} Kategorija {Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane"} Blend SrcAlpha OneMinusSrcAlpha ColorMask RGB Cull Off Lighting Off ZWrite Off SubShader {Stencil {Ref 1 Comp [_Stencil]} Proslijedi {CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 2.0 #pragma multi_compile_particles #pragma multi_compile_fog #include "UnityCGe fixed4 _TintColor; struct appdata_t {float4 vertex: POSITION; fiksno4 boja: COLOR; float2 texcoord: TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID}; struct v2f {float4 tjeme: SV_POSITION; fiksno4 boja: COLOR; telekoord float2: 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.vertex = UnityObjectToClipPos (v.vertex); #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.vertex); povratak 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))); dio s plovkomZ = i.projPos.z; float fade = saturate (_InvFade * (sceneZ-partZ)); i.boja.a *= blijedi; #endif fixed4 col = 2.0f * i.color * tex2D (_MainTex, i.texcoord); UNITY_APPLY_FOG (i.fogCoord, col); povratni col; } ENDCG}}}}

Izradite dva nova materijala, jedan koji se zove portalSmoke, a drugi portalParticles.

Za svakoga odaberite ovaj zasjenjivač, s padajućeg izbornika, na portalima, čestice. Za čestice dima odaberite teksturu dima, a za čestice teksturu čestica. Promijenite boju dima u tamnije plavu s oko 50% prozirnosti. Idite na komponentu renderera svakog sustava čestica na svom portalu i odaberite odgovarajuće materijale koje smo upravo stvorili.

Korak 7: Izradite Skybox

Napravite Skybox
Napravite Skybox

Sada da bismo doista stvorili izgled naopačke, moramo sve tonirati tamnoplavo. Za to ćemo koristiti prozirni skybox pa napravite novi shader i zalijepite ovaj kod:

Shader "Portal/portalSkybox" {

Svojstva {_Tint ("Boja nijanse", Boja) = (.5,.5,.5,.5) [Gama] _Exposure ("Izloženost", Raspon (0, 8)) = 1.0 _Rotation ("Rotacija", Raspon (0, 360)) = 0 [NoScaleOffset] _Tex ("Cubemap (HDR)", Cube) = "grey" {} _Stencil ("StencilNum", int) = 6} Pod -sjenilo {Oznake {"Red" = "Pozadina" "RenderType" = "Pozadina" "PreviewType" = "Skybox"} Izdvoji ZWrite Off Blend SrcAlpha OneMinusSrcAlpha matrica {Ref 1 Comp [_Stencil]} Položi {CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 2.0 #CGclude ".cginc "samplerCUBE _Tex; pola4 _Tex_HDR; half4 _Tint; pola _Izlaganje; float _Rotation; float3 RotateAroundYInDegrees (float3 tjeme, float stupnjevi) {float alpha = stupnjevi * UNITY_PI / 180.0; plutati sina, cosa; sincos (alfa, sina, cosa); plovak2x2 m = plovak2x2 (cosa, -sina, sina, cosa); return float3 (mul (m, vertex.xz), vertex.y).xzy; } struct appdata_t {float4 vertex: POSITION; UNITY_VERTEX_INPUT_INSTANCE_ID}; struct v2f {float4 tjeme: 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 rotated = RotateAroundYInDegrees (v.vertex, _Rotation); o.vertex = UnityObjectToClipPos (rotirano); o.texcoord = v.vertex.xyz; povratak o; } fixed4 frag (v2f i): SV_Target {half4 tex = texCUBE (_Tex, i.texcoord); half3 c = DecodeHDR (tex, _Tex_HDR); c = c * _Tint.rgb * Unity_ColorSpaceDouble.rgb; c *= _Izlaganje; return half4 (c,.5); } ENDCG}} Rezervno isključeno}

Sada stvorite novi skybox materijal, nazovite ga "PortalSkybox" i odaberite ovaj portalSkybox shader s izbornika portala. Idite na Window, Lighting na vrhu i odaberite ovaj skybox koji smo upravo stvorili. Idite na glavnu kameru i postavite jasne zastavice u skybox. Dok smo ovdje, dodajmo neke komponente na našu kameru kako bismo mogli otkriti sudare. Dodajte kameri komponentu s krutim tijelom i poništite upotrebu gravitacije. Dodajte okvirni sudarač i provjerite je li okidač. Postavite okvirne sudarače veličine.5 x 1 x 4. Postavite ravninu izrezivanja na fotoaparatu na.01.

Korak 8: Logika portala

Logika portala
Logika portala

Posljednje što moramo učiniti je stvoriti logiku koja kontrolira naš portal. Napravite novu C# skriptu i nazovite je PortalController.

pomoću System. Collections;

pomoću System. Collections. Generic; koristeći UnityEngine; imenski prostor UnityEngine. XR.iOS {javni razred PortalController: MonoBehaviour {javni materijal materijali; javni MeshRenderer meshRenderer; javni UnityARVideo UnityARVideo; privatni bool isInside = false; privatni bool isOutside = true; // Koristi ovo za inicijalizaciju 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 = true; InsidePortal (); }} else {if (isInside) {isInside = false; isOutside = istina; OutsidePortal (); }}} void OutsidePortal () {StartCoroutine (DelayChangeMat (3)); } void InsidePortal () {StartCoroutine (DelayChangeMat (6)); } IEnumerator DelayChangeMat (int stencilNum) {UnityARVideo.shouldRender = false; yield return new WaitForEndOfFrame (); meshRenderer.enabled = false; foreach (Materijal mat u materijalima) {mat. SetInt ("_Stencil", stencilNum); } yield return new WaitForEndOfFrame (); meshRenderer.enabled = true; UnityARVideo.shouldRender = true; }}}

Povucite ovu novu skriptu na prozor portala. To će nas prevesti unutra i van portala kad god se sudarač na našoj kameri sudari s prozorom portala. Sada u funkciji koja mijenja sve materijale kažemo dodatku ARkit da ne generira okvir, pa idite na glavnu kameru i otvorite skriptu UnityARVideo. Napravite javni bool shouldRender na vrhu i postavite ga jednakim true. Dolje u funkciji OnPreRender () zamotajte sve u if naredbu gdje će se sve izvoditi samo ako shouldRender je istina. Cijela skripta bi trebala izgledati ovako:

pomoću sustava;

pomoću System. Runtime. InteropServices; koristeći UnityEngine; pomoću UnityEngine. Rendering; imenski prostor UnityEngine. XR.iOS {javni razred UnityARVideo: MonoBehaviour {javni materijal m_ClearMaterial; [HideInInspector] javni bool shouldRender = true; privatni CommandBuffer m_VideoCommandBuffer; privatni Texture2D _videoTextureY; privatni Texture2D _videoTextureCbCr; privatni Matrix4x4 _displayTransform; privatni 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 = novi CommandBuffer (); m_VideoCommandBuffer. Blit (null, BuiltinRenderTextureType. CurrentActive, m_ClearMaterial); GetComponent (). AddCommandBuffer (CameraEvent. BeforeForwardOpaque, m_VideoCommandBuffer); bCommandBufferInitialized = true; } void OnDestroy () {GetComponent (). RemoveCommandBuffer (CameraEvent. BeforeForwardOpaque, m_VideoCommandBuffer); UnityARSessionNativeInterface. ARFrameUpdatedEvent -= UpdateFrame; bCommandBufferInitialized = false; } #i! UNITY_EDITOR javna void OnPreRender () {if (shouldRender) {ARTextureHandles handles = UnityARSessionNativeInterface. GetARSessionNativeInterface (). GetARVideoTextureHandles (); if (handles.textureY == System. IntPtr. Zero || handles.textureCbCr == System. IntPtr. Zero) {return; } if (! bCommandBufferInitialized) {InitializeCommandBuffer (); } Resolution currentResolution = Screen.currentResolution; // Tekstura Y ako (_videoTextureY == null) {_videoTextureY = Texture2D. CreateExternalTexture (currentResolution.width, currentResolution.height, TextureFormat. R8, false, false, (System. IntPtr) handles.textureY); _videoTextureY.filterMode = FilterMode. Bilinearno; _videoTextureY.wrapMode = TextureWrapMode. Repeat; m_ClearMaterial. SetTexture ("_ textureY", _videoTextureY); } // Tekstura CbCr ako (_videoTextureCbCr == null) {_videoTextureCbCr = Texture2D. CreateExternalTexture (currentResolution.width, currentResolution.height, TextureFormat. RG16, false, false, (System. IntPtr); _videoTextureCbCr.filterMode = FilterMode. Bilinear; _videoTextureCbCr.wrapMode = TextureWrapMode. Repeat; m_ClearMaterial. SetTexture ("_ textureCbCr", _videoTextureCbCr); } _videoTextureY. UpdateExternalTexture (ručke.teksturaY); _videoTextureCbCr. UpdateExternalTexture (ručke.teksturaCbCr); m_ClearMaterial. SetMatrix ("_ DisplayTransform", _displayTransform); }} #else public void SetYTexure (Texture2D YTex) {_videoTextureY = YTex; } javna praznina 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); } #završi ako } }

Korak 9: Skoro gotovo

Skoro gotovo!
Skoro gotovo!

Konačno, kad kliknemo na zaslon i postavimo portal, želimo da nam uvijek bude okrenut. Da biste to učinili, idite na skriptu "UnityARHitTestExample" na portalu. Zamijenite sve unutra ovim:

pomoću sustava;

pomoću System. Collections. Generic; imenski prostor UnityEngine. XR.iOS {javni razred UnityARHitTestExample: MonoBehaviour {public Transform m_HitTransform; javni plovak maxRayDistance = 30.0f; javni LayerMask collisionLayer = 1 <0) {foreach (var hitResult u 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 (Camera.main.transform); transform.eulerAngles = novi Vector3 (currAngle.x, transform.eulerAngles.y, currAngle.z); return true; }} return false; } // Ažuriranje se poziva jednom po okviru void Update () {#if UNITY_EDITOR // ovu ćemo skriptu koristiti samo na strani uređivača, iako ne postoji ništa što bi je spriječilo da radi na uređaju ako (Input. GetMouseButtonDown (0)) {Ray ray = Camera.main. ScreenPointToRay (Input.mousePosition); RaycastHit hit; // pokušat ćemo pogoditi jedan od objekata avionskih sudarača koji je generiran dodatkom // učinkovito slično pozivanju HitTesta s ARHitTestResultType. ARHitTestResultTypeExistingPlaneUsingExtent if (Physics. Raycast (ray, out hit, maxRayDistance, collisionLayer)) {// poziciju ćemo dobiti od kontaktne točke 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 rotacija iz transformacije ravnog sudarača 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 točka = nova ARPoint {x = screenPosition.x, y = screenPosition.y}; // kao prioritet reults vrste ARHitTestResultType resultTypes = {ARHitTestResultType. ARHitTestResultTypeExistingPlaneUsingExtent, // ukoliko želite koristiti beskonačni zrakoplove upotrijebiti: //ARHitTestResultType. ARHitTestResultTypeExistingPlane, ARHitTestResultType. ARHitTestResultTypeHorizontalPlane, ARHitTestResultType. ARHitTestResultTypeFeaturePoint}; foreach (ARHitTestResultType resultType u resultTypes) {if (HitTestWithResultType (point, resultType)) {return; } } } } #završi ako } } }

Korak 10: Postavite aplikaciju na telefon

Stavite aplikaciju na telefon!
Stavite aplikaciju na telefon!

Napokon smo gotovi. Idite na datoteku, postavite postavke i kliknite na izgradnju. Otvorite Xcode i odaberite mapu koja je stvorena iz međuverzije. Odaberite svoj razvojni tim i stavite aplikaciju na telefon! Možda ćete htjeti promijeniti boje čestica i skybox -a kako bi odgovarali vašim potrebama. Javite mi u komentarima ako imate pitanja i hvala što ste pogledali!

Preporučeni: