在脚本中使用来自链接游戏对象的组件

Using components from a linked gameObject in a script

抱歉,如果这太简单了,但我无法找到这方面的答案。通常问题要么太复杂无法回答,要么太简单不知道。

这在一定程度上是一个统一体 VR/VRTK 问题(也许...)

无论如何,我的目标是为我的 Canvas 设置触发器,以便能够启动视频播放器并使其在拾取对象时启用并出现在场景中。截至目前,除了我能够在玩家与游戏对象交互时触发这两个动作外,一切都已准备就绪。

在我的脚本中,我有:

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;


}

很简单,但是一切都在统一中联系起来,而且很有趣。我的问题是我试图引用 GameObject 上的脚本,以便我可以使用它的触发器来使视频播放器能够执行它的操作。在附加的 Interactible 脚本中有一个简单的 bool,我认为它可能有用,或者我可以自己编写,问题是我不知道如何从 GameObject 组件中引用。也许我只是不理解它,但我已经看了一段时间,现在我转向你,集体寻求帮助......

帮助:(

-提前感谢大家,该项目还有更多内容,但我认为这些内容最相关。如果我遗漏了一些需要的东西,请告诉我。

我不太明白你的最终目标是什么,但是这两行

videoPlayer = videoPlayer.GetComponent<VideoPlayer>();
canvas = canvas.GetComponent<Canvas>();

没有多大意义。你要么已经有了引用(例如来自检查员)而不需要再次获取组件,要么你想从 GameObject

中获取它们

如果您希望组件附加到 与提供的脚本相同 GameObect,请改用

videoPlayer = GetComponent<VideoPlayer>();
canvas = GetComponent<Canvas>();

或者,如果您想从 asset 游戏对象中获取组件,请使用

videoPlayer = asset.GetComponent<VideoPlayer>();
canvas = asset.GetComponent<Canvas>();

然后你可以添加一个 public 方法来调用它 "interacting" (但是看起来像)与 GameObject

public void ReactToInteraction()
{
    // E.g.

    canvas.enabled = true;
    videoPlayer.Play();
}

来自您的评论

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.

我知道你在某个地方有一个 "triggering event" 让我们在 class TriggeringBehaviour 中的 GameObject ObjectA 例如

void OnTriggerEnter(Collider col)
{
    //...
}

并且您希望在调用触发器时在 canvas 上调用方法 ReactToInteraction

有很多方法可以做到这一点,但我个人更喜欢以下方法之一:

方案一:直接调用

如果您 "know" 您的引用,要么在检查器中引用,要么使用某种形式查找它们,例如使用单例或 FindObjectOfTypeFind(按名称)等您可以直接从 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
}

或者,您也可以创建静态 class 来处理这些事件

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)
{
    // ...
}

这非常灵活,您还可以传递尽可能多的参数 want/need(在本例中 none 无论如何)。但是,您仍然需要以某种方式获得对正确组件的相应引用。
一个很大的缺陷是注册,尤其是销毁某些东西而不注销会导致错误并且非常令人沮丧。

解决方案 3:UnityEvent(我个人最喜欢的)

或者,您也可以在 TriggeringBehaviour

中实现 UnityEvent
public event Action OnTriggered;

void OnTriggerEnter(Collider col)
{
    // ...

    OnTriggered.Invoke();
}

最大的优势是这个 UnityEvent 将在检查器中显示和配置! (您会从 UI 按钮的 onClick 事件中认出它)
因此,您可以仅从检查器中引用任何其他组件,而不必在运行时注册侦听器(您仍然可以通过 triggerBahviour.OnTriggered.AddListener() 进行注册)。
但是 UnityEvent 有点受限。例如。使用具有多个或非标准参数(例如自定义 class 引用)的不同签名调用不同的方法并不是那么简单。

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.

我的做法是

  • 创建一个 canvas,添加一个 UI> RawImage GO 作为 canvas
  • 的子项
  • 向原始图像添加视频播放器组件并取消选中“播放于 醒来'
  • 创建 RenderTexture 资源,将其大小更改为 1920 x 1080?
  • 将您的视频剪辑和新的渲染纹理资产插入视频 组件
  • 关闭原始图像 GO [您已设置]

对象的伪代码

 if object is picked up (on collision enter?)
   turn on raw image GO (setActive)
   rawImage.getComponent<videoPlayer>().Play()