NullReferenceException UnityEngine.MonoBehaviour.StartCoroutine

Hello,

I want to change the Sprite of a GameObject via C# script. The picture URL I get successfully from a REST API Call. With WWW I want to create the new Sprite for the GameObject. But now I don’t have no idea what i am doing wrong. I read to solve the problem by using Unity - Scripting API: GameObject.AddComponent but how in detail?

This is the OnClick event script of a button:

    ApiClient apiclient = new ApiClient();
    string imageurl = apiclient.callSearchApiWithCSharp(realEstateType, preisText.text, zimmerText.text);
    Debug.Log(imageurl);
    apiclient.loadPic(imageurl);

methods to get the picture and create a sprite of it:

public void loadPic(string url)
{
    WWW www = new WWW(url);
    StartCoroutine(WaitForRequest(www));
}

IEnumerator WaitForRequest(WWW www)
{
    yield return www;

    // check for errors
    if (www.error == null)
    {
        Debug.Log("WWW Ok!: " + www.text);
        image.GetComponent<Image>().overrideSprite = Sprite.Create(www.texture, new Rect(0, 0, 438, 441), new Vector2(0.5f, 0.5f));
    }
    else
    {
        Debug.Log("WWW Error: " + www.error);
    }
}

Output is:

https://s@sandboxpicis24-a.akamaihd.net/pic/orig02/L/106/539/941/106539941-0.png

NullReferenceException
UnityEngine.MonoBehaviour.StartCoroutine (IEnumerator routine) (at C:/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineMonoBehaviourBindings.gen.cs:61)
ApiClient.loadPic (System.String url) (at Assets/ApiClient.cs:89)
ObjectTypeListener.callObjectType () (at Assets/ObjectTypeListener.cs:59)
UnityEngine.Events.InvokableCall.Invoke (System.Object[] args) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:153)
UnityEngine.Events.InvokableCallList.Invoke (System.Object[] parameters) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:634)
UnityEngine.Events.UnityEventBase.Invoke (System.Object[] parameters) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:769)
UnityEngine.Events.UnityEvent.Invoke () (at C:/buildslave/unity/build/Runtime/Export/UnityEvent_0.cs:53)
UnityEngine.UI.Button.Press () (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:35)
UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:44)
UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:52)
UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:269)
UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
ControllerTrack2:ProcessTrigger(PointerEventData, GameObject) (at Assets/ControllerTrack2.cs:77)
ControllerTrack2:Process() (at Assets/ControllerTrack2.cs:49)
UnityEngine.EventSystems.EventSystem:Update()

Your problem is a common gotcha for Unity beginners. The “reason-chain” for this is:

  • Coroutines are run by the coroutine scheduler and are bound to the MonoBehaviour that has been used to start the coroutine. StartCoroutine is an instance member of MonoBehaviour.
  • All Components must not be created with “new”. Components always need to be created with AddComponent. Components can only “live” on GameObjects.
  • Wrongly initialized Components (i.e. created with “new”) will turn into “fake null objects”.

“Fake null objects” are true C# managed classes but they are lacking the native C++ equivalent in the engine’s core. They could still be used as “normal” managed classes, but nothing related to Untiy will work, Furthermore the “UnityEngine.Object” baseclass overloads the == operator and “fakes” that the object is null when it’s lacking the native part. That happens when you create a Component class with new or when you Destroy such an object.

So the solution is you have to attach your “ApiClient” component to a GameObject. Unlike Components GameObjects can be created with “new”. So you can simply replace

ApiClient apiclient = new ApiClient();

with

ApiClient apiclient = (new GameObject("SomeObjName")).AddComponent<ApiClient>();

This will create a new GameObject with the name “SomeObjName” and add your ApiClient component to it.

Keep in mind that the GameObject (and it’s components) will now be present in the scene until you destroy it.

As alternative you could attach your ApiClient component to the same gameobject that the calling script is attached to by using:

ApiClient apiclient = gameObject.AddComponent<ApiClient>();

Every component (so MonoBehaviour as well) has the gameObject property which can be used to access the GameObject that this component is attached to.

edit
A quick note on “Destroy”. When you destroy a component, only that component will be destroyed and removed. If you call Destroy on a GameObject reference it will destroy the gameobject including all attached components (since they can’t exist without GameObject) as well as all child GameObjects of the GameObject.

my psychic debugging powers are telling me that either your “GameObject image” variable is not set, or it doesn’t have Image component attached to it, at the time when this line is called:

image.GetComponent<Image>().overrideSprite = Sprite.Create(www.texture, new Rect(0, 0, 438, 441), new Vector2(0.5f, 0.5f));

To check if this is the case (as well as automatically handle if it is), replace the line with

if(image != null){
Image imgComponent = image.GetComponent<Image>();
if(imgComponent == null){
   Debug.Log("image object doesn't contain Image component. Adding it.");
   imgComponent = (Image)image.AddComponent<Image>();
 }

imgComponent.overrideSprite = Sprite.Create(www.texture, new Rect(0, 0, 438, 441), new Vector2(0.5f, 0.5f));

} else Debug.Log("image GameObject is not set to anything");

Also “thank you very much”, now the word “image” looks and sounds extremely weird to me, after so many repetitions :smiley: Get back to tell us how the replacement code I gave you behaves.

I’ve been using unity for 7 + years and this type of behavior sometimes still stumps me.