Sorry if this is too simple, but i've not been able to find an answer on this. Usually either the question is too complicated to answer or too simple to not know.
THIS IS PARTIALLY A UNITY VR/VRTK ISSUE (maybe...)
Anyways, my goal is to set up triggers for my Canvas to be able to start a video player and have it enable and appear in the scene when an object is being picked up. As of now, everything is in place except for my ability to trigger both those actions when the player interacts with the game object.
Within my script, I have:
public VideoPlayer videoPlayer;
public Canvas canvas;
public GameObject asset;
void Awake ()
{
videoPlayer.GetComponent<VideoPlayer>();
canvas.GetComponent<Canvas>();
}
private void Start()
{
videoPlayer.Pause();
canvas.enabled = !canvas.enabled;
}
Simple, but everything gets linked within unity and its alot of fun. My problem is that im trying to reference a script that the GameObject has on it so that I can use its triggers in order to enable the video player to do its thing. Theres a simple bool within the Interactible script attached to it that I think might work or maybe i can write my own, problem is i have no idea how to reference from the GameObject components. Maybe im just not understaning it but ive looked for a while and now I turn to you, the collective for help...
help :(
-Thanks to all in advance, there's more pieces to the project but i thought these would be the most relevant. Let me know if i missed something needed.
I don't really understand what is your final goal yet but those two lines
videoPlayer = videoPlayer.GetComponent<VideoPlayer>();
canvas = canvas.GetComponent<Canvas>();
don't make much sense. You either have the references already (e.g. from the inspector) than you don't need to get the components again or you want to get them from a GameObject
In case you want the components attached to the same GameObect as the provided script instead use
videoPlayer = GetComponent<VideoPlayer>();
canvas = GetComponent<Canvas>();
Or in case you rather want to get the components from the asset
GameObject use
videoPlayer = asset.GetComponent<VideoPlayer>();
canvas = asset.GetComponent<Canvas>();
Than you can add a public method to call it whenever "interacting" (however that looks like) with the GameObject
public void ReactToInteraction()
{
// E.g.
canvas.enabled = true;
videoPlayer.Play();
}
From your comment
My main problem revolves around trying to access a script thats attached to a different game object. In the script im writing, I have it attached to a canvas but I want it to be triggered by a componemt that is inside of a different game object that isn't associated with this canvas.
I understand you somewhere have a "triggering event" lets say on a GameObject ObjectA
in a class TriggeringBehaviour
e.g.
void OnTriggerEnter(Collider col)
{
//...
}
and you want a method ReactToInteraction
be called on your canvas whenever the trigger is called.
There are many ways to do so but I personally would prefere one of following:
If you "know" your references, either referencing in the inspector or have some form of finding them using e.g. Singleton or FindObjectOfType
, Find
(by name) etc you could just directly call the method from TriggeringBehaviour
:
// todo get this somehow with the known methods
public CanvasBehaviour ReferenceToYourCanvasScript;
void OnTriggerEnter(Collider col)
{
//...
ReferenceToYourCanvasScript.ReactToInteraction;
}
You can implement custom events in the TriggeringBehaviour
by using e.g.
public event Action OnTriggered;
void OnTriggerEnter(Collider col)
{
//...
if(OnTriggered!=null)
{
OnTriggered.Invoke();
}
}
Than you would have to register listeners to those events in your CanvasBahviour
private void Start()
{
//TODO somehow get the according reference e.g.
var triggerBahviour = FindObjectOfType<TriggeringBahviour>();
// and add the listener
// it is save to remove the listener first -> makes sure it is only registered once
triggerBahviour.OnTriggered -= ReactToInteraction;
triggerBahviour.OnTriggered += ReactToInteraction;
// after that whenever OnTriggered is invoked, ReactToInteraction will be executed
}
Alternatively you can also make a static class for handling those events
public static class TriggerEvents
{
// I leave this as example on how to give it parameters
public static event Action<TriggerBehaviour> OnTriggeredBy;
public static event Action OnTriggered;
public static void InvokeOnTriggered()
{
if(OnTriggered!=null) OnTriggered.Invoke();
}
public static void InvokeOnTriggeredBy(TriggeringBehavior by)
{
if(OnTriggeredBy!=null) OnTriggeredBy.Invoke(by);
}
}
With this way it is a bit easier to register and invoke the events:
in TriggerBehaviour
void OnTriggerEnter(Collider col)
{
//...
TriggerEvents.InvokeOnTriggered();
// or if you want to also check who triggered
// TriggerEvents.InvokeOnTriggeredBy(this);
}
and in CanvasBehaviour
void Start()
{
TriggerEvents.OnTriggered -= ReactToInteraction;
TriggerEvents.OnTriggered += ReactToInteraction;
// or if you want to checl who triggered
// TriggerEvents.OnTriggeredBy -= ReactToInteractionBy;
// TriggerEvents.OnTriggeredBy += ReactToInteractionBy;
}
// In case you need the ReactToInteractionBy
// has to have the same signature as defined by the Action
void ReactToInteractionBy(TriggeringBehaviour triggerer)
{
// ...
}
This is very flexible and can also pass as many parameters you want/need (In this case none anyway). However you still have to somehow get the according reference to the correct component.
One big flaw is that registering and especially destroying something without unregistering can lead to errors and be quite frustrating.
Alternatively you can also implement a UnityEvent
in TriggeringBehaviour
public event Action OnTriggered;
void OnTriggerEnter(Collider col)
{
// ...
OnTriggered.Invoke();
}
The big advantage is that this UnityEvent
will be shown and configurable in the Inspector! (You'll recognize it from the UI Button onClick event)
So you can just reference any other component from the inspector and don't have to register listeners at runtime (You still can do so via triggerBahviour.OnTriggered.AddListener()
).
However UnityEvent
is kind of limitted. E.g. it is not that simple to have different Methods called with different signatures that have multiple or non-standart parameters (such as custom class references).