Kazalo:

AR portal na glavo navzdol od čudnih stvari: 10 korakov (s slikami)
AR portal na glavo navzdol od čudnih stvari: 10 korakov (s slikami)

Video: AR portal na glavo navzdol od čudnih stvari: 10 korakov (s slikami)

Video: AR portal na glavo navzdol od čudnih stvari: 10 korakov (s slikami)
Video: Моя работа наблюдать за лесом и здесь происходит что-то странное 2024, November
Anonim
AR portal na glavo od tujih stvari
AR portal na glavo od tujih stvari
AR portal na glavo od tujih stvari
AR portal na glavo od tujih stvari

Ta Instructable bo šel skozi ustvarjanje mobilne aplikacije z razširjeno resničnostjo za iPhone s portalom, ki vodi navzdol od Stranger Things. Lahko greste na portal, se sprehodite in se vrnete ven. Vse znotraj portala je mogoče videti le skozi portal, dokler ne vstopite noter. Ko bo notri, bo vse povsod upodobljeno, dokler se ne vrneš nazaj v resnični svet. Uporabili bomo motor za video igre Unity 3D z vtičnikom Apple ARKit. Vso programsko opremo, ki jo bomo uporabljali, je mogoče brezplačno prenesti in uporabljati. Za spremljanje vam ni treba biti strokovnjak, šli bomo skozi vsak korak!

1. korak: Začnite projekt New Unity

Začnite projekt New Unity
Začnite projekt New Unity

Najprej prenesite Unity3D in ne pozabite namestiti gradbenih datotek za platformo IOS. Prav tako boste morali prenesti Xcode in se prijaviti za brezplačen račun razvijalca Apple. Tudi vaš iPhone bo moral uporabljati IOS 11 ali novejši. Od 5. februarja 2018 je IOS 11.3 izšel, vendar xCode 9.2 zanj še nima podpornih datotek. Torej, če uporabljate najnovejšo različico iOS -a, prenesite najnovejšo različico beta Xcode beta z Apple. Developer.com.

Ko imate vse potrebne programe, odprite Unity in začnite nov projekt, pokličite ga kakor želite. Potrebovali bomo vtičnik Apple ARKit, da bomo lahko s kamero telefona zaznali tla in postavili predmete na tla. Uvozimo to zdaj, tako da odpremo zavihek Trgovina sredstev in poiščemo »ARKit«. Če še nimate računa Unity, morate ustvariti brezplačen račun, nato kliknite uvoz, da dobite vtičnik.

Pomaknite se do mape z primeri v mapi ARKit in poiščite »UnityARKitScene«. Dvokliknite, da ga odprete. Ta prizor bomo uporabili kot izhodišče in gradili od tu naprej. Ta prizor vam privzeto omogoča zaznavanje tal in ko se dotaknete zaslona, bo v ta položaj postavljena kocka.

Najprej nastavimo nastavitve gradnje na kvadrat, da tega ne pozabimo narediti pozneje. Kliknite datoteko, ustvarite nastavitve in odstranite vse prizore s tega seznama. Kliknite Dodaj odprte prizore, če želite dodati našega trenutnega. Zadnja stvar, ki jo moramo nastaviti tukaj, je v nastavitvah predvajalnika iti do identifikatorja svežnja in oblika tega niza je com. YourCompanyName. YourAppName, zato v mojem primeru naredim nekaj takega kot com. MatthewHallberg. PortalTest.

2. korak: Nastavite sceno

Nastavite sceno
Nastavite sceno

Najprej poglejte levo in poiščite predmet igre z imenom "GeneratePlanes". Ko je to označeno, poglejte desno in kliknite potrditveno polje, da ga onemogočite. Na ta način nimamo ustvarjenih grdih modrih kvadratov, ko ARKit zazna osnovno ravnino. Nato izbrišite predmet igre "RandomCube", ker tega ne želimo videti v našem prizoru.

Zdaj moramo najprej ustvariti vrata portala. Izbrišite kocko, ki je podrejena "HitCubeParent". Z desno miškino tipko kliknite in izberite Ustvari prazen predmet igre. Preimenujte ga v "Portal". Zdaj z desno tipko miške kliknite ta predmet in ustvarite kocko, tako da bo podrejen portala. Preimenujte ga v "PostLeft" in to bo leva objava našega portala. Prilagodite tako, da je x 1, y je 28, z pa eno. Naredite enako za pravo objavo. Zdaj ustvarite zgornji drog in pomerite y na 14. Obrnite ga vstran in ga premaknite tako, da povezuje druge stebre. Naj bo celotna lestvica portala 1,3 x 1,4 x 1.

Pojdite na google in vnesite teksturo lesa ali lubja. Prenesite eno od teh slik in jo povlecite v mapo sredstev v sistemu Unity. Zdaj povlecite to sliko na vse svoje objave na portalu.

Znova kliknite predmet "Portal" in na desni kliknite dodajanje komponente. Vanj dodajte skript "UnityARHitTestExample". Tam je prazna reža za "Hit Transform", povlecite predmet "HitCubeParent" v to režo.

3. korak: Naredimo nekaj delcev

Naredimo nekaj delcev
Naredimo nekaj delcev

Zdaj bomo s sistemom Unity Particle ustvarili učinek dima in plavajočih delcev za naš portal. Pojdite na Sredstva v zgornji menijski vrstici, Standardna sredstva in uvozite sisteme delcev.

Ustvarite dva prazna predmeta igre na svojem portalu in enega pokličite »SmokeParticles«, drugega pa »FloatingParticles«.

Delcem dima dodajte komponento sistema delcev.

Ta komponenta ima kup možnosti, vendar moramo spremeniti le nekaj.

Spremenite začetno barvo v nekaj temno modrega s približno 50% preglednostjo. Naj bo stopnja emisij 100. V notranjosti oblikujte polmer.01. V delu upodabljalnika na dnu spremenite velikost min na.8 in največjo velikost na 5. Pri komponenti materiala samo izberite dimni material s seznama, vendar bomo to spremenili kasneje.

Zdaj dodajte sistem delcev v predmet igre s plavajočimi delci in nastavite emisijo na 500. Nastavite življenjsko dobo na 2, polmer na 10, najmanjšo velikost delcev na 0,01 in največjo velikost delcev na 0,015. Material za zdaj nastavite na privzete delce.

Nazadnje vzemite oba predmeta igre in jih zavrtite za 90 stopinj na x in ju dvignite v zrak, tako da oddajata navzdol na vrata portala.

4. korak: Upočasnite delce

Upočasnitev delcev
Upočasnitev delcev

Ker želimo, da ti delci pokrivajo veliko površino, a se tudi premikajo počasi, moramo ustvariti lastno vzorčno funkcijo. Zato z desno miškino tipko kliknite mapo sredstev in ustvarite nov skript C# in ga pokličite »ParticleSample«. Kopirajte in prilepite to kodo:

z uporabo System. Collections;

z uporabo System. Collections. Generic; z uporabo UnityEngine; javni razred ParticleSample: MonoBehaviour {private ParticleSystem ps; // To uporabite za inicializacijo 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; }}

Zdaj povlecite ta skript na vsak predmet igre v sistemu delcev.

5. korak: Ustvarite portal

Ustvarjanje portala!
Ustvarjanje portala!

Zdaj moramo ustvariti portal, tako da z desno miškino tipko kliknemo na predmet portalske igre in ustvarimo štirikolesnik. Prilagodite štirikolesnik tako, da pokriva celoten portal, to bo postalo naše okno portala. Prva stvar, ki jo moramo dodati, je senčnik portala, ki bo upodobil le predmete z drugo posebno senco. Z desno miškino tipko kliknite mapo sredstev in ustvarite novo neosvetljeno senčilo. Odstranite vse tam in prilepite to kodo:

Shader "Portal/portalWindow"

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

Z desno miškino tipko kliknite hierarhijo in ustvarite novo gradivo, pokličite ga PortalWindowMat, v spustnem meniju za to gradivo poiščite razdelek portala in izberite okno portala. Povlecite ta material na svoj portalni štirikolesnik.

Korak 6: Senčniki delcev

Senčniki delcev
Senčniki delcev

Znova z desno miškino tipko kliknite mapo sredstev in ustvarite novo senco. Izdelati moramo senčila za delce, ki gredo v portal. Zamenjajte vso kodo s tem:

Shader "Portal/Delci" {

Lastnosti {_TintColor ("Barva odtenka", Barva) = (0,5, 0,5, 0,5, 0,5) _MainTex ("Tekstura delcev", 2D) = "bela" {} _InvFade ("Faktor mehkih delcev", Razpon (0,01, 3,0)) = 1.0 _Stencil ("stencil", int) = 6} Kategorija {Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane"} Mešanica SrcAlpha OneMinusSrcAlpha ColorMask RGB Cull Off Lighting Off ZWrite Off SubShader {Stencil {Ref 1 Comp [_Stencil]} Prenesite {CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 2.0 #pragma multi_compile_particles #pragma multi_compile_fog #include "UnityCgc2 fixed4 _TintColor; struct appdata_t {float4 vertex: POSITION; fiksno4 barva: BARVA; texcoord float2: TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID}; struct v2f {float4 vertex: SV_POSITION; fiksno4 barva: BARVA; texcoord 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); vrniti 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))); plavajoči delZ = i.projPos.z; float fade = saturate (_InvFade * (sceneZ-partZ)); i.color.a *= zbledi; #endif fixed4 col = 2.0f * i.color * tex2D (_MainTex, i.texcoord); UNITY_APPLY_FOG (i.fogCoord, stolpec); povratni stolpec; } ENDCG}}}}

Ustvarite dva nova materiala, enega, imenovanega portalSmoke, in drugega, imenovanega portalParticles.

Za vsakega izberite to senčilo, na spustnem seznamu, v portalih, delce. Za delce dima izberite teksturo dima, za delce pa teksturo delcev. Spremenite barvo dima v temno modro s približno 50% prozornostjo. Pojdite na komponento upodabljanja vsakega sistema delcev na svojem portalu in izberite ustrezne materiale, ki smo jih pravkar ustvarili.

7. korak: Ustvarite Skybox

Ustvarite Skybox
Ustvarite Skybox

Zdaj, da resnično ustvarimo obrnjen videz, moramo vse obarvati temno modro. Za to bomo uporabili pregleden skybox, zato naredite novo senco in prilepite to kodo:

Shader "Portal/portalSkybox" {

Lastnosti {_Tint ("Barva odtenka", Barva) = (.5,.5,.5,.5) [Gama] _Exposure ("Osvetlitev", Razpon (0, 8)) = 1.0 _Rotation ("Rotation", Range (0, 360)) = 0 [NoScaleOffset] _Tex ("Cubemap (HDR)", Cube) = "grey" {} _Stencil ("StencilNum", int) = 6} Podsenčnik {Oznake {"Čakalna vrsta" = "Ozadje" "RenderType" = "Ozadje" "PreviewType" = "Skybox"} Izključi ZWrite Off Blend SrcAlpha OneMinusSrcAlpha šablona {Ref 1 Comp [_Stencil]} Prenesite {CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 2.0 #CGclude ".cginc "samplerCUBE _Tex; pol4 _Tex_HDR; half4 _Tint; polovica _izpostavljenost; float _Rotation; float3 RotateAroundYInDegrees (float3 vertex, float stopinje) {float alpha = stopinje * UNITY_PI / 180.0; float sina, cosa; sincos (alfa, sina, cosa); float2x2 m = float2x2 (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 vertex: SV_POSITION; texcoord float3: 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 (zasukano); o.texcoord = v.vertex.xyz; vrniti o; } fixed4 frag (v2f i): SV_Target {half4 tex = texCUBE (_Tex, i.texcoord); half3 c = DecodeHDR (tex, _Tex_HDR); c = c * _Tint.rgb * unit_ColorSpaceDouble.rgb; c *= _Osvetlitev; vrni polovico4 (c,.5); } ENDCG}} Rezervni izklop}

Zdaj ustvarite nov material za skybox, ga pokličite "PortalSkybox" in v meniju portala izberite to senčilo portalSkybox. Pojdite na Window, Lighting na vrhu in izberite to skybox, ki smo ga pravkar ustvarili. Pojdite na glavno kamero in nastavite jasne zastavice v skybox. Medtem ko smo tukaj, lahko na naš fotoaparat dodamo nekatere komponente, da lahko zaznamo trke. Kameri dodajte komponento iz trdega telesa in počistite polje za uporabo gravitacije. Dodajte okvirni trkalnik in preverite, ali je sprožilec. Naj bo velikost nalepk okvirja 0,5 x 1 x 4. Nastavite ravnino izrezovanja na fotoaparatu na 0,01.

8. korak: Logika portala

Logika portala
Logika portala

Zadnja stvar, ki jo moramo storiti, je ustvariti logiko, ki upravlja naš portal. Ustvarite nov skript C# in ga pokličite PortalController.

z uporabo System. Collections;

z uporabo System. Collections. Generic; z uporabo UnityEngine; imenski prostor UnityEngine. XR.iOS {javni razred PortalController: MonoBehaviour {javni material materiali; javni MeshRenderer meshRenderer; javni UnityARVideo UnityARVideo; zasebni bool isInside = false; private bool isOutside = true; // To uporabite za inicializacijo 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 = res; InsidePortal (); }} else {if (isInside) {isInside = false; isOutside = res; ZunajPortal (); }}} 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 (Material mat v materialih) {mat. SetInt ("_Stencil", stencilNum); } yield return new WaitForEndOfFrame (); meshRenderer.enabled = res; UnityARVideo.shouldRender = res; }}}

Povlecite ta novi skript v okno portala. To nas bo preusmerilo v portal in iz njega, kadar koli trkalnik na naši kameri trči v okno portala. Zdaj v funkciji, ki spreminja vse materiale, povemo vtičniku ARkit, da ne upodobi okvirja, zato pojdite na glavno kamero in odprite skript UnityARVideo. Ustvarite javni bool shouldRender na vrhu in ga nastavite na true. Spodaj v funkciji OnPreRender () vse zavijte v stavek if, kjer se bo vse v notranjosti izvajalo le, če shouldRender drži. Celoten scenarij bi moral izgledati tako:

uporaba sistema;

z uporabo System. Runtime. InteropServices; z uporabo UnityEngine; uporaba UnityEngine. Rendering; imenski prostor UnityEngine. XR.iOS {javni razred UnityARVideo: MonoBehaviour {javni material m_ClearMaterial; [HideInInspector] javni bool shouldRender = true; zasebni CommandBuffer m_VideoCommandBuffer; zasebna Texture2D _videoTextureY; zasebno Texture2D _videoTextureCbCr; zasebna Matrix4x4 _displayTransform; zasebni bool bCommandBufferInitialized; public void Start () {UnityARSessionNativeInterface. ARFrameUpdatedEvent += UpdateFrame; bCommandBufferInitialized = false; } void UpdateFrame (kamera UnityARCamera) {_displayTransform = nova 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 = nov 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; } #if! 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, če (_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); } // Texture CbCr if (_videoTextureCbCr == null) {_videoTextureCbCr = Texture2D. CreateExternalTexture (currentResolution.width, currentResolution.height, TextureFormat. RG16, false, false, (System. IntPtr); _videoTextureCbCr.filterMode = FilterMode. Bilinearno; _videoTextureCbCr.wrapMode = TextureWrapMode. Repeat; m_ClearMaterial. SetTexture ("_ textureCbCr", _videoTextureCbCr); } _videoTextureY. UpdateExternalTexture (handles.textureY); _videoTextureCbCr. UpdateExternalTexture (handles.textureCbCr); 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); } #endif}}

9. korak: Skoraj končano

Skoraj končano!
Skoraj končano!

Ko kliknemo na zaslon in postavimo portal, želimo, da je vedno obrnjen proti nam. Če želite to narediti, pojdite na skript "UnityARHitTestExample" na portalu. Vse v notranjosti zamenjajte s tem:

uporaba sistema;

z uporabo System. Collections. Generic; imenski prostor UnityEngine. XR.iOS {javni razred UnityARHitTestExample: MonoBehaviour {public Transform m_HitTransform; javni plavajoči maxRayDistance = 30.0f; public LayerMask collisionLayer = 1 <0) {foreach (var hitResult v hitResults) {Debug. Log ("Got hit!"); m_HitTransform.position = UnityARMatrixOps. GetPosition (hitResult.worldTransform); m_HitTransform.rotation = UnityARMatrixOps. GetRotation (hitResult.worldTransform); Odpravljanje napak (niz. 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 = nov Vector3 (currAngle.x, transform.eulerAngles.y, currAngle.z); vrni true; }} return false; } // Posodobitev se kliče enkrat na okvir void Update () {#if UNITY_EDITOR // ta skript bomo uporabili le na strani urejevalnika, čeprav nič ne preprečuje delovanja na napravi, če (Input. GetMouseButtonDown (0)) {Ray ray = Camera.main. ScreenPointToRay (Input.mousePosition); Hit RaycastHit; // poskušali bomo zadeti enega od objektov ravninskih trkalnikov, ki jih je ustvaril vtičnik // dejansko podobno klicanju HitTesta z ARHitTestResultType. ARHitTestResultTypeExistingPlaneUsingExtent if (Physics. Raycast (ray, out hit, maxRayDistance, collisionLayer)) {// položaj bomo dobili od kontaktne točke m_HitTransform.position = hit.point; Odpravljanje napak (niz. Format ("x: {0: 0. ######} y: {1: 0. ######} z: {2: 0. ###### } ", m_HitTransform.position.x, m_HitTransform.position.y, m_HitTransform.position.z)); // in rotacija iz transformacije ravninskega trkalnika 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); Točka ARPoint = nova točka ARPoint {x = screenPosition.x, y = screenPosition.y}; // določitvi prednostnih nalog reults vrste ARHitTestResultType resultTypes = {ARHitTestResultType. ARHitTestResultTypeExistingPlaneUsingExtent, // če želijo uporabljati neskončne ravnine uporabljati to: //ARHitTestResultType. ARHitTestResultTypeExistingPlane, ARHitTestResultType. ARHitTestResultTypeHorizontalPlane, ARHitTestResultType. ARHitTestResultTypeFeaturePoint}; foreach (ARHitTestResultType resultType v resultTypes) {if (HitTestWithResultType (point, resultType)) {{return; }}}} #endif}}}

10. korak: aplikacijo postavite na telefon

Aplikacijo postavite na telefon!
Aplikacijo postavite na telefon!

Končno smo končali. Pojdite v datoteko, nastavitve gradnje in kliknite gradnja. Odprite Xcode in izberite mapo, ki je bila ustvarjena iz gradnje. Izberite svojo razvojno skupino in aplikacijo postavite na telefon! Morda boste želeli spremeniti barve delcev in skybox, da bodo ustrezale vašim potrebam. Sporočite mi v komentarjih, če imate kakršna koli vprašanja in hvala za ogled!

Priporočena: