感谢yolon3000大神关于ARCore的详细介绍,本文已获转载权限!
本文记录ARCore从零到放置物体的关键步骤,详细解析请参考博客:ARCore之路
1、导入ARCore SDK
2、删掉场景中Main Camera 和 Directional Light
3、将”GoogleARCore-Prefabs下的 ARCore Device 和 Environmental Light 两个预制体拖到场景,添加Event System
ARCore Device处理所有与设备相关的事宜,更新device的位置,更新Anchor的位置,更新检测到的平面等等
Enviromental Light则处理所有光照相关事宜,如光照强度估计,光源方向估计等等
Event System使我们的应用能监听和处理事件信息
4、可视化平面
a、新建DetectedPlaceGenerater空gameobject,给其添加DetectedPlaneGenerator
b、制作Prefab平面,添加到 a 的 DetectedPlaneGenerator 脚本上
1)、新建名为 VisualDetectedPlane 的 3DObject—Plane,必须Reset,避免实例化后生成的位置出现偏差
2)、应用纹理:MeshRenderer—Materials选择PlaneGrid
3)、为其添加DetectedPlaneVisualizer组件,完成预制体制作。
5、添加名为GameManager 的gameObject,为其添加 AppController 脚本。内容附在下方。其作用:
a、进行各种错误处理
b、管理应用生命周期:保持亮屏、息屏、变暗等
c、放置物体
脚本内容参考文章:参考文章
enjoy!
using UnityEngine;
using GoogleARCore;
public class AppController : MonoBehaviour {
public Camera FirstPersonCamera; //ARCore的FirstPersonCamera摄像机
public GameObject prefab; //点击生成的对象预制体
private const float mModelRotation = 180.0f;
void Start()
{
//检查设备
OnCheckDevice();
}
void Update()
{
//管理应用的生命周期
UpdateApplicationLifecycle();
Touch touch;
if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
{
return;
}
//TrackableHit:保存的是发生碰撞检测时的检测到相关信息
TrackableHit hit;
//TrackableHitFlags:用来过滤需要进行碰撞检测的对象类型,其值可以一个,也可以是几个
TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinPolygon | TrackableHitFlags.PlaneWithinBounds;
//ARCore在Frame中为我们准备了四种发射射线检测物体的方法,具体参考文章
if (Frame.Raycast(touch.position.x, touch.position.y, raycastFilter, out hit))
{
if ((hit.Trackable is DetectedPlane) && Vector3.Dot(FirstPersonCamera.transform.position - hit.Pose.position, hit.Pose.rotation * Vector3.up) < 0)
{
Debug.Log("射线击中了DetectedPlane的背面!");
}
else
{
var prefabIns = Instantiate(prefab, hit.Pose.position, hit.Pose.rotation);
prefabIns.transform.Rotate(0, mModelRotation, 0, Space.Self);
var anchor = hit.Trackable.CreateAnchor(hit.Pose);
prefabIns.transform.parent = anchor.transform;
}
}
}
///
/// 检查设备
///
private void OnCheckDevice()
{
if (Session.Status == SessionStatus.ErrorSessionConfigurationNotSupported)
{
ShowAndroidToastMessage("ARCore在本机上不受支持或配置错误!");
Invoke("DoQuit", 0.5f);
}
else if (Session.Status == SessionStatus.ErrorPermissionNotGranted)
{
ShowAndroidToastMessage("AR应用的运行需要使用摄像头,现无法获取到摄像头授权信息,请允许使用摄像头!");
Invoke("DoQuit", 0.5f);
}
else if (Session.Status.IsError())
{
ShowAndroidToastMessage("ARCore运行时出现错误,请重新启动本程序!");
Invoke("DoQuit", 0.5f);
}
}
///
/// 管理应用的生命周期
///
private void UpdateApplicationLifecycle()
{
if (Session.Status != SessionStatus.Tracking)
{
const int lostTrackingSleepTimeout = 15;
//Screen.sleepTimeout:一种节能设置,允许屏幕在上次激活用户交互后一段时间变暗
Screen.sleepTimeout = lostTrackingSleepTimeout;
}
else
{
//SleepTimeout.NeverSleep:防止屏幕变暗
Screen.sleepTimeout = SleepTimeout.NeverSleep;
}
}
///
/// 弹出信息提示
///
/// 要弹出的信息
private void ShowAndroidToastMessage(string message)
{
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject unityActivity = unityPlayer.GetStatic("currentActivity");
if (unityActivity != null)
{
AndroidJavaClass toastClass = new AndroidJavaClass("android.widget.Toast");
unityActivity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
AndroidJavaObject toastObject = toastClass.CallStatic("makeText", unityActivity, message, 0);
toastObject.Call("show");
}));
}
}
}