我真的不明白你的最终目标是什么,但这两行
videoPlayer = videoPlayer.GetComponent<VideoPlayer>();
canvas = canvas.GetComponent<Canvas>();
没有多大意义。您要么已经拥有引用(例如来自检查器)而不是您不需要再次获取组件,或者您想从 GameObject 获取它们
如果您希望将组件附加到与提供的脚本相同的GameObect,请使用
videoPlayer = GetComponent<VideoPlayer>();
canvas = GetComponent<Canvas>();
或者,如果您更想从asset
GameObject 中获取组件,请使用
videoPlayer = asset.GetComponent<VideoPlayer>();
canvas = asset.GetComponent<Canvas>();
比你可以添加一个公共方法来调用它每当与游戏对象“交互”(无论看起来如何)
public void ReactToInteraction()
{
// E.g.
canvas.enabled = true;
videoPlayer.Play();
}
从你的评论
我的主要问题围绕着尝试访问附加到不同游戏对象的脚本。在我正在编写的脚本中,我将它附加到画布上,但我希望它由位于与此画布无关的不同游戏对象内部的组件触发。
ObjectA
我知道你在某个地方有一个“触发事件”让我们在一个类中的 GameObject 上说,TriggeringBehaviour
例如
void OnTriggerEnter(Collider col)
{
//...
}
并且您希望ReactToInteraction
在调用触发器时在画布上调用一个方法。
有很多方法可以做到这一点,但我个人更喜欢以下方法之一:
解决方案一:直接调用
如果您“知道”您的引用,无论是在检查器中引用还是使用 Singleton 或FindObjectOfType
, Find
(按名称)等以某种形式找到它们,您都可以直接从以下位置调用该方法TriggeringBehaviour
:
// todo get this somehow with the known methods
public CanvasBehaviour ReferenceToYourCanvasScript;
void OnTriggerEnter(Collider col)
{
//...
ReferenceToYourCanvasScript.ReactToInteraction;
}
解决方案2:事件动作
TriggeringBehaviour
您可以使用例如实现自定义事件
public event Action OnTriggered;
void OnTriggerEnter(Collider col)
{
//...
if(OnTriggered!=null)
{
OnTriggered.Invoke();
}
}
比你必须在你的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
}
或者,您也可以创建一个静态类来处理这些事件
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);
}
}
通过这种方式,注册和调用事件会更容易一些:
在TriggerBehaviour
void OnTriggerEnter(Collider col)
{
//...
TriggerEvents.InvokeOnTriggered();
// or if you want to also check who triggered
// TriggerEvents.InvokeOnTriggeredBy(this);
}
并且在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)
{
// ...
}
这非常灵活,还可以传递您想要/需要的任意数量的参数(在这种情况下无论如何都没有)。但是,您仍然必须以某种方式获得对正确组件的相应引用。
一个很大的缺陷是注册,尤其是在不取消注册的情况下销毁某些东西会导致错误并且非常令人沮丧。
解决方案3:UnityEvent(我个人最喜欢的)
或者,您也可以实现一个UnityEvent
inTriggeringBehaviour
public event Action OnTriggered;
void OnTriggerEnter(Collider col)
{
// ...
OnTriggered.Invoke();
}
最大的优点是这UnityEvent
将在 Inspector 中显示和配置!(您会从 UI Button onClick 事件中识别它)
因此您可以从检查器中引用任何其他组件,而不必在运行时注册侦听器(您仍然可以通过 来注册triggerBahviour.OnTriggered.AddListener()
)。
但是UnityEvent
有点有限。例如,使用具有多个或非标准参数(例如自定义类引用)的不同签名调用不同的方法并不是那么简单。