0

MonoBehaviour - базовый класс в Unity, в котором реализованы все основные функции, методы и обработчики... Сделаю условный пример:

Есть 2 класса:

// 1 - ый класс:
public class HttpRequest : MonoBehaviour
{
    //public delegate void DelegateAnswer(string j);
    //public event DelegateAnswer Emit_answer;
private string url = "http://localhost";
private string port = ":5555";


public void POST(string dataForSending) {
    StartCoroutine(PostRequest(dataForSending)); // !!! ОШИБКА В ЭТОЙ СТРОКЕ ВОЗНИКАЕТ !!!
}

public IEnumerator PostRequest(string json) {
    UnityWebRequest req = new UnityWebRequest(url + port, "POST");
    byte[] jsonToSend = new System.Text.UTF8Encoding().GetBytes(json);
    req.uploadHandler = (UploadHandler)new UploadHandlerRaw(jsonToSend);
    req.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
    req.SetRequestHeader("Content-Type", "application/json");

    yield return req.SendWebRequest();

    if (!req.isNetworkError) {
        json = req.downloadHandler.text;
        //Emit_answer(json);
    }
}

}

ОШИБКА: NullReferenceException

// 2-ой класс:
public class Menu : MonoBehaviour
{
    private HttpRequest httpRequest;
    private string statusOfWaiting = "";

void Start() { httpRequest = new HttpRequest(); httpRequest.Emit_answer += Checking;

    httpRequest.POST("CkeckOnUniqNickname|" + chInfo.Nickname);
    statusOfWaiting = "CkeckOnUniqNickname";
}

}

Подскажите, может кто знает, что не так сделано?

Возможно стоило вызывать только метод возвращающий Ienumerator для запуска корутины в классе, в котором располагается сам объект. Но Мне бы хотелось бы построить такой вот класс HttpRequest, который бы все делал бы внутри себя и возвращал бы ответ при помощи сигнала и слота.

aepot
  • 49,560
Gleb Igorevich
  • 155
  • 1
  • 8

1 Answers1

3

Скорее всего проблема в том, что вы пытаетесь использовать конструктор у класса HttpReqest, который наследует MonoBehaviour. При разработке на юнити, следует отказаться от использования конструкторов для MonoBehaviour классов. Заместо конструктора юнити предлагает методы Awake() и Start(). Все дело в том, что между обычным и MonoBehaviour классом есть большая разница. MonoBehaviour класс подразумевает собой объект (gameobject) на сцене в юнити, что по факту является ресурсом и требует времени на создание\загрузку. Юнити использует конструкторы MonoBehaviour классов для своих нужд и в свое время за кулисами вашего кода. На эту тему, вы можете прочитать множество вопросов и статей в интернете.

Думаю в вашем коде проблема может быть связана с тем, что вы создаете HttpRequest с помощью конструктора и сразу заставляете его исполнить какие-то действия (в корутине). Но на момент вызова этого кода у вас нет никакой гарантии, что стоящий за этим классом gameObject уже был создан и проинициализирован (а как все знают у любого gameObject есть компоненты типа Transform\ RectTransform, которые тоже наверняка требуют времени на инициализацию). Таким образом вы пытаетесь стартовать корутину на объекте, которого может еще не быть.

На вашем месте, я бы не стал наследовать HttpRequest от MonoBehaviour, как минимум потому, что ему не нужен никакой функционал. А gameobject для запуска корутины внутри этого класса можно передать и как параметр в методе.

Либо можете попробовать поправить код минимальной кровью - заменить вызов конструктора на вызов метода AddComponent(), оставив при этом HttpRequest наследником MonoBehaviour - тогда и HttpeRequest и Menu будут висеть на одном и том же gameObject и все должно быть в порядке.

vmchar
  • 4,442
  • Я думаю, это самый ахренительный ответ в моей жизни =)) Я не пробовал еще, так как был занят. Но уверен, что вы правы. Думаю так и есть. Я как то об этом не подумал. Сразу видно профи гейм дева ! – Gleb Igorevich Apr 19 '21 at 17:56