Съдържание:

AR портал към главата надолу от странни неща: 10 стъпки (със снимки)
AR портал към главата надолу от странни неща: 10 стъпки (със снимки)

Видео: AR портал към главата надолу от странни неща: 10 стъпки (със снимки)

Видео: AR портал към главата надолу от странни неща: 10 стъпки (със снимки)
Видео: 14 СТРАННИ неща, които за ПЪРВИ ПЪТ ще ВИДИТЕ в живота си 2024, Юли
Anonim
AR портал към главата надолу от странни неща
AR портал към главата надолу от странни неща
AR портал към главата надолу от странни неща
AR портал към главата надолу от странни неща

Този Instructable ще премине през създаването на мобилно приложение за разширена реалност за iPhone с портал, който води към главата надолу от Stranger Things. Можете да влезете в портала, да се разходите и да излезете. Всичко в портала може да се вижда само през портала, докато не влезете вътре. След като влезе вътре, всичко ще се визуализира навсякъде, докато не се върнете обратно в реалния свят. Ще използваме Unity 3D видеоиграта с приставката Apple ARKit. Целият софтуер, който ще използваме, може да бъде изтеглен и използван безплатно. Не е нужно да сте експерт, за да следвате, ние ще преминем през всяка стъпка!

Стъпка 1: Стартирайте нов проект Unity

Стартирайте нов проект за единство
Стартирайте нов проект за единство

Първо изтеглете Unity3D и не забравяйте да инсталирате файловете за компилация за IOS платформата. Също така ще трябва да изтеглите Xcode и да се регистрирате за безплатен акаунт за разработчици на Apple. Вашият iPhone също ще трябва да работи с IOS 11 или по -нова версия. От днес 5 февруари 2018 г. IOS 11.3 е излязъл, но xCode 9.2 все още няма файлове за поддръжка за него. Така че, ако използвате най -новата версия на IOS, не забравяйте да изтеглите най -новата бета версия на Xcode от Apple. Developer.com.

След като имате всички необходими програми, отворете Unity и започнете нов проект, наречете го както искате. Ще се нуждаем от приставката Apple ARKit, за да можем да използваме камерата на телефона си, за да открием земята и да поставим обекти на пода. Нека импортираме това сега, като отидем в раздела Asset Store и потърсим „ARKit“. Ще трябва да създадете безплатен акаунт в Unity, ако все още нямате такъв, след което щракнете върху импортиране, за да получите приставката.

Придвижете се до папката с примери в папката ARKit и намерете „UnityARKitScene“. Щракнете двукратно върху него, за да го отворите. Ще използваме тази сцена като отправна точка и ще изградим оттук нататък. Тази сцена по подразбиране ще ви позволи да откриете земята и когато докоснете екрана, куб ще бъде поставен в тази позиция.

Нека първо да нагласим нашите настройки за изграждане, за да не забравим да го направим по -късно. Щракнете върху файл, създайте настройки и премахнете всички сцени от този списък. Щракнете върху добавяне на отворени сцени, за да добавите нашата текуща. Последното нещо, което трябва да настроим тук, е в настройките на плейъра да отидат до идентификатора на пакета и форматът за този низ е com. YourCompanyName. YourAppName, така че в моя случай правя нещо като com. MatthewHallberg. PortalTest.

Стъпка 2: Настройте сцената

Настройте сцената
Настройте сцената

Първо погледнете вляво и намерете обекта на играта, наречен "GeneratePlanes". С това подчертано, погледнете вдясно сега и щракнете върху квадратчето за отметка, за да го деактивирате. По този начин нямаме генерираните грозни сини квадрати, когато ARKit открие равнина на земята. След това изтрийте игралния обект "RandomCube", защото не искаме да виждаме това в нашата сцена.

Сега първо трябва да създадем вратата на нашия портал. Изтрийте куба, който е дете на "HitCubeParent". Щракнете с десния бутон и изберете създаване на празен игрален обект. Преименувайте го на „Портал“. Сега щракнете с десния бутон върху този обект и създайте куб, това ще го направи дете на портала. Преименувайте го на „PostLeft“и това ще бъде лявата публикация на нашия портал. Мащабирайте го така, че x е 1, y е 28, а z е единица. Направете същото за правилния пост. Сега създайте най -горния пост и мащабирайте y до 14. Завъртете това настрани и го преместете така, че да свързва другите стойки. Направете цялата скала на портала 1,3 x 1,4 x 1.

Отидете в google и въведете текстура на дърво или кора. Изтеглете едно от тези изображения и го плъзнете в папката с активи в Unity. Сега плъзнете това изображение във всичките си публикации в портала.

Кликнете отново върху обекта "Портал" и щракнете върху добавяне на компонент вдясно. Добавете скрипта "UnityARHitTestExample" към него. Там има празен слот за "Hit Transform", плъзнете обекта "HitCubeParent" в този слот.

Стъпка 3: Нека направим някои частици

Нека направим някои частици
Нека направим някои частици

Сега ще използваме системата Unity Particle, за да направим ефект на дим и плаващи частици в нашия портал. Отидете на Активи в горната лента с менюта, стандартни активи и импортирайте частични системи.

Създайте два празни обекта за игра във вашия портал и наречете единия „SmokeParticles“, а другия „FloatingParticles“.

Добавете компонент на система от частици към димните частици.

Този компонент има куп опции, но трябва само да променим няколко.

Променете началния цвят на нещо тъмно синьо с около 50% прозрачност. Направете емисионната норма 100. Вътрешната форма, направете радиуса.01. В частта за визуализация в долната част променете минималния размер на.8 и максималния размер на 5. На компонента материал просто изберете материала за дим от списъка, но ще го променим по -късно.

Добавете система от частици към игралния обект с плаващи частици сега и задайте емисията на 500. Задайте началния живот на 2, радиус на 10, минимален размер на частиците на.01 и максимален размер на частиците на.015. Задайте материала за частици по подразбиране засега.

Накрая вземете двата предмета на играта и ги завъртете на 90 градуса върху x и ги повдигнете във въздуха, така че да излъчват надолу към вратата на портала.

Стъпка 4: Забавяне на частиците

Забавяне на частиците
Забавяне на частиците

Тъй като искаме тези частици да обхващат голяма площ, но и да се движат бавно, трябва да създадем своя собствена пробна функция. Така че щракнете с десния бутон в папката с активи и създайте нов C# скрипт и го наречете „ParticleSample“. Копирайте и поставете в този код:

използване на System. Collections;

използване на System. Collections. Generic; използване на UnityEngine; публичен клас ParticleSample: MonoBehaviour {private ParticleSystem ps; // Използвайте това за инициализация void Start () {ps = GetComponent (); StartCoroutine (SampleParticleRoutine ()); } IEnumerator SampleParticleRoutine () {var main = ps.main; main.simulationSpeed = 1000f; ps. Play (); return връщане new WaitForSeconds (.1f); main.simulationSpeed =.05f; }}

Сега плъзнете този скрипт върху всеки от обектите на вашата система за частици.

Стъпка 5: Създаване на портала

Създаване на портала!
Създаване на портала!

Сега трябва да създадем портала, така че щракнете с десния бутон върху обекта на порталната игра и създайте четворка. Мащабирайте четириъгълника, така че да обхваща целия портал, това ще се превърне в нашия прозорец на портала. Първото нещо, което трябва да добавим към него, е порталният шейдър, това ще изобразява само обекти с друг специфичен шейдър върху тях. Щракнете с десния бутон в папката с активи и създайте нов неосветен шейдър. Премахнете всичко там и поставете този код:

Шейдър „Портал/портален прозорец“

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

Щракнете с десния бутон в йерархията и създайте нов материал, наречете го PortalWindowMat, в падащото меню за този материал намерете секцията на портала и изберете прозореца на портала. Плъзнете този материал върху вашия четириъгълен портал.

Стъпка 6: Шейдъри за частици

Шейдъри за частици
Шейдъри за частици

Щракнете отново с десния бутон в папката с активи и създайте нов шейдър. Трябва да направим шейдъри за частиците, които влизат в портала. Заменете целия код с това:

Шейдър „Портал/частици“{

Свойства {_TintColor ("Цвят на нюанса", Цвят) = (0.5, 0.5, 0.5, 0.5) _MainTex ("Текстура на частиците", 2D) = "бял" {} _InvFade ("Фактор на меките частици", Диапазон (0.01, 3.0)) = 1.0 _Stencil ("stencil", int) = 6} Категория {Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane"} Blend SrcAlpha OneMinusSrcAlpha ColorMask RGB Cull Off Осветление Off ZWrite Off SubShader {Stencil {Ref 1 Comp [_Stencil]} Предайте {CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 2.0 #pragma multi_compile_particles #pragma multi_compile_fog #include "UnityCG2 фиксиран4 _TintColor; struct appdata_t {float4 vertex: POSITION; фиксиран4 цвят: ЦВЯТ; float2 texcoord: TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID}; struct v2f {float4 vertex: SV_POSITION; фиксиран4 цвят: ЦВЯТ; 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.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); връщане o; } UNITY_DECLARE_DEPTH_TEXTURE (_CameraDepthTexture); float _InvFade; fixed4 frag (v2f i): SV_Target {#ifdef SOFTPARTICLES_ON флоат сцена Z = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ (_CameraDepthTexture, UNITY_PROJ_COORD (i.projPos))); поплавъчна частZ = i.projPos.z; float fade = saturate (_InvFade * (sceneZ-partZ)); i.color.a *= избледняване; #endif fixed4 col = 2.0f * i.color * tex2D (_MainTex, i.texcoord); UNITY_APPLY_FOG (i.fogCoord, колона); връщане на колона; } ENDCG}}}}

Създайте два нови материала, един наречен portalSmoke и един, наречен portalParticles.

За всеки от тях изберете този шейдър, от падащото меню, в портали, частици. За частиците дим изберете текстура на дим, а за частиците - текстурата на частиците. Променете цвета на дима на по -тъмно син с около 50% прозрачност. Отидете на компонента за визуализация на всяка система от частици във вашия портал и изберете съответните им материали, които току -що създадохме.

Стъпка 7: Създайте Skybox

Създайте Skybox
Създайте Skybox

Сега, за да създадем наистина обърнат вид, трябва да оцветим всичко в тъмно синьо. За това ще използваме прозрачен skybox, така че направете нов шейдър и поставете в този код:

Шейдър „Portal/portalSkybox“{

Свойства {_Tint ("Цвят на нюанса", Цвят) = (.5,.5,.5,.5) [Gamma] _Exposure ("Експозиция", Диапазон (0, 8)) = 1.0 _Rotation ("Rotation", Range (0, 360)) = 0 [NoScaleOffset] _Tex ("Cubemap (HDR)", Cube) = "сив" {} _Stencil ("StencilNum", int) = 6} SubShader {Tags {"Queue" = "Background" "RenderType" = "Фон" "PreviewType" = "Skybox"} Изключете ZWrite Off Blend SrcAlpha OneMinusSrcAlpha Stencil {Ref 1 Comp [_Stencil]} Предайте {CGPROGRAM #pragma vertex vert #pragma фрагмент frag #pragma target 2.0 #CGclude ".cginc "samplerCUBE _Tex; половина4 _Tex_HDR; half4 _Tint; наполовина _Експозиция; float _Rotation; float3 RotateAroundYInDegrees (float3 vertex, float градуси) {float alpha = градуси * UNITY_PI / 180.0; float 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; 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 (завъртяно); o.texcoord = v.vertex.xyz; връщане o; } fixed4 frag (v2f i): SV_Target {half4 tex = texCUBE (_Tex, i.texcoord); half3 c = DecodeHDR (tex, _Tex_HDR); c = c * _Tint.rgb * единство_ColorSpaceDouble.rgb; c *= _ Експозиция; върнете половината4 (c,.5); } ENDCG}} Резервно изключване}

Сега създайте нов материал за skybox, наречете го „PortalSkybox“и изберете този портал SkySky шейдър от менюто на портала. Отидете на Window, Lighting, в горната част и изберете този skybox, който току -що създадохме. Отидете до основната камера и задайте ясни знамена към skybox. Докато сме тук, нека добавим някои компоненти към нашата камера, за да можем да откриваме сблъсъци. Добавете компонент с твърдо тяло към камерата и премахнете отметката от гравитацията. Добавете кутия коллайдер и проверете дали е задействан. Направете размера на колайдерите на кутията.5 x 1 x 4. Задайте равнината на изрязване на камерата на.01.

Стъпка 8: Логика на портала

Портална логика
Портална логика

Последното нещо, което трябва да направим, е да създадем логиката, която контролира нашия портал. Създайте нов C# скрипт и го наречете PortalController.

използване на System. Collections;

използване на System. Collections. Generic; използване на UnityEngine; пространство на имената UnityEngine. XR.iOS {публичен клас PortalController: MonoBehaviour {обществени материали материали; публичен MeshRenderer meshRenderer; публичен UnityARVideo UnityARVideo; private bool isInside = false; private bool isOutside = вярно; // Използвайте това за инициализация 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 = вярно; OutsidePortal (); }}} void OutsidePortal () {StartCoroutine (DelayChangeMat (3)); } void InsidePortal () {StartCoroutine (DelayChangeMat (6)); } IEnumerator DelayChangeMat (int stencilNum) {UnityARVideo.shouldRender = false; return return new WaitForEndOfFrame (); meshRenderer.enabled = false; foreach (Материал мат в материали) {mat. SetInt ("_Stencil", stencilNum); } yield return new WaitForEndOfFrame (); meshRenderer.enabled = вярно; UnityARVideo.shouldRender = вярно; }}}

Плъзнете този нов скрипт в прозореца на портала. Това ще ни прехвърли навътре и извън портала винаги, когато сблъсъкът на нашата камера се сблъска с прозореца на портала. Сега във функцията, която променя всички материали, казваме на приставката ARkit да не изобразява рамката, така че отидете на основната камера и отворете скрипта UnityARVideo. Създайте публичен bool shouldRender в горната част и го задайте равно на true. Долу във функцията OnPreRender () увийте всичко в оператор if, където всичко вътре ще работи само ако shouldRender е истина. Целият скрипт трябва да изглежда така:

използване на System;

използване на System. Runtime. InteropServices; използване на UnityEngine; използване на UnityEngine. Rendering; пространство на имената UnityEngine. XR.iOS {публичен клас UnityARVideo: MonoBehaviour {обществен материал m_ClearMaterial; [HideInInspector] публичен bool shouldRender = true; частен CommandBuffer m_VideoCommandBuffer; частна Texture2D _videoTextureY; частна Texture2D _videoTextureCbCr; частна Matrix4x4 _displayTransform; частен bool bCommandBufferInitialized; public void Start () {UnityARSessionNativeInterface. ARFrameUpdatedEvent += UpdateFrame; bCommandBufferInitialized = false; } void UpdateFrame (камера UnityARCamera) {_displayTransform = нова 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 = нов CommandBuffer (); m_VideoCommandBuffer. Blit (null, BuiltinRenderTextureType. CurrentActive, m_ClearMaterial); GetComponent (). AddCommandBuffer (CameraEvent. BeforeForwardOpaque, m_VideoCommandBuffer); bCommandBufferInitialized = вярно; } void OnDestroy () {GetComponent (). RemoveCommandBuffer (CameraEvent. BeforeForwardOpaque, m_VideoCommandBuffer); UnityARSessionNativeInterface. ARFrameUpdatedEvent -= UpdateFrame; bCommandBufferInitialized = false; } #ако! UNITY_EDITOR публична анулиране OnPreRender () {if (shouldRender) {ARTextureHandles handles = UnityARSessionNativeInterface. GetARSessionNativeInterface (). GetARVideoTextureHandles (); if (handles.textureY == System. IntPtr. Zero || handles.textureCbCr == System. IntPtr. Zero) {връщане; } if (! bCommandBufferInitialized) {InitializeCommandBuffer (); } Резолюция currentResolution = Screen.currentResolution; // Текстура Y, ако (_videoTextureY == null) {_videoTextureY = Texture2D. CreateExternalTexture (currentResolution.width, currentResolution.height, TextureFormat. R8, false, false, (System. IntPtr) handles.textureY); _videoTextureY.filterMode = FilterMode. Bilinear; _videoTextureY.wrapMode = TextureWrapMode. Repeat; m_ClearMaterial. SetTexture ("_ textureY", _videoTextureY); } // Текстура CbCr, ако (_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 (handles.textureY); _videoTextureCbCr. UpdateExternalTexture (handles.textureCbCr); m_ClearMaterial. SetMatrix ("_ DisplayTransform", _displayTransform); }} #else public void SetYTexure (Texture2D YTex) {_videoTextureY = YTex; } обществена пустота 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: Почти готово

Почти готово!
Почти готово!

И накрая, когато щракнем върху екрана и поставим портала, искаме той винаги да е с лице към нас. За да направите това, отидете на скрипта "UnityARHitTestExample" на портала. Заменете всичко вътре с това:

използване на System;

използване на System. Collections. Generic; пространство на имената UnityEngine. XR.iOS {публичен клас UnityARHitTestExample: MonoBehaviour {public Transform m_HitTransform; публично плаващо maxRayDistance = 30.0f; публичен LayerMask collisionLayer = 1 <0) {foreach (var hitResult в 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 = нов Vector3 (currAngle.x, transform.eulerAngles.y, currAngle.z); връщане true; }} return false; } // Актуализацията се извиква веднъж на кадър void Update () {#if UNITY_EDITOR // ще използваме само този скрипт от страна на редактора, въпреки че няма нищо, което да му попречи да работи на устройството, ако (Input. GetMouseButtonDown (0)) {Ray ray = Camera.main. ScreenPointToRay (Input.mousePosition); RaycastHit хит; // ще се опитаме да ударим един от обектите за самолетни колайдери, генерирани от приставката // ефективно подобно на извикването на HitTest с ARHitTestResultType. ARHitTestResultTypeExistingPlaneUsingExtent if (Physics. Raycast (ray, out hit, maxRayDistance, collisionLayer)) {// ще получим позицията от точката за контакт 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)); // и въртенето от трансформацията на равнинния колайдер 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 = нова ARPoint {x = screenPosition.x, y = screenPosition.y}; // даване на приоритет reults видове ARHitTestResultType resultTypes = {ARHitTestResultType. ARHitTestResultTypeExistingPlaneUsingExtent, // ако искате да използвате безкрайни равнини използват това: //ARHitTestResultType. ARHitTestResultTypeExistingPlane, ARHitTestResultType. ARHitTestResultTypeHorizontalPlane, ARHitTestResultType. ARHitTestResultTypeFeaturePoint}; foreach (ARHitTestResultType resultType в resultTypes) {if (HitTestWithResultType (точка, resultType)) {return; }}}} #endif}}}

Стъпка 10: Поставете приложението на телефона си

Поставете приложението на телефона си!
Поставете приложението на телефона си!

Накрая свършихме. Отидете на файл, създайте настройки и щракнете върху изграждане. Отворете Xcode и изберете папката, създадена от компилацията. Изберете своя екип за разработка и поставете приложението на телефона си! Може да искате да промените цветовете на частиците и skybox, за да отговарят на вашите нужди. Кажете ми в коментарите, ако имате въпроси и благодаря за търсенето!

Препоръчано: