【零unity基礎(chǔ)開發(fā)AR應(yīng)用05】蘋果vision pro:VR+透視就...

AR開發(fā)對編程感興趣但又沒有美工基礎(chǔ)的玩家非常適合。記錄一下AR動態(tài)照片墻(含點(diǎn)擊播放對應(yīng)視頻)的代碼:
一、動態(tài)照片墻,實(shí)現(xiàn)照片位置設(shè)計及相關(guān)關(guān)鍵數(shù)據(jù)。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
public class PhotoWallController : MonoBehaviour
{
??public static PhotoWallController _instance;
??//private VideoClip[] danceMov;
???
??public float photoSpace = 5.0f;
??private RectTransform[] photoRects;
??public RectTransform zeroPosition;
??public float maxWidthValue = 1920;
??//字典
??private Dictionary<RectTransform, Vector2> photoDic = new Dictionary<RectTransform, Vector2>();
??public float doEndPosTime = 1.0f;
??public float doAvoidViewPhotoTime = 0.5f;
??[Header("CurrentViewPhoto")]
??public RectTransform currentViewPhoto;
??public Vector3 originalScale = new Vector3(1, 1, 1);
??public Vector3 maxScale = new Vector3(3, 3, 3);
??private Vector2 originalPos;
??//照片排擠功能
??public float minDistance = 200;
??// Start is called before the first frame update
??void Start()
??{
????originalPos = currentViewPhoto.anchoredPosition;
??}
??private void Awake()
??{
????_instance = this;
??}
??// Update is called once per frame
??void Update()
??{
????//回歸原位置
????OpenDoEndPos();
????//排斥
????foreach (var photo in photoDic)
????{
??????float dis = Vector2.Distance(photo.Key.anchoredPosition, currentViewPhoto.anchoredPosition);
??????if (dis < minDistance)
??????{
????????Vector2 targetPos = currentViewPhoto.anchoredPosition+(photo.Key.anchoredPosition-currentViewPhoto.anchoredPosition).normalized*minDistance;
????????photo.Key.DOAnchorPos(targetPos, doAvoidViewPhotoTime);
??????}
????}
??}
??public void InitializationPhotos()
??{
????if (zeroPosition == null) return;
????//1.獲取所有照片的RectTransform和video clip
????var objs = GameObject.FindGameObjectsWithTag("myPhoto");
????photoRects = new RectTransform[objs.Length];
????for (int i = 0; i < objs.Length; i++)
????{
??????photoRects[i] = objs[i].GetComponent<RectTransform>();
??????//danceMov[i] = objs[i].GetComponent<VideoPlayer>().clip;
????}
????//2.計算并設(shè)置照片的排列位置
????Vector2 photoZero = zeroPosition.anchoredPosition;
????float currentWidthSum = 0;
????for(int i = 0; i < photoRects.Length; i++)
????{
??????Vector2 photoEndPos = photoZero + new Vector2(photoRects[i].rect.width / 2 + photoSpace, photoRects[i].rect.height / 2 + photoSpace);
??????photoZero += new Vector2(photoRects[i].rect.width + photoSpace, 0);
??????currentWidthSum += photoRects[i].rect.width + photoSpace;
??????if (currentWidthSum >= maxWidthValue)
??????{
????????photoZero = new Vector2(zeroPosition.anchoredPosition.x, photoZero.y+photoRects[i].rect.height + photoSpace);
????????currentWidthSum = 0;
??????}
??????photoDic.Add(photoRects[i], photoEndPos);
????}
????//做一個緩動
????Invoke("OpenDoEndPos", 1); //延遲1秒調(diào)用方法
???}
??void OpenDoEndPos()
??{
????foreach(var dic in photoDic)
????{
??????dic.Key.DOAnchorPos(dic.Value,doEndPosTime);
????}
??}
??public void CloseCurrentViewPhoto()
??{
????currentViewPhoto.anchoredPosition = originalPos;
??}
?????
}
二、當(dāng)前照片放大顯示(選中點(diǎn)擊后放大,若照片墻對象下掛了視頻,則播放視頻)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using DG.Tweening;
using UnityEngine.UI;
using UnityEngine.Video;
public class PhotoEventController : MonoBehaviour,IPointerDownHandler
{
???
??public void OnPointerDown(PointerEventData eventData)
??{
????RectTransform _currentViewPhoto = PhotoWallController._instance.currentViewPhoto;
????if (_currentViewPhoto == null) return;
????_currentViewPhoto.DOKill(); //殺死當(dāng)前RectTransform的所有DOTween動畫
????_currentViewPhoto.GetChild(0).GetComponent<VideoPlayer>().targetTexture.Release();//(fsx)釋放已播放的視頻
????_currentViewPhoto.anchoredPosition = this.GetComponent<RectTransform>().anchoredPosition;
????_currentViewPhoto.localScale = PhotoWallController._instance.originalScale;
????if (this.GetComponent<VideoPlayer>() == null)
????{
??????//如果照片墻對象沒有掛載視頻組件,則關(guān)閉當(dāng)前顯示照片框下的RawImage視頻播放對象
??????_currentViewPhoto.GetChild(0).gameObject.SetActive(false);
??????_currentViewPhoto.GetComponent<Image>().sprite = this.GetComponent<Image>().sprite;
????}
????else
????{
??????//如果照片墻對象掛載了視頻組件,則開啟當(dāng)前顯示照片框下的RawImage視頻播放對象,并加載對應(yīng)視頻
??????_currentViewPhoto.GetChild(0).gameObject.SetActive(true);
??????_currentViewPhoto.GetChild(0).GetComponent<VideoPlayer>().clip = this.GetComponent<VideoPlayer>().clip;
??????_currentViewPhoto.GetChild(0).GetComponent<VideoPlayer>().Play();
????}
?????
????_currentViewPhoto.DOScale(PhotoWallController._instance.maxScale, 1);
??}
??// Start is called before the first frame update
??void Start()
??{
?????
??}
??// Update is called once per frame
??void Update()
??{
?????
??}
}
三、上一期視頻遇到的如何讓UI顯示在玩家視野前方的問題,用如下代碼解決了
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
public class MenusController : MonoBehaviour
{
??public float x;
??public float y;
??public float z;
??bool buttonYPressed = false;
?
??// Start is called before the first frame update
??void Start()
??{
??}
??// Update is called once per frame
??void Update()
??{
????InputDevices.GetDeviceAtXRNode(XRNode.LeftHand).TryGetFeatureValue(CommonUsages.secondaryButton,out buttonYPressed);
????if (buttonYPressed)
????{
??????//GameObject[] myUIObjs = GameObject.FindGameObjectsWithTag("myUI");
??????//for (int i = 0; i <= myUIObjs.Length; i++)
??????//{
??????//??myUIObjs[i].SetActive(true);
??????//}
??????transform.rotation = Camera.main.transform.rotation;
??????transform.TransformDirection(Camera.main.transform.forward);
??????transform.position = Camera.main.transform.position;
??????transform.Translate(new Vector3(x, y, z));
??????Transform child = this.transform.Find("mainMenu");
??????if (!child.gameObject.activeSelf)
??????{
????????child.gameObject.SetActive(true);
??????}
????}
?????
??}
}