Оглавление:
- Шаг 1. Начните новый проект Unity
- Шаг 2: Настройте сцену
- Шаг 3: сделаем несколько частиц
- Шаг 4. Замедление частиц
- Шаг 5: Создание портала
- Шаг 6: шейдеры частиц
- Шаг 7: Создайте Skybox
- Шаг 8: логика портала
- Шаг 9: почти готово
- Шаг 10: Установите приложение на свой телефон
Видео: Портал дополненной реальности в перевернутом виде из очень странных дел: 10 шагов (с изображениями)
2024 Автор: John Day | [email protected]. Последнее изменение: 2024-01-30 11:53
В этом руководстве мы создадим мобильное приложение с дополненной реальностью для 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, чтобы создать эффект дыма и плавающих частиц внутри нашего портала. Перейдите в Assets в верхней строке меню, стандартные активы и импортируйте системы частиц.
Создайте два пустых игровых объекта внутри своего портала и назовите один «SmokeParticles», а другой «FloatingParticles».
Добавьте к частицам дыма компонент системы частиц.
У этого компонента есть множество опций, но нам нужно изменить только пару.
Измените начальный цвет на темно-синий с прозрачностью около 50%. Сделайте скорость излучения 100. Внутри формы сделайте радиус 0,01. В части рендеринга внизу измените минимальный размер на 0,8 и максимальный размер на 5. В компоненте материала просто выберите материал дыма из списка, но мы собираемся изменить это позже.
Теперь добавьте систему частиц к игровому объекту с плавающими частицами и установите излучение на 500. Установите время начала действия на 2, радиус на 10, минимальный размер частицы на 0,01 и максимальный размер частицы на 0,015. На данный момент установите материал для частиц по умолчанию.
Наконец, возьмите оба игровых объекта, поверните их на 90 градусов по оси x и поднимите в воздух, чтобы они падали в дверной проем портала.
Шаг 4. Замедление частиц
Поскольку мы хотим, чтобы эти частицы покрывали большую площадь, но при этом двигались медленно, нам нужно создать нашу собственную функцию-образец. Итак, щелкните правой кнопкой мыши папку с ресурсами и создайте новый сценарий C # и назовите его «ParticleSample». Скопируйте и вставьте этот код:
using System. Collections;
using System. Collections. Generic; using UnityEngine; публичный класс ParticleSample: MonoBehaviour {частный ParticleSystem ps; // Используйте это для инициализации void Start () {ps = GetComponent (); StartCoroutine (SampleParticleRoutine ()); } IEnumerator SampleParticleRoutine () {var main = ps.main; main.simulationSpeed = 1000f; ps. Play (); yield return новый WaitForSeconds (.1f); main.simulationSpeed =.05f; }}
Теперь перетащите этот скрипт на каждый игровой объект вашей системы частиц.
Шаг 5: Создание портала
Теперь нам нужно создать портал, поэтому щелкните правой кнопкой мыши на игровом объекте портала и создайте четырехугольник. Измените масштаб квадрата так, чтобы он покрыл весь портал, он станет нашим окном портала. Первое, что нам нужно добавить к нему, это шейдер портала, он будет отображать только объекты с другим конкретным шейдером на них. Щелкните правой кнопкой мыши папку с ресурсами и создайте новый неосвещенный шейдер. Удалите все и вставьте этот код:
Шейдер "Portal / portalWindow"
{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} Категория {Теги {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane"} Blend SrcAlpha OneMinusSrcAlpha ColorMask RGB Cull 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 "_SampleCG.cg" fixed4 _TintColor; struct appdata_t {вершина float4: ПОЗИЦИЯ; fixed4 цвет: ЦВЕТ; float2 texcoord: TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID}; struct v2f {вершина float4: SV_POSITION; fixed4 цвет: ЦВЕТ; float2 texcoord: TEXCOORD0; UNITY_FOG_COORDS (1) #ifdef SOFTPARTICLES_ON float4 projPos: TEXCOORD2; #endif UNITY_VERTEX_OUTPUT_STEREO}; float4 _MainTex_ST; v2f верт (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); return 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))); float partZ = 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, столбец); return col; } ENDCG}}}}
Создайте два новых материала, один под названием portalSmoke, а другой под названием portalParticles.
Для каждого выберите этот шейдер в раскрывающемся списке порталов, частиц. Для частиц дыма выберите текстуру дыма, а для частиц выберите текстуру частиц. Измените цвет дыма на темно-синий с прозрачностью около 50%. Перейдите к компоненту рендеринга каждой системы частиц на вашем портале и выберите соответствующие материалы, которые мы только что создали.
Шаг 7: Создайте Skybox
Теперь, чтобы действительно создать перевернутый вид, нам нужно окрасить все в темно-синий цвет. Для этого мы будем использовать прозрачный скайбокс, поэтому создайте новый шейдер и вставьте этот код:
Шейдер "Portal / portalSkybox" {
Свойства {_Tint ("Цвет оттенка", Color) = (.5,.5,.5,.5) [Gamma] _Exposure ("Exposure", Range (0, 8)) = 1.0 _Rotation ("Rotation", Range (0, 360)) = 0 [NoScaleOffset] _Tex ("Cubemap (HDR)", Cube) = "серый" {} _Stencil ("StencilNum", int) = 6} SubShader {Tags {"Queue" = "Фон" "RenderType" = "Background" "PreviewType" = "Skybox"} Cull Off ZWrite Off Blend SrcAlpha OneMinusSrcAlpha Stencil {Ref 1 Comp [_Stencil]} Передать {CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 2.0Colder #inGclude.cginc "samplerCUBE _Tex; half4 _Tex_HDR; half4 _Tint; половина _Exposure; float _Rotation; float3 RotateAroundYInDegrees (вершина float3, градусы с плавающей запятой) {альфа с плавающей точкой = градусы * UNITY_PI / 180.0; float sina, cosa; синко (альфа, сина, коза); float2x2 m = float2x2 (cosa, -sina, sina, cosa); вернуть float3 (mul (m, vertex.xz), vertex.y).xzy; } struct appdata_t {вершина float4: ПОЗИЦИЯ; UNITY_VERTEX_INPUT_INSTANCE_ID}; struct v2f {вершина float4: SV_POSITION; float3 texcoord: TEXCOORD0; UNITY_VERTEX_OUTPUT_STEREO}; v2f верт (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; return 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 * = _Exposure; вернуть half4 (c,.5); } ENDCG}} Откл. Откл.}
Теперь создайте новый материал скайбокса, назовите его «PortalSkybox» и выберите этот шейдер portalSkybox в меню портала. Перейдите в Window, Lighting, вверху и выберите этот скайбокс, который мы только что создали. Подойдите к основной камере и установите флажки для скайбокса. Пока мы здесь, давайте добавим некоторые компоненты в нашу камеру, чтобы мы могли обнаруживать столкновения. Добавьте в камеру компонент твердого тела и снимите флажок использовать гравитацию. Добавьте коллайдер коробки и отметьте триггер. Установите размер коллайдера бокса 0,5 x 1 x 4. Установите плоскость отсечения камеры на 0,01.
Шаг 8: логика портала
Последнее, что нам нужно сделать, это создать логику, управляющую нашим порталом. Создайте новый сценарий C # и назовите его PortalController.
using System. Collections;
using System. Collections. Generic; using UnityEngine; пространство имен UnityEngine. XR.iOS {открытый класс PortalController: MonoBehaviour {общедоступные материалы материалы; общедоступный MeshRenderer meshRenderer; общедоступный UnityARVideo UnityARVideo; частный bool isInside = false; private bool isOutside = true; // Используйте это для инициализации void Start () {OutsidePortal (); } void OnTriggerStay (Collider col) {Vector3 playerPos = Camera.main.transform.position + Camera.main.transform.forward * (Camera.main.nearClipPlane * 4); если (transform. InverseTransformPoint (playerPos).z <= 0) {если (isOutside) {isOutside = false; isInside = true; InsidePortal (); }} еще {если (isInside) {isInside = false; isOutside = true; 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 (Мат материала в материалах) {mat. SetInt ("_Stencil", stencilNum); } yield return new WaitForEndOfFrame (); meshRenderer.enabled = true; UnityARVideo.shouldRender = true; }}}
Перетащите этот новый скрипт в окно вашего портала. Это будет перемещать нас в портал и обратно всякий раз, когда коллайдер на нашей камере сталкивается с окном портала. Теперь в функции, которая изменяет все материалы, мы говорим плагину ARkit не отображать кадр, поэтому перейдите к основной камере и откройте скрипт UnityARVideo. Создайте публичный bool shouldRender вверху и установите для него значение true. Внизу в функции OnPreRender () оберните все в оператор if, где все внутри будет запускаться только в том случае, если shouldRender истинно. Весь сценарий должен выглядеть так:
используя Систему;
using System. Runtime. InteropServices; using UnityEngine; с использованием UnityEngine. Rendering; пространство имен UnityEngine. XR.iOS {открытый класс UnityARVideo: MonoBehaviour {общедоступный материал m_ClearMaterial; [HideInInspector] public bool shouldRender = true; частный CommandBuffer m_VideoCommandBuffer; частный Texture2D _videoTextureY; частный Texture2D _videoTextureCbCr; частный 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 = новый 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 public void OnPreRender () {if (shouldRender) {ARTextureHandles handles = UnityARSessionNativeInterface. GetARSessionNativeInterface (). GetARVideoTextureHandles (); если (handles.textureY == System. IntPtr. Zero || handles.textureCbCr == System. IntPtr. Zero) {возврат; } если (! bCommandBufferInitialized) {InitializeCommandBuffer (); } Разрешение currentResolution = Screen.currentResolution; // Текстура Y if (_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 if (_videoTextureCbCr == null) {_videoTextureCbCr = Texture2D. CreateExternalTexture (currentResolution.width, currentResolution.height, TextureFormat. RG16, false, false, (System. IntPtr) handles.textureCbCr); _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; } public void SetUVTexure (Texture2D UVTex) {_videoTextureCbCr = UVTex; } public void OnPreRender () {если (! bCommandBufferInitialized) {InitializeCommandBuffer (); } m_ClearMaterial. SetTexture ("_ textureY", _videoTextureY); m_ClearMaterial. SetTexture ("_ textureCbCr", _videoTextureCbCr); m_ClearMaterial. SetMatrix ("_ DisplayTransform", _displayTransform); } #endif}}
Шаг 9: почти готово
Наконец, когда мы щелкаем по экрану и размещаем портал, мы хотим, чтобы он всегда был обращен к нам. Для этого перейдите к скрипту «UnityARHitTestExample» на портале. Замени все внутри на это:
используя Систему;
using System. Collections. Generic; пространство имен UnityEngine. XR.iOS {открытый класс UnityARHitTestExample: MonoBehaviour {общедоступное преобразование m_HitTransform; публичный поплавок maxRayDistance = 30.0f; общедоступный LayerMask collisionLayer = 1 <0) {foreach (var hitResult в hitResults) {Debug. Log ("Попал!"); 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); вернуть истину; }} return false; } // Обновление вызывается один раз за кадр void Update () {#if UNITY_EDITOR // мы будем использовать этот скрипт только на стороне редактора, хотя нет ничего, что могло бы помешать ему работать на устройстве if (Input. GetMouseButtonDown (0)) {Ray ray = Camera.main. ScreenPointToRay (Input.mousePosition); RaycastHit Hit; // мы попытаемся поразить один из игровых объектов коллайдера плоскости, который был сгенерирован плагином // эффективно аналогично вызову 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 (point, resultType)) {return; }}}} #endif}}}
Шаг 10: Установите приложение на свой телефон
Наконец мы закончили. Зайдите в файл, выберите настройки сборки и нажмите build. Откройте Xcode и выберите папку, созданную при сборке. Выберите команду разработчиков и установите приложение на свой телефон! Вы можете изменить цвета частиц и скайбокса в соответствии с вашими потребностями. Дайте мне знать в комментариях, если у вас есть какие-либо вопросы, и спасибо, что посмотрели!
Рекомендуемые:
GlobalARgallery - Глобальная галерея дополненной реальности: 16 шагов
#GlobalARgallery - Глобальная галерея дополненной реальности: #GlobalARgallery - это возможность для школ (и других) асинхронно подключаться по всему миру и делиться опытом, произведениями искусства, историями, хрониками, выставками, презентациями и всем остальным, что вы можете себе представить. Все это появляется в A
Головоломка дополненной реальности: 11 шагов
Головоломка с дополненной реальностью: Головоломки просто замечательны. Есть пазлы всех видов, типичные пазлы, лабиринты с жетонами и даже видеоигры этого жанра (например, Captain Toad). Головоломки требуют от игрока разработки стратегии решения проблем
Arduino Glass - гарнитура дополненной реальности с открытым исходным кодом: 9 шагов (с изображениями)
Arduino Glass - гарнитура дополненной реальности с открытым исходным кодом: задумывались ли вы когда-нибудь о приобретении гарнитуры дополненной реальности? Вы тоже были поражены возможностью дополненной реальности и с разбитым сердцем смотрели на ценник? Да, я тоже! Но это меня не остановило. Я набрался храбрости и вместо этого
Размещение объектов AR в координатах GPS в дополненной реальности: 8 шагов (с изображениями)
Размещение объектов AR в координатах GPS в дополненной реальности: в этом руководстве мы рассмотрим создание мобильного приложения для размещения объектов AR в координатах GPS с помощью ARkit и ARCore с использованием Unity3D. Я проведу вас через настройку проекта, который я сделал с помощью Mapbox, который позволяет нам помечать сообщения в определенных G
Витрина продуктов дополненной реальности (TfCD): 11 шагов (с изображениями)
Витрина продуктов с дополненной реальностью (TfCD): Продажа продуктов во время полета становится все более популярной в настоящее время. Однако в самолете первая и почти единственная информация, которую видит пассажир (возможный покупатель), - это печатная брошюра. Это руководство покажет, как вводить новшества в airp