AR Foundation - Control Image Tracked Prefab - c#

I am using AR Foundation and I want to control spawned prefab's timeline.
I am trying to create a simple AR app. Imagine I am tracking an image where I am spawning Tracked Image Prefab. Let's say this prefab is a model of a dragon with some fire effect on its timeline. And I want to control the prefabs timeline when it is instantiated by AR Foundation. For example, I want to play fire animation with a button click.
Can I put a listener on the prefab to trigger the timeline in Runtime? How can I do it, please? Is my assumption that I need somehow communicate with the instantiated prefab right?
This is the object and I want to trigger its timeline to play after a button is clicked.
This is the simple code with I wanted to control instantiated prefab's timeline.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
public class TimelineController : MonoBehaviour
{
public PlayableDirector playebleDirector;
public void Play()
{
playebleDirector.Play();
}
}

If I get yoru question correctly, the first you need is something that "prevales" on the scene, if the dragon is created or no, like a Controller.
Your controller can, for example, be the responsible to spawn the dragon. When your dragon is spawned, store that reference (GameObject dragon = Instantiate(dragonPrefab);). It also can have your button reference.
With that you can add your dragons behaviour to the button like:
button.onClick.AddListener(() => { dragon.dragonSpitFire(); }); //with lambda function
button.onClick.AddListener(dragon.dragonSpitFire); //without lambda function
And inside your method "dragonSpitFire" you can put your timeline or animation Start method, like your timeline.Play();

I have solved this problem with Events and Delegates. All initiated objects are subscribed to the event and trigger the function responsible for playing the timeline.

Related

How can I make a method that runs before any scene is loaded?

I'm currently making a game in Unity and I ran into a problem. Essentially what I'm currently trying to do is load a huge list of objects that I require for future scenes in my Recource folder and load them before any scene including the startup scene has been loaded so that I can essentially randomly choose to load scenes instead of being dependent on the first scene in order to load gameobjects that I will need in later scenes. I found a method online that was supposed to be able to do this. I created a gameobject called main put it into my resources folder and attached the Script bellow to it. Then I attached all the gameobjects that I would need to load before any of my scenes to this gameobject ("Main"):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Main : MonoBehaviour
{
//[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
void Start()
{
GameObject main = Instantiate(Resources.Load("Main")) as GameObject;
var mainObj = Instantiate(main);
mainObj.SetActive(false);
GameObject.DontDestroyOnLoad(main);
MySceneManager.LoadScene(1, this);
}
}
When I then run my game for somereason I get a NullReferenceexception stating: (The Object you want to instantiate is null). Does anyone know how I can solve this problem or even if their is an easier solution to the problem I'm trying to solve?
Thanks in advance
You can create an empty "loading scene". The scene will be purely to instantiate the objects you need and will terminate after it is done. Like a main menue in games.
You can put the scripts in the scene select scene.

Vuforia + Unity : Instantiate model in AR when UI Button pressed

I know this is a really simple question but I can't figure out how to archive this:
I have a UI button in my scene and I want Vuforia to instantiate one AR Model ONLY when I press a button.
Following the tutorial on the net I was able to instantiate a model on the screen when I touch it but I need to know how to set up Vuforia for archive the same result only when I press a button.
I have to disable the "Anchor Input Listener Behaviour"?
And then?
I want to call for the PositionContentAtPlaneAnchor but I can't figure out how to call it in the right way in the OnClick field of the button. I need to make a custom script for this?
Thanks for any answer.
Ok, sorry for the delay.
I deduce that you are working with the ground plane, if you have the Ground Plane Stage and the Plane Finder in the scene and works, we're at a good point.
Now, you must only add a button to the scene and into the script add something like this:
public PlaneFinderBehaviour plane;
void Start()
{
...
buttonOnTheScene.onClick.AddListener(TaskOnClick);
...
}
void TaskOnClick()
{
Vector2 aPosition = new Vector2(0,0);
...
plane.PerformHitTest(aPosition);
}
What does it mean?
First of all, you must move the Plane Finder from Hierarchy to the script variable, so we have a reference to the plane into the script.
Then when you click (or tap) on the button you simulate the click (or tap) on the display with the PerformHitTest.
If you're wondering why my question in the comment, it's because the Plane Finder Behaviour Script has two modes type: Interactive and Automatic. The Interactive intercept the tap on the display and shows the object (on the ground plane) in the exact position of the tap, the automatic shows the object in the center of the plane.
So if you want the object in an exact position you can pass a Vector2 position in the PerformHitTest and if you want to show an object programmatically or do something when it shows the object you can call a custom method OnInteractiveHitTest.
That's all.

Create objects with ground plane detection only once with Vuforia & Unity

I am trying to create an AR app using Unity & Vuforia. I have a 3D model that needs to be spawned when ground plane is detected.But this needs to happen only once.
The way Vuforia work is, it keeps on spawning objects when new plane is detected. So what i need to do is either detect plane only once or spawn the object only once. As i am new to Unity, i need help doing this. Great if someone could tell me what i need to do to achieve this.
Vuforia has updated.Now There is no DeploymentStageOnce script.Inorder to stop duplicating while we touch, we have to turn off Duplicate Stage in Content Positioning Behaviour (Script)Check the Inspector when we click Plane Finder.
In your app you should have a Plane Finder object somewhere with the following properties set by default
The Plane Finder object has a Behaviour component attached that calls a Position Content method if a plane was found. That method belongs to the Content Positioning Behaviour and it makes an instance (Clone) of your Ground Plane Stage. In order to avoid more than one instance you should import the vuforia Deploy Stage Once script located here: https://library.vuforia.com/articles/Solution/ground-plane-guide.html and you should change the Plane Finder Behaviour as the following:
I struggled a long with it, in short we must disable AnchorInputListenerBehaviour after hit.
I attached a new script on PlaneFinder with this code below:
<!-- language-all: c# -->
public void OnInteractiveHitTest(HitTestResult result)
{
var listenerBehaviour = GetComponent<AnchorInputListenerBehaviour>();
if (listenerBehaviour != null)
{
listenerBehaviour.enabled = false;
}
}
I added event on Plane Finder Behavior
That's all, I hope it will be useful.
For Updated Versions:
go to "Advanced" setting and "On Interactive Hit Test" script -> Select "Off" option for the script.
Most of the answers are correct but kind of obsolete, the correct way to do that is by code.
Create for example a gameObject called GameManager and pass the GroundPlaneStage and a prefab of the object you want to spawn to a script attached to that GameManager for example call it GameManagerScript.cs, and create a small function called spawnObjects which does the following:
public class SceneManagerScript : MonoBehaviour {
public GameObject objPrefab;
public GameObject ground;
private int count = 0;
public void spawnObject() {
Instantiate(objPrefab, new Vector3(count, 0, 0), Quaternion.identity, ground.transform);
count += 2;
}
}
then after that go to the PlaneFinder specifically to the PlaneFinderBehaviour.cs component you will have callbacks for OnInteractiveHitTest and OnAutomaticHitTest, in your case you need the OnAutomativeHitTest, click + and add a new callback (the function spawnObject in code above like in the image below)
also when you instantiate the object of your preference via the prefab don't forget to write the proper position updates to prevent the objects from getting added in the same position
also don't forget to make the GroundPlaneStage the parent of the object and realize that the position you are adding in the Instantiate() function is relative to that parent (GroundPlaneStage which is represented in the code above with the variable ground)
Finally don't forget to uncheck Duplicate Stage from the "Content Positioning Behaviour" component in the Plane Finder as shown in the picture below:
I hope that helps
please try the vuforia website for this problem
Introduction to Ground Plane in Unity

How to play audio in Unity (Click Event Trigger Cardboard SDK)?

I'm using the Cardboard sdk and have configured Gaze Input Module in Event System. Have also added a collider to my object.
I want to look at the object and play audio when I pull the trigger on my Cardboard HMD. However, it's currently not playing.
Can you advise if the problem is with my code:
using UnityEngine;
using UnityEngine.EventSystems;
using System.Collections;
[RequireComponent(typeof(AudioSource))]
public class Kim : MonoBehaviour {
public GameObject kkhair;
public AudioSource audio;
void Start() {
audio = GetComponent<AudioSource>();
}
public void speakKim() {
audio.Play();
}
}
This audio does 'play on wake' when that setting is enabled. So I know the file is ok. Just can't make it work for trigger only.
If you have the Cardboard SDK, you should also have the Demo Scene made by Google. There you click a cube that teleports, using the Gaze Input Module. You can use the same mechanism to trigger your audio. The Cube gameObject in that scene has an Event Trigger component that handles the click (and highlighting) for you, and calls a method on another component of the gameObject (in this example the TeleportRandomly() function of the Teleport script attached to the Cube).
In your case, you could change the Pointer Click event handling to speakKim on your script, to make start the audio playing.
You need to attach an "Event Trigger" component to your GameObject.
Select your GameObject in the Hierarchy, click "Add Component", search for "Event Trigger"
Create a new event type of "Pointer Click"
Drag in your Kim script, and choose the method speakKim
Your game object should look something like this:
You must also have an EventSystem in your Hierarchy. If you don't, add one by going to "Create > UI > Event System"

Instantiate gameobject from a script that is on that gameobject

I have a script called DialogueController, which is attached to a canvas. I would like to instantiate that canvas from the DialogueController script. Whenever I attempt to do this, all of the public objects that were assigned to the canvas through the Unity editor are set to null (including the canvas itself, which is what I am trying to instantiate).
Is there a simple way to do this? I have an alternative solution, but being able to do this would keep my code slightly more compartmentalized.
You could initialize these variables from the script itself, using the resources folders (and the Resources.Load() method). Something like that:
//The canvas is at the path "Assets/Resources/canvas".
function Start () {
your_canvas = Instantiate(Resources.Load("canvas"));
}
From the comments, it seems like you need an initial "seed" instance of that Canvas which contains your script to instantiate more copies if you need. Part 2 is most common for your needs
The easiest way is to have one instance of said canvas already in the scene. You could have the drawable/visible canvas part "disabled" by unticking the little checkbox in the inspector, and then have it enable itself in a function of a script on the GameObject...
void Start ()
{
thisCanvas = GetComponent<Canvas>();
thisCanvas.enabled = true;
}
of course, another way would just be to instantiate one copy from another script which you already have in the scene - classic case:
Create a BLANK GameObject in your scene (CTRL+Shift+N), [F2] rename it "GameManager" (SOME unity functions still bug out when there are spaces in GameObject names BTW) and then attach a new script called GameManager.
This script is basically just here to make sure the right scenes load, and instantiate certain prefabs, make network connections, set player variables that you haven't done from the editor etc etc
so:
using UnityEngine;
using System.Collections;
public class GameManager : MonoBehaviour
{
public GameObject myObject;
void Start ()
{
Instantiate(myObject, transform.position, transform.rotation);
}
}
now drag+drop your "prefab" which you want to instantiate into the slot on your "GameManager" in the inspector.
Note that it doesn't have to be when the game starts, another example is the GameManager script having a function listening for whenever a login is needed, and at that time - it instantiates your login dialog.

Categories

Resources