Unity3D_VR或AR 凝视效果
效果展示
在Unity中的层级关系及命名
改变每个物体的属性
创建脚本 GazePartical,将该脚本挂载到CanvasGaze上
脚本代码如下:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; // 实心圆代表没有看到物体或看到的物体上没有碰撞器,空心圆带表看到了待遇碰撞器的物体 // 射线检测到的物体为 selectTrans public class GazePartical : MonoBehaviour { [Header("发出射线的物体")] // 一般为摄像机 public Transform rayGameObject; // 点击效果(粒子特效) public ParticleSystem clickPartical; // 返回选中的物体 [HideInInspector] public Transform selectTrans; // 开始转圈的等待时间(秒) private float startAnimatorTime = 1; // 转满一圈的时间(秒) private float finishCircleTime = 1; // 在看不到物体时显示 private GameObject imageSolid; // 看到可交互的物体时显示 private GameObject imageHollow150; // 看到可交互的物体一秒不变时显示 private Image imageHollow200; // 用于设置凝视点在看不到物体时的位置 private Transform imageSolidTrans; // 计时器 private float timer; // 当前看到的物体 private string targetName; // 是否开始计时 private bool isTime; // 是否达到激活条件 private bool isActivate; public bool IsActivate { get { if (imageHollow200.fillAmount >= 1) return true; else return false; } } void Start() { imageSolid = transform.Find("Image_Solid").gameObject; imageHollow150 = transform.Find("Image_Hollow150").gameObject; imageHollow200 = transform.Find("Image_Hollow150/Image_Hollow200").GetComponent<Image>(); // 用于设置凝视点在看不到物体时的位置 imageSolidTrans = new GameObject().transform; imageSolidTrans.parent = rayGameObject; imageSolidTrans.localPosition = new Vector3(0f, 0f, 4.5f); imageSolidTrans.localRotation = Quaternion.identity; // fillAmount 取值范围:0 ~ 1 imageHollow200.fillAmount = 0f; // 生成特效,并赋值 clickPartical = Instantiate(clickPartical.gameObject).GetComponent<ParticleSystem>(); } void Update() { Ray ray = new Ray(rayGameObject.position, rayGameObject.forward); RaycastHit raycastHit = new RaycastHit(); if (Physics.Raycast(ray, out raycastHit)) { // 显示空心,隐藏实心 imageHollow150.SetActive(true); imageSolid.SetActive(false); // 设置位置 transform.position = raycastHit.point; // 让圆环贴到物体表面 transform.forward = raycastHit.normal; // 当体验者盯住一个物体超过一秒,开始填充 if (raycastHit.transform.name == targetName) { isTime = true; } else { isTime = false; targetName = raycastHit.transform.name; } } else { // 显示实心,隐藏空心 imageSolid.SetActive(true); imageHollow150.SetActive(false); imageHollow200.fillAmount = 0f; // 归零计时器 isTime = false; timer = 0f; // 设置位置和旋转 transform.position = imageSolidTrans.position; transform.rotation = imageSolidTrans.rotation; } // 盯住同一个物体,开始计时 if (isTime) { timer += Time.deltaTime; } // 不盯住他物体时计时器初始化,重新计时 else { timer = 0f; imageHollow200.fillAmount = 0f; isPlayParticle = true; } if (timer >= startAnimatorTime) { timer = startAnimatorTime; imageHollow200.fillAmount += ((1 / finishCircleTime) / (1 / Time.deltaTime)); } if (imageHollow200.fillAmount >= 1f) { // 播放点击粒子 ClickParticle(raycastHit.transform.position); selectTrans = raycastHit.transform; } else { selectTrans = null; } // 测试:打印检测到的物体 // if (selectTrans) print("射线检测到的物体:" + selectTrans.name); } // 是否播放粒子 private bool isPlayParticle; // 点击粒子 private void ClickParticle(Vector3 point) { if (isPlayParticle) { // 特效位置 clickPartical.transform.position = transform.position + (transform.forward * 0.001f); clickPartical.transform.rotation = transform.rotation; if (clickPartical.isPlaying) { clickPartical.Stop(); } // 播放粒子 clickPartical.Play(); isPlayParticle = false; } } }
本示例 UnityPackage 下载