Vuforia 有 DefaultTrackableEventHandler .. 代码很难找到 (source) 但看起来像这样
/*==============================================================================
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,这样它们就不会掉下来了。然后在找到 imagetarget 后作为回调启用它。
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;
}
}
把它放在你的每一个失败的对象上,如果可能的话,可能在检查器中设置引用(效率更高一点)。