unity3d - 在没有扫描目标的情况下生成游戏对象
问题描述
我有多个游戏对象作为 ImageTarget 的孩子。
Ar 相机 世界中心模式= first_target 跟踪设备姿态检查和定位
当我启动游戏模式时。
所有对象开始下落(球体碰撞器和网格渲染器关闭)。
当我扫描目标时,物体已经穿过我在它们下面的平面(平面上有一个网格对撞机)。
如果我在启动游戏模式后立即扫描目标,一切都按计划进行,球体会与飞机相撞并停留在其顶部。
是否可以在扫描目标之前冻结对象的 Y 轴以及如何启用扩展跟踪(只要我将相机从目标移开并重新扫描目标,对象就会穿过平面)。
解决方案
Vuforia 有DefaultTrackableEventHandler
.. 代码很难找到(源代码),但它看起来像这样
/*==============================================================================
Copyright (c) 2017 PTC Inc. All Rights Reserved.
Copyright (c) 2010-2014 Qualcomm Connected Experiences, Inc.
All Rights Reserved.
Confidential and Proprietary - Protected under copyright and other laws.
==============================================================================*/
/*
* Modified by PauloSalvatore on 04/03/2018 - 15:38 (GMT-3)
*
* Change Log:
*
* Track Events added on Inspector
* Custom events can be added to be invoked during initialization,
* when appear start, when object is appearing and when disappear start.
*/
using UnityEngine;
using UnityEngine.Events;
using Vuforia;
[System.Serializable]
public class TrackEvents
{
#region PUBLIC_EVENTS
public UnityEvent onInitialized;
public UnityEvent onAppear;
public UnityEvent isAppearing;
public UnityEvent onDisappear;
#endregion PUBLIC_EVENTS
}
/// <summary>
/// A custom handler that implements the ITrackableEventHandler interface.
/// </summary>
public class DefaultTrackableEventHandler : MonoBehaviour, ITrackableEventHandler
{
#region PUBLIC_EVENTS
public TrackEvents trackEvents;
#endregion PUBLIC_EVENTS
#region PRIVATE_MEMBER_VARIABLES
protected TrackableBehaviour mTrackableBehaviour;
#endregion PRIVATE_MEMBER_VARIABLES
#region UNTIY_MONOBEHAVIOUR_METHODS
protected virtual void Start()
{
mTrackableBehaviour = GetComponent<TrackableBehaviour>();
if (mTrackableBehaviour)
mTrackableBehaviour.RegisterTrackableEventHandler(this);
// onInitialized custom events
if (trackEvents.onInitialized != null)
trackEvents.onInitialized.Invoke();
}
protected virtual void Update()
{
// isAppearing custom events
if (trackEvents.isAppearing != null)
trackEvents.isAppearing.Invoke();
}
#endregion UNTIY_MONOBEHAVIOUR_METHODS
#region PUBLIC_METHODS
/// <summary>
/// Implementation of the ITrackableEventHandler function called when the
/// tracking state changes.
/// </summary>
public void OnTrackableStateChanged(
TrackableBehaviour.Status previousStatus,
TrackableBehaviour.Status newStatus)
{
if (newStatus == TrackableBehaviour.Status.DETECTED ||
newStatus == TrackableBehaviour.Status.TRACKED ||
newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED)
{
Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " found");
OnTrackingFound();
}
else if (previousStatus == TrackableBehaviour.Status.TRACKED &&
newStatus == TrackableBehaviour.Status.NOT_FOUND)
{
Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " lost");
OnTrackingLost();
}
else
{
// For combo of previousStatus=UNKNOWN + newStatus=UNKNOWN|NOT_FOUND
// Vuforia is starting, but tracking has not been lost or found yet
// Call OnTrackingLost() to hide the augmentations
OnTrackingLost();
}
}
#endregion PUBLIC_METHODS
#region PRIVATE_METHODS
protected virtual void OnTrackingFound()
{
var rendererComponents = GetComponentsInChildren<Renderer>(true);
var colliderComponents = GetComponentsInChildren<Collider>(true);
var canvasComponents = GetComponentsInChildren<Canvas>(true);
// Enable rendering:
foreach (var component in rendererComponents)
component.enabled = true;
// Enable colliders:
foreach (var component in colliderComponents)
component.enabled = true;
// Enable canvas:
foreach (var component in canvasComponents)
component.enabled = true;
// onAppear custom events
if (trackEvents.onAppear != null)
trackEvents.onAppear.Invoke();
}
protected virtual void OnTrackingLost()
{
var rendererComponents = GetComponentsInChildren<Renderer>(true);
var colliderComponents = GetComponentsInChildren<Collider>(true);
var canvasComponents = GetComponentsInChildren<Canvas>(true);
// Disable rendering:
foreach (var component in rendererComponents)
component.enabled = false;
// Disable colliders:
foreach (var component in colliderComponents)
component.enabled = false;
// Disable canvas:
foreach (var component in canvasComponents)
component.enabled = false;
// onDisappear custom events
if (trackEvents.onDisappear != null)
trackEvents.onDisappear.Invoke();
}
#endregion PRIVATE_METHODS
}
这应该放置在相应的 ImageTarget 或您正在使用的任何目标上,默认为 afaik。如您所见,如果目标丢失,他们将禁用Renderer
,Collider
等等……我个人总是会删除它,而是将其替换为,UnityEvent
以便我以后可以决定应该发生什么,不应该发生什么。
由于这两种方法OnTrackingFound()
,OnTrackingLost()
您virtual
可以继承DefaultTrackableEventHandler
并覆盖/替换它们的功能。通过不调用base.OnTrackingFound()
或者base.OnTrackingLost()
我们告诉 c#不执行父类最初实现的任何内容,而只使用我们实现的内容:
// This is used to directly pass a string value into the event
// I'll explain why later ...
[Serializable]
public class VuforiaTargetFoundEvent : UnityEvent<string, Transform> { }
public MyTrackableEventHandler : DefaultTrackableEventHandler
{
// Give this specific VuforiaTarget a certain custom ID
// We will pass it dynamically into the UnityEvent
// so every listener automatically also knows WHICH target
// was lost or found
public string TargetID;
public VuforiaTargetEvent _OnTrackingFound;
public VuforiaTargetEvent _OnTrackingLost;
protected override void OnTrackingFound()
{
// call _OnTrackingFound with your specific target ID and
// also pass in the Transform so every listener can know
// WHICH target was found and WHERE it is positioned
_OnTrackingFound?
}
protected override void OnTrackingLost()
{
// call _OnTrackingLost with your specific target ID and
// also pass in the Transform so every listener can know
// WHICH target was lost and WHERE it was last positioned
_OnTrackingLost?
}
}
只需将它放在 Vuforia 目标上,而不是DefaultTrackableEventHandler
(如果它已经存在的话),所以现在默认情况下,不会禁用子级中的Renderer
,等。Collider
(如果您仍然需要它,您当然可以再次添加base.OnTrackingLost()
和base.OnTrackingFound()
或者在单独的脚本中实现它,并在我们刚刚添加的回调中引用相应的方法UnityEvents
;))
现在到你的坠落物体。一开始设置useGravity
为false
这样他们就不会再跌倒了。然后作为回调一旦找到图像目标启用它。
public GravityEnabler : MonoBehaviour
{
// either reference this in the Inspector ...
public RigidBody _rigidBody;
// also this either reference it in the Inspector ...
public MyTrackableEventHandler target;
// ... or get them on runtime
private void Awake()
{
if(!_rigidBody) _rigidBody = GetComponent<RigidBody>();
if(!target= target = FindObjectOfType<MyTrackableEventHandler>();
// before start disable gravity
_rigidBody.useGravity = false;
// setup the callback for the target
target._OnTrackingFound.AddListener(OnTargetScanned);
target._OnTrackingLost.AddListener(OnTargetLost);
}
privtae void OnDestroy()
{
// If this object gets destroyed be sure to remove the callbacks
// otherwise you would get exceptions because the callbacks
// would still exist but point to a NULL reference
target._OnTrackingFound.RemoveListener(OnTargetScanned);
target._OnTrackingLost.RemoveListener(OnTargetLost);
}
public void OnTargetFound(string targetID, Transform targetTransform)
{
_rigidBody.useGravity = true;
}
public void OnTargetLost(string targetID, Transform targetTransform)
{
// If you need to do anything here
// maybe you want to stop the falling again when the target is lost
_rigidBody.useGravity = false;
_rigidBody.velocity = Vector3.zero;
}
}
把它放在你的每一个失败的对象上,如果可能的话,可能已经在 Inspector 中设置了引用(效率更高一点)。
推荐阅读
- javascript - 您好我想仅通过过滤器功能过滤嵌套数组中的数据
- java - 如何在 Java 中实现多对多关系?
- node.js - React 编译错误“尝试导入错误:'./registerServiceWorker' 不包含默认导出(导入为'registerServiceWorker')。”
- java - 如何将 Apache Camel 路由到内存中的 ActiveMQ JMS 队列
- mysql - MySQL程序检查下一个空闲值
- html - 如何在编辑 HTML 文档时添加网站图标?(学校项目)
- php - CSS 和 javascript 在 Symfony 项目中不起作用
- python-3.x - 打印dict显示keyerror
- sql-server - 如果变量在 T-SQL 语句的 IN 子句中,如何实现参数化 SQL
- jenkins - 为什么将动态变量作为代码插件注入自定义管道时无法正确解析?