除了这两行,我还不太明白你的最终目标是什么
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();
}
来自您的评论
我的主要问题围绕着尝试访问附加到不同游戏对象的脚本。在我编写的脚本中,我将它附加到画布上,但我希望它由与此画布无关的不同游戏对象内部的组件触发。
我知道你在某个地方有一个“触发事件”,比如说在 TriggeringBehaviour 类中的一个游戏对象 ObjectA 上,例如
void OnTriggerEnter(Collider col)
{
//...
}
并且您希望在调用触发器时在您的画布上调用方法 ReactToInteraction。
有很多方法可以做到这一点,但我个人更喜欢以下一种:
方案一:直接调用
如果你“知道”你的引用,要么在检查器中引用,要么使用某种形式找到它们,例如单例或FindObjectOfType、Find(按名称)等你可以直接从TriggeringBehaviour调用方法:
// todo get this somehow with the known methods
public CanvasBehaviour ReferenceToYourCanvasScript;
void OnTriggerEnter(Collider col)
{
//...
ReferenceToYourCanvasScript.ReactToInteraction;
}
方案二:事件动作
您可以使用例如在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(我个人最喜欢的)
或者,您也可以在TriggeringBehaviour 中实现UnityEvent
public event Action OnTriggered;
void OnTriggerEnter(Collider col)
{
// ...
OnTriggered.Invoke();
}
最大的优势是这个UnityEvent 将在检查器中显示和配置! (您会从 UI Button onClick 事件中认出它)
因此,您可以从检查器中引用任何其他组件,而不必在运行时注册侦听器(您仍然可以通过 triggerBahviour.OnTriggered.AddListener() 注册)。
但是UnityEvent 有点受限。例如。使用具有多个或非标准参数(例如自定义类引用)的不同签名调用不同的方法并不是那么简单。