GetComponent with events

Hi All,

I am evaluating unity for a project I’m working on, and I’m having trouble accessing one script from another.

In my example, I have a webcam library which has a callback for when a new frame is received. I have created a callback class to fire when that frame is received, which then fires an event alerting the Webcam : MonoBehavior script that it was received.

In the event handler the Webcam script then calls GetComponent() [which is also a script that extends MonoBehavior] but when I do this I get an exception in the error log and unity freezes up.

UnityEngine.Component:GetComponent(Type)
UnityEngine.Component:GetComponent() (at C:\BuildAgent\work\f724c1acfee760b6\Runtime\ExportGenerated\Editor\BaseClass.cs:630)
Webcam:webcamCallback_FrameReceived(Object, EventArgs) (at Assets\Webcam.cs:93)
WebcamImageSourceCallback:OnImageSourceNewFrame(WebcamImage) (at Assets\Webcam.cs:26)

Webcam.cs line 93 is the GetComponent<…> call.

Any ideas how I’m supposed to be doing this?

Thanks,
Liron

It looks like you omitted the actual exception message and provided the stacktrace in stead. Also, some pastes of what code is causing this would be helpful in debugging the issue.

All I get in the error log is the stacktrace above along with:
Error in file: C;/BuildAgent/work/f724c1afee760b6/Runtime/mono/MonoManager.cpp at line: 2494.

If I actually debug into it in MonoDevelop when I try and step over the GetComponent call I get:
System.ArgumentException has been thrown
Object reference not set to an instance of the object

Some basic code is stubs are as follows:
In Webcam.cs

public class WebcamImageSourceCallback : IUnityImageSourceCallback
{
  public event EventHandler FrameReceived;
  public WebcamImageSourceCallback()
  {
  }
  public override void OnImageSourceNewFrame(WebcamImage image)
  {
    if (m_pendingImage)
    {
      m_lastImage = image;
      if (FrameReceived != null)
      {
        FrameReceived(this, null);
      }
    }
  }
  ...
}

public class Webcam : MonoBehaviour 
{
  ...
  void Awake()
  {
      m_WebcamCallback = new WebcamImageSourceCallback();
      m_Webcam = new UnityWebcam();
      m_Webcam.SetCallback(m_WebcamCallback);      	
      m_WebcamCallback.FrameReceived += new EventHandler(webcamCallback_FrameReceived);
  }
  void Start()
  {
     m_Webcam.Start();
  }
  
  void webcamCallback_FrameReceived(object sender, EventArgs e)
  {
    MainAppLogic mainScript = GetComponent<MainAppLogic>();
   mainScript.AddImage(...);
    ...
  }
}

In MainAppLogic.cs

public class MainAppLogic: MonoBehaviour 
{
//Whatever logic this class does on awake/start/update
  public void AddImage(...);
}

Not exactly a lot of detail in there :wink: Could you try reproducing the issue in a super-simple script which you may be able to paste here in full?

511788–18179–$Assets.zip (1.6 KB)

Here is a basic demo app that causes this crash. In an empty scene I attach all 3 scripts to the main camera and get the same error as I got above.

MainGui creates a start/stop button which call into the Webcam script. This works and the webcam script starts.

Webcam starts a thread which fires an event every second. When this event is handled it should call into MainApp, but calling GetComponent fails.

I’m assuming the issue has something to do with needing to invoke the main thread somehow, but I’m not sure.

Hope this is enough code to be of some help.

Thanks,
Liron

Bump. Anyone?

I’m not sure why the GetComponent() call is failing, but I was able to get this to work by making one small change. Make the mainAppScript variable global to the class and set it in the Awake function.

  MyCallback m_WebcamCallback = null;
  WebcamSimulator m_Webcam = null;
  MainApp mainAppScript;
  public void StartWebcam()
  {
    m_Webcam.Start();
  }
  public void StopWebcam()
  {
    m_Webcam.Stop();
  }
  void Awake()
  {
    m_WebcamCallback = new MyCallback();
    m_Webcam = new WebcamSimulator();
    mainAppScript = GetComponent<MainApp>();
    m_WebcamCallback.FrameReceived += new EventHandler(webcamCallback_FrameReceived);
  }

Then change your webcamCallback_FrameReceived function to this:

void webcamCallback_FrameReceived(object sender, EventArgs e)
  {
    //MainApp mainAppScript = GetComponent<MainApp>();
    mainAppScript.IncrementCount();
  }

Thanks, I’m giving this a try right now.