【零unity基础开发AR应用05】苹果vision pro:VR+透视就...

AR开发对编程感兴趣但又没有美工基础的玩家非常适合。记录一下AR动态照片墙(含点击播放对应视频)的代码:
一、动态照片墙,实现照片位置设计及相关关键数据。
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.计算并设置照片的排列位置
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秒调用方法
}
void OpenDoEndPos()
{
foreach(var dic in photoDic)
{
dic.Key.DOAnchorPos(dic.Value,doEndPosTime);
}
}
public void CloseCurrentViewPhoto()
{
currentViewPhoto.anchoredPosition = originalPos;
}
}
二、当前照片放大显示(选中点击后放大,若照片墙对象下挂了视频,则播放视频)
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(); //杀死当前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)
{
//如果照片墙对象没有挂载视频组件,则关闭当前显示照片框下的RawImage视频播放对象
_currentViewPhoto.GetChild(0).gameObject.SetActive(false);
_currentViewPhoto.GetComponent<Image>().sprite = this.GetComponent<Image>().sprite;
}
else
{
//如果照片墙对象挂载了视频组件,则开启当前显示照片框下的RawImage视频播放对象,并加载对应视频
_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);
}
}
}
}