Augmented Reality using Unity3D - c#

I am working on an AR Android application. I finished building the application but whenever I open it, the video plays in the background before even scanning the target image but the video gets displayed only when I scan the image. Any help or suggestions about that? The code for DefaultTrackableEventHandler.cs is:
using UnityEngine;
using Vuforia;
public class DefaultTrackableEventHandler : MonoBehaviour, ITrackableEventHandler
{
protected TrackableBehaviour mTrackableBehaviour;
protected TrackableBehaviour.Status m_PreviousStatus;
protected TrackableBehaviour.Status m_NewStatus;
protected virtual void Start()
{
mTrackableBehaviour = GetComponent<TrackableBehaviour>();
if (mTrackableBehaviour)
mTrackableBehaviour.RegisterTrackableEventHandler(this);
}
protected virtual void OnDestroy()
{
if (mTrackableBehaviour)
mTrackableBehaviour.UnregisterTrackableEventHandler(this);
}
public void OnTrackableStateChanged(
TrackableBehaviour.Status previousStatus,
TrackableBehaviour.Status newStatus)
{
m_PreviousStatus = previousStatus;
m_NewStatus = 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.NO_POSE)
{
Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " lost");
OnTrackingLost();
}
else
{
OnTrackingLost();
}
}
protected virtual void OnTrackingFound()
{
var rendererComponents = GetComponentsInChildren<Renderer>(true);
var colliderComponents = GetComponentsInChildren<Collider>(true);
var canvasComponents = GetComponentsInChildren<Canvas>(true);
foreach (var component in rendererComponents)
component.enabled = true;
foreach (var component in colliderComponents)
component.enabled = true;
foreach (var component in canvasComponents)
component.enabled = true;
}
protected virtual void OnTrackingLost()
{
var rendererComponents = GetComponentsInChildren<Renderer>(true);
var colliderComponents = GetComponentsInChildren<Collider>(true);
var canvasComponents = GetComponentsInChildren<Canvas>(true);
foreach (var component in rendererComponents)
component.enabled = false;
foreach (var component in colliderComponents)
component.enabled = false;
foreach (var component in canvasComponents)
component.enabled = false;
}
}

If you use the Unity Videoplayer check if you disabled the Loop option in Video Player Inspector view.
Second, the game object that include the VideoPlayer component is located as child of ImageTarget gameobject?
Third, in the OnTrackingFound() you must manage the Play and in OnTrackingLost() the Stop about VideoPlayer.

Related

Unity - Accessing Events Throwing Null Exception

I have a script accessing an instantiated game object of Vuforia from Hierarchy and adding a component to it:
IEnumerable<TrackableBehaviour> tbs = TrackerManager.Instance.GetStateManager().GetTrackableBehaviours();
foreach (TrackableBehaviour tb in tbs)
{
if (tb.TrackableName == "Fashion")
{
if (tb.name == "New Game Object")
{
// change generic name to include trackable name
tb.gameObject.name = ++counter + "DynamicImageTarget-" + tb.TrackableName;
// add additional script components for trackable
tb.gameObject.AddComponent<DefaultTrackableEventHandler>();
tb.gameObject.AddComponent<TurnOffBehaviour>();
Up to here it is working but at this point/line when i try to add
tb.gameObject.GetComponent<DefaultTrackableEventHandler>().OnTargetFound.AddListener(DressFound);
is throwing null exception in runtime
When I try
tb.gameObject.GetComponent<DefaultTrackableEventHandler>().OnTargetFound.RemoveAllListeners();
throwing null exception in runtime as well
However when i try
tb.gameObject.GetComponent<DefaultTrackableEventHandler>().enable = false;
it is working and disabling script component
void DressFound()
{
augmentation.SetActive(true);
}
Why i can't reach events on the script?
/*==============================================================================
Copyright (c) 2019 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.
==============================================================================*/
using UnityEngine;
using UnityEngine.Events;
using Vuforia;
/// <summary>
/// A custom handler that implements the ITrackableEventHandler interface.
///
/// Changes made to this file could be overwritten when upgrading the Vuforia version.
/// When implementing custom event handler behavior, consider inheriting from this class instead.
/// </summary>
public class DefaultTrackableEventHandler : MonoBehaviour
{
public enum TrackingStatusFilter
{
Tracked,
Tracked_ExtendedTracked,
Tracked_ExtendedTracked_Limited
}
/// <summary>
/// A filter that can be set to either:
/// - Only consider a target if it's in view (TRACKED)
/// - Also consider the target if's outside of the view, but the environment is tracked (EXTENDED_TRACKED)
/// - Even consider the target if tracking is in LIMITED mode, e.g. the environment is just 3dof tracked.
/// </summary>
public TrackingStatusFilter StatusFilter = TrackingStatusFilter.Tracked_ExtendedTracked_Limited;
public UnityEvent OnTargetFound;
public UnityEvent OnTargetLost;
protected TrackableBehaviour mTrackableBehaviour;
protected TrackableBehaviour.Status m_PreviousStatus;
protected TrackableBehaviour.Status m_NewStatus;
protected bool m_CallbackReceivedOnce = false;
protected virtual void Start()
{
mTrackableBehaviour = GetComponent<TrackableBehaviour>();
if (mTrackableBehaviour)
{
mTrackableBehaviour.RegisterOnTrackableStatusChanged(OnTrackableStatusChanged);
}
}
protected virtual void OnDestroy()
{
if (mTrackableBehaviour)
{
mTrackableBehaviour.UnregisterOnTrackableStatusChanged(OnTrackableStatusChanged);
}
}
void OnTrackableStatusChanged(TrackableBehaviour.StatusChangeResult statusChangeResult)
{
m_PreviousStatus = statusChangeResult.PreviousStatus;
m_NewStatus = statusChangeResult.NewStatus;
Debug.LogFormat("Trackable {0} {1} -- {2}",
mTrackableBehaviour.TrackableName,
mTrackableBehaviour.CurrentStatus,
mTrackableBehaviour.CurrentStatusInfo);
HandleTrackableStatusChanged();
}
protected virtual void HandleTrackableStatusChanged()
{
if (!ShouldBeRendered(m_PreviousStatus) &&
ShouldBeRendered(m_NewStatus))
{
OnTrackingFound();
}
else if (ShouldBeRendered(m_PreviousStatus) &&
!ShouldBeRendered(m_NewStatus))
{
OnTrackingLost();
}
else
{
if (!m_CallbackReceivedOnce && !ShouldBeRendered(m_NewStatus))
{
// This is the first time we are receiving this callback, and the target is not visible yet.
// --> Hide the augmentation.
OnTrackingLost();
}
}
m_CallbackReceivedOnce = true;
}
protected bool ShouldBeRendered(TrackableBehaviour.Status status)
{
if (status == TrackableBehaviour.Status.DETECTED ||
status == TrackableBehaviour.Status.TRACKED)
{
// always render the augmentation when status is DETECTED or TRACKED, regardless of filter
return true;
}
if (StatusFilter == TrackingStatusFilter.Tracked_ExtendedTracked)
{
if (status == TrackableBehaviour.Status.EXTENDED_TRACKED)
{
// also return true if the target is extended tracked
return true;
}
}
if (StatusFilter == TrackingStatusFilter.Tracked_ExtendedTracked_Limited)
{
if (status == TrackableBehaviour.Status.EXTENDED_TRACKED ||
status == TrackableBehaviour.Status.LIMITED)
{
// in this mode, render the augmentation even if the target's tracking status is LIMITED.
// this is mainly recommended for Anchors.
return true;
}
}
return false;
}
protected virtual void OnTrackingFound()
{
if (mTrackableBehaviour)
{
var rendererComponents = mTrackableBehaviour.GetComponentsInChildren<Renderer>(true);
var colliderComponents = mTrackableBehaviour.GetComponentsInChildren<Collider>(true);
var canvasComponents = mTrackableBehaviour.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;
}
if (OnTargetFound != null)
OnTargetFound.Invoke();
}
protected virtual void OnTrackingLost()
{
if (mTrackableBehaviour)
{
var rendererComponents = mTrackableBehaviour.GetComponentsInChildren<Renderer>(true);
var colliderComponents = mTrackableBehaviour.GetComponentsInChildren<Collider>(true);
var canvasComponents = mTrackableBehaviour.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;
}
if (OnTargetLost != null)
OnTargetLost.Invoke();
}
}
The issue seems to be that both UnityEvents are not assigned in the case the component is attached on runtime via AddComponent.
Usually these are assigned to automatically by the Unity Inspector since they are serialized.
To be sure you could simply initialize them always using
public UnityEvent OnTargetFound = new UnityEvent();
public UnityEvent OnTargetLost = new UnityEvent();

Unsure why logic will not turn game object active

My logic has worked in the past, but it is unclear why this does not work to turn my gameobjects active. This is especially puzzling as I have no errors. The fields match up correctly and I have no errors as mentioned. This is used for an inventory system.
public class addToArtMode : MonoBehaviour
{
public bool On = true;
public GameObject slotPanel;
void Start()
{
this.GetComponent<Button>().onClick.AddListener(() => AddToArtMode());
slotPanel = GameObject.Find("Slot Panel");
}
public void AddToArtMode()
{
if (On)
{
Debug.Log("ID'ing ");
slotPanel = GameObject.Find("Slot Panel");
foreach (Transform child in slotPanel.transform)
{
var parentName = this.GetComponentInParent<ArtBrowseContentInformation>().NameofArt;
var childname = child.GetComponent<InventoryContentInfo>().NameofArt;
if (childname == parentName)
{
child.gameObject.SetActive(true);
On = false;
Debug.Log("what ");
}
else
{
Off();
}
}
void Off()
{
foreach (Transform child in slotPanel.transform)
{
var parentName = this.GetComponentInParent<ArtBrowseContentInformation>().NameofArt;
var childname = child.GetComponent<InventoryContentInfo>().NameofArt;
if (childname == parentName)
{
Debug.Log("the heck");
child.gameObject.SetActive(false);
On = true;
}
}
}
}
}
}
}
try gameObject.enabled = false/true;

How to add a space between the Tabbar line and the icons in iOS using Xamarin Forms Shell?

I have used ShellRenderer but I am unable to get the code working to add an extra space between the Tabbar line and the icons. Here is an image:
I need to increase the space between the gray line and Top of all icons.
Here is the code that I have tried.
[assembly: ExportRenderer(typeof(Shell), typeof(CustomShellRenderer))]
namespace MyProject.iOS.CustomRenderers
{
public class CustomShellRenderer : ShellRenderer
{
protected override IShellSectionRenderer CreateShellSectionRenderer(ShellSection shellSection)
{
var renderer = base.CreateShellSectionRenderer(shellSection);
if (renderer != null)
{
var a = (renderer as ShellSectionRenderer);
(renderer as ShellSectionRenderer).NavigationBar.Translucent = false;
}
return renderer;
}
protected override IShellItemRenderer CreateShellItemRenderer(ShellItem item)
{
var renderer = base.CreateShellItemRenderer(item);
(renderer as ShellItemRenderer).TabBar.Translucent = false;
(renderer as ShellItemRenderer).TabBar.ShadowImage = new UIImage();
(renderer as ShellItemRenderer).TabBar.BackgroundImage = new UIImage();
CGRect frame = (renderer as ShellItemRenderer).TabBar.Frame;
UIView view = new UIView();
view.BackgroundColor = UIColor.Yellow;
view.Frame = new CGRect(frame.X, frame.Y, frame.Width, 10);
(renderer as ShellItemRenderer).TabBar.AddSubview(view);
return renderer;
}
}
You can add a little ImageInsets of barItem to make a space between the gray line and Top of all icons. You can't add a extra view because the space is fixed.
public class MyShellRenderer : ShellRenderer
{
protected override IShellSectionRenderer CreateShellSectionRenderer(ShellSection shellSection)
{
var renderer = base.CreateShellSectionRenderer(shellSection);
if (renderer != null)
{
(renderer as ShellSectionRenderer).NavigationBar.SetBackgroundImage(UIImage.FromFile("monkey.png"), UIBarMetrics.Default);
}
return renderer;
}
protected override IShellTabBarAppearanceTracker CreateTabBarAppearanceTracker()
{
return new CustomTabbarAppearance();
}
}
public class CustomTabbarAppearance : IShellTabBarAppearanceTracker
{
public void Dispose()
{
}
public void ResetAppearance(UITabBarController controller)
{
}
public void UpdateLayout(UITabBarController controller)
{
UITabBar myTabBar = controller.TabBar;
foreach (var barItem in myTabBar.Items)
{
barItem.ImageInsets = new UIEdgeInsets(8, 0, 0, 0);
//barItem.TitlePositionAdjustment = new UIOffset(10, 0);
}
}
}
You can check my sample here.

Anchoring in Vuforia

I'm able to fix the position of the object once it's spawned. But, the object is placed onto different position on every tap on the screen. I want to avoid this problem and want my object to be fixed in a spawned position throughout the Session or Application lifetime.
This is my Deploy Stage Once script:
public class DeployStageOnce : MonoBehaviour
{
public GameObject AnchorStage;
private PositionalDeviceTracker _deviceTracker;
private GameObject _anchorGameObject;
private GameObject _previousAnchor;
public void Start()
{
if (AnchorStage == null)
{
Debug.Log("AnchorStage must be specified");
return;
}
AnchorStage.SetActive(false);
}
public void Awake()
{
VuforiaARController.Instance.RegisterVuforiaStartedCallback(OnVuforiaStarted);
}
public void OnDestroy()
{
VuforiaARController.Instance.UnregisterVuforiaStartedCallback(OnVuforiaStarted);
}
private void OnVuforiaStarted()
{
_deviceTracker = TrackerManager.Instance.GetTracker<PositionalDeviceTracker>();
}
private void AnchorGameObjectSetHitTestPosition(HitTestResult reuslt)
{
_anchorGameObject.transform.position = reuslt.Position;
_anchorGameObject.transform.rotation = reuslt.Rotation;
}
public void OnInteractiveHitTest(HitTestResult result)
{
if (result == null || AnchorStage == null)
{
Debug.LogWarning("Hit test is invalid or AnchorStage not set");
return;
}
var anchor = _deviceTracker.CreatePlaneAnchor(Guid.NewGuid().ToString(), result);
_anchorGameObject = new GameObject();
AnchorGameObjectSetHitTestPosition(result);
if (anchor != null)
{
AnchorStage.transform.parent = _anchorGameObject.transform;
AnchorStage.transform.localPosition = Vector3.zero;
AnchorStage.transform.localRotation = Quaternion.identity;
AnchorStage.SetActive(true);
}
if (_previousAnchor != null)
{
Destroy(_previousAnchor);
}
_previousAnchor = _anchorGameObject;
}
}
Well you can create an isPlaced variable in your script to check if your object is already placed like this:
private bool isPlaced = false;
public void OnInteractiveHitTest(HitTestResult result)
{
if (result == null || AnchorStage == null)
{
Debug.LogWarning("Hit test is invalid or AnchorStage not set");
return;
}
if(!isPlaced)
{
var anchor = _deviceTracker.CreatePlaneAnchor(Guid.NewGuid().ToString(), result);
_anchorGameObject = new GameObject();
AnchorGameObjectSetHitTestPosition(result);
if (anchor != null)
{
AnchorStage.transform.parent = _anchorGameObject.transform;
AnchorStage.transform.localPosition = Vector3.zero;
AnchorStage.transform.localRotation = Quaternion.identity;
AnchorStage.SetActive(true);
}
isPlaced = true;
}
}

map pins is never drew in my android (xamarin forms)

This is my mapRenderer and I need to draw pins in Android, but, for some reasson, my if (e.PropertyName.Equals("VisibleRegion") && !isDrawn) is never true...then, my map pins are never drew
Does someone know what does this be true? What is the problem?
I am using xamarin forms and this is in my android project...all the rest about the map is working well
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace neoFly_Montana.Droid
{
public class CustomMapRenderer : MapRenderer, IOnMapReadyCallback
{
GoogleMap map;
List<Position> routeCoordinates;
List<CustomPin> customPins;
Position userLocation;
bool isDrawn;
protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
//\ NativeMap.InfoWindowClick -= OnInfoWindowClick;
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
//pin
customPins = formsMap.CustomPins;
routeCoordinates = formsMap.RouteCoordinates;
userLocation = formsMap.userLocation;
((MapView)Control).GetMapAsync(this);
}
}
public void OnMapReady(GoogleMap googleMap)
{
map = googleMap;
var polylineOptions = new PolylineOptions();
polylineOptions.InvokeColor(0x66FF0000);
foreach (var position in routeCoordinates)
{
polylineOptions.Add(new LatLng(position.Latitude, position.Longitude));
}
map.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(new LatLng(userLocation.Latitude, userLocation.Longitude), 15.0f));
map.AddPolyline(polylineOptions);
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName.Equals("VisibleRegion") && !isDrawn)
{
NativeMap.Clear();
//NativeMap.InfoWindowClick += OnInfoWindowClick;
//NativeMap.SetInfoWindowAdapter(this);
foreach (var pin in customPins)
{
var marker = new MarkerOptions();
marker.SetPosition(new LatLng(pin.Pin.Position.Latitude, pin.Pin.Position.Longitude));
marker.SetTitle(pin.Pin.Label);
marker.SetSnippet(pin.Pin.Address);
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.menusmiley));
NativeMap.AddMarker(marker);
}
isDrawn = true;
}
}
}
}
the e.PropertyName that never is "VisibleRegion"
I show my pins in OnMapReady
public void OnMapReady(GoogleMap googleMap)
{
_googleMap = googleMap;
if (_googleMap != null)
{
_googleMap.MapClick += OnMapClick;
UpdatePins();
}
}
private void UpdatePins(bool firstUpdate = true)
{
if (_googleMap == null) return;
if (FormsMap.CustomPins != null)
{
foreach (var pin in FormsMap.CustomPins)
{
AddPin(pin);
}
if (firstUpdate)
{
var observable = FormsMap.CustomPins as INotifyCollectionChanged;
if (observable != null)
{
observable.CollectionChanged += OnCustomPinsCollectionChanged;
}
}
}
}
private void AddPin(CustomPin pin)
{
var markerWithIcon = new MarkerOptions();
markerWithIcon.SetPosition(new LatLng(pin.BasePin.Position.Latitude, pin.BasePin.Position.Longitude));
if (!string.IsNullOrWhiteSpace(pin.BasePin.Label))
markerWithIcon.SetTitle(pin.BasePin.Label);
_googleMap.AddMarker(markerWithIcon);
}

Categories

Resources