Форум программистов, компьютерный форум, киберфорум
Unity, Unity3D
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/30: Рейтинг темы: голосов - 30, средняя оценка - 5.00
17 / 5 / 3
Регистрация: 22.03.2011
Сообщений: 329

Как вызвать методы Unity вне главного потока?

08.01.2013, 00:16. Показов 6305. Ответов 1
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Привет. У меня есть асинхронный сервер и клиент. И вся инфа, которая приходит от сервера к клиенту, обрабатывается в отдельном потоке, но мне необходимо создать объект, вытащить из него компонент, и присвоить полям компонента значения, которые пришли от сервера. Я уже неделю над этим страдаю, мне кто-то подсказал, что нужно использовать делегаты, вот буквально 15 минут назад я так и сделал, но вылезла таже ошибка -Невозможно вызвать функцию Load вне главного потока.
Вот код, ключевая функция, в которой обрабатывается инфа пришедшая от сервера, и в которой должен создаватся объект - ProcessReceive
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
 
public class Client : MonoBehaviour {
    //public static GameObject user;
    public TextMesh my_nick=new TextMesh(); // ник над головой перса
    private static  GameObject pref; // то, что будет создаватся при вхождении в игру нового перса
    private static List<GameObject> user_list=new List<GameObject>(); // массив всех персов кроме нашего
    public Transform Spawn_Point;
    private static Vector3 Spawn_Pos;
    //private static Quaternion Spawn_Rot;
    private static int my_id; // id юзера
    private static int char_id; // id перса
    private static string nick_name; //ник перса
    private static int first=1;
    private static Transform my_trans; // наша трансформа
    //private static int UserID;
    //private static int CharID;
    //private static string Nick;
    
    //new char start
    private static bool create_pref=false;
    private static float p_x; // координаты созданного в будущем перса
    private static float p_y; //
    private static float p_z; //
    
    //new char end
    
        private static Socket socket;
        private static SocketAsyncEventArgs SockAsyncEventArgs; // объект для асинхронной операции на сокете
 
        private static byte[] buff; // буфер обмена
        
        private static For_Delegates FD = new For_Delegates();
        
        delegate GameObject Del_For_GO(Vector3 v3);
        delegate User_Info Del_User_Info(GameObject go);
        
 
        
    
    private static void Init()
        {
        
        
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            buff = new byte[256];
            SockAsyncEventArgs = new SocketAsyncEventArgs();
            // подписываемся на завершение асинхронного соединения
            SockAsyncEventArgs.Completed += SockAsyncArgs_Completed;
        }
    
     private static void SockAsyncArgs_Completed(object sender, SocketAsyncEventArgs e)
        {
            switch (e.LastOperation)
            {
                case SocketAsyncOperation.Connect:
                    ProcessConnect(e);
                    break;
                case SocketAsyncOperation.Receive:
                    ProcessReceive(e);
                    break;
            }
        }
    
     private static void Start_Connect(string address, int port)
        {
            SockAsyncEventArgs.RemoteEndPoint = new IPEndPoint(IPAddress.Parse(address), port);
            ConnectAsync(SockAsyncEventArgs);
        }
    
     private static void ConnectAsync(SocketAsyncEventArgs e)
        {
            bool willRaiseEvent = socket.ConnectAsync(e);
            if (!willRaiseEvent)
                ProcessConnect(e);
        }
    
     private static void ProcessConnect(SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)
                SockAsyncEventArgs.SetBuffer(buff, 0, buff.Length);
            else
                Debug.Log("Lost connection with "+ e.RemoteEndPoint.ToString());
 
        }
    
     private static void SendAsync(byte[] data)
        {
            if (socket.Connected && data.Length > 0)
            {   
                SocketAsyncEventArgs e = new SocketAsyncEventArgs();
                e.SetBuffer(data, 0, data.Length);
                e.Completed += SockAsyncArgs_Completed;
                bool willRaiseEvent = socket.SendAsync(e);
            }
        }
 
    private static void ProcessSend(SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)
            {
                ReceiveAsync(SockAsyncEventArgs);
            }
            else
            {
                Debug.Log("Not sended");
            }
        }
    
     private static void ReceiveAsync(SocketAsyncEventArgs e)
        {
            bool willRaiseEvent = socket.ReceiveAsync(e);
            if (!willRaiseEvent)
                ProcessReceive(e);
        }
    
     private static void ProcessReceive(SocketAsyncEventArgs e)
        {
            if (e.SocketError == SocketError.Success)
            {
            string s = Encoding.UTF8.GetString(e.Buffer,0,1); //получаем идентификатор команды
            Debug.Log("receive = "+s);
                if(s=="n") // если команда "n"
            {
                p_x = BitConverter.ToSingle(e.Buffer, 9); //вытягиваем из буффера позицию
                p_y = BitConverter.ToSingle(e.Buffer, 13);
                p_z = BitConverter.ToSingle(e.Buffer, 17); //позиция получена
                Del_For_GO dfg = new Del_For_GO(FD.Pref);
                Del_User_Info dui = new Del_User_Info(FD.U_I);
                GameObject character = dfg(new Vector3(p_x,p_y,p_z));
                User_Info ui = dui(character);
                ui.UserID = BitConverter.ToInt32(e.Buffer,1); //присваиваем персу id юзера
                ui.CharID = BitConverter.ToInt32(e.Buffer,5); //id персонажа
                ui.Nick = Encoding.UTF8.GetString(e.Buffer,25,BitConverter.ToInt32(e.Buffer,21)); //ник персонажа
                //create_pref=true; // создаем перса
                user_list.Add(pref); //добавляем перса в коллекцию 
                Debug.Log("pref added");
                
            } 
            else // если данные без команды
            {
                Debug.Log("else");
                foreach(GameObject go in user_list) // для каждого юзера в коллеции юзеров
                {
                    /*Debug.Log("foreach");
                    User_Info u_i = (User_Info)go.GetComponent("User_Info"); //получаем компонент с информацией
                    int temp_char_ID = u_i.CharID; // получаем id перса
                    Debug.Log("temp_char ID = "+temp_char_ID+"  buffer id "+BitConverter.ToInt32(e.Buffer,28));*/
                    //if(char_id==BitConverter.ToInt32(e.Buffer,28)) //если id перса из коллеции равен id, который только что пришел
                    //{
                    go.transform.position = new Vector3(BitConverter.ToSingle(e.Buffer,0),BitConverter.ToSingle(e.Buffer,4),BitConverter.ToSingle(e.Buffer,8)); // присваиваем персу из коллекции данные которые в буффере
                    go.transform.rotation = new Quaternion(BitConverter.ToSingle(e.Buffer,12),BitConverter.ToSingle(e.Buffer,16),BitConverter.ToSingle(e.Buffer,20),BitConverter.ToSingle(e.Buffer,24));
                //}
            }
           }              
         }
        }
    
    class For_Delegates
    {
        public User_Info U_I(GameObject go)
        {
            User_Info u_i = (User_Info)go.GetComponent("User_Info");
            return u_i;
        }
        
        public GameObject Pref(Vector3 sp)
        {
            GameObject go = (GameObject)Instantiate(Resources.Load("Prefabs/Player") as GameObject,sp,Quaternion.identity); // создаем перса
            return go;
        }
    }
    
    void Awake()
    {
    transform.position = new Vector3(Selecting.spawn_x,Selecting.spawn_y,Selecting.spawn_z); // присваиваем позицию, которую получили при входе в игру в предыдущей сцене
    }
    
    void Start()
    {
        my_trans=transform; // говорят, так работает быстрее
        //Spawn_Pos=Spawn_Point.position;
        //Spawn_Rot=Spawn_Point.rotation;
        Screen.showCursor=false; //прячем курсор
        char_id = Selecting.char_id; //присваиваем персонажу id который получили при входе в игру в предыдущей сцене
        my_id=Selecting.my_id; // присваиваем персонажу id самого юзера (для бана аккаунта в будущем)
        nick_name = Selecting.slc; // присваиваем персу его ник. который получили при вход в игру в предыдущей сцене
        my_nick.text = nick_name; // рисуем ник над головой перса
        Init(); //подготовка соединения  с сервером
        Start_Connect("127.0.0.1", 9390); //соединяемся с сервером
        StartCoroutine(Transfer()); // отправляем данные серверу
    }
    
    void Update()
    {
        /*Debug.Log(" u list count = "+user_list.Count);
        if(create_pref) 
        {
            pref = (GameObject)Instantiate(Resources.Load("Prefabs/Player") as GameObject,new Vector3(p_x,p_y,p_z),Quaternion.identity); // создаем перса
            User_Info u_i = (User_Info)pref.GetComponent("User_Info");
            u_i.CharID = CharID;
            u_i.UserID = UserID;
            u_i.Nick = Nick;
            user_list.Add(pref);
            create_pref=false;
        }*/
            
    }
    
    /*Transform GetTransform(byte[] b)
    {
        Transform tr;
        tr.position=new Vector3(BitConverter.ToSingle(b,0),BitConverter.ToSingle(b,4),BitConverter.ToSingle(b,8));
        tr.rotation=new Quaternion(BitConverter.ToSingle(b,12),BitConverter.ToSingle(b,16),BitConverter.ToSingle(b,20),BitConverter.ToSingle(b,24));
        return tr;
    }*/
        
    public byte[] ToBytes()
    {
        byte[] bf=new byte[256];
        if(first==1) //если это первая отправка данных серверу
        {
            Debug.Log("Start new");
            Encoding.UTF8.GetBytes("n").CopyTo(bf,0); // пакуем идентифекатор того, что это новый перс
            BitConverter.GetBytes(my_id).CopyTo(bf,1); // пакуем id юзера
            BitConverter.GetBytes(char_id).CopyTo(bf,5); //id перса
            BitConverter.GetBytes(Selecting.spawn_x).CopyTo(bf,9); // координаты перса
            BitConverter.GetBytes(Selecting.spawn_y).CopyTo(bf,13);
            BitConverter.GetBytes(Selecting.spawn_z).CopyTo(bf,17);
            BitConverter.GetBytes(Encoding.UTF8.GetByteCount(nick_name)).CopyTo(bf,21); // длина ника 
            Encoding.UTF8.GetBytes(nick_name).CopyTo(bf,25); //ник
            
            Debug.Log("Send new");
            
            Debug.Log(my_id);
            
            first=0;
            return bf;
        }
        else{ // обычная отправка данных
            byte[] bb = new byte[256];
        BitConverter.GetBytes(transform.position.x).CopyTo(bf, 0); // позиция
        BitConverter.GetBytes(transform.position.y).CopyTo(bf, 4);
        BitConverter.GetBytes(transform.position.z).CopyTo(bf, 8);
        
        BitConverter.GetBytes(transform.rotation.x).CopyTo(bf, 12); //поворот
        BitConverter.GetBytes(transform.rotation.y).CopyTo(bf, 16);
        BitConverter.GetBytes(transform.rotation.z).CopyTo(bf, 20);
        BitConverter.GetBytes(transform.rotation.w).CopyTo(bf, 24);
        
        BitConverter.GetBytes(char_id).CopyTo(bf,28); //id перса
        Debug.Log("sended just trans");
        return bb;
        
        }
    }
/*  
    public static GameObject LoadPlayer(Vector3 pos)
    {
    
        GameObject go = (GameObject)Instantiate(Resources.Load("Prefabs/Player") as GameObject,pos,Quaternion.identity);
        return go;
    }*/
     
    IEnumerator Transfer()
    {
        while(true)
        {
                try
        {
        SendAsync(ToBytes()); // отправка данных
        Debug.Log("sended");    
        if (socket.Available != 0) //если пришли данные
                    {
                        //Thread.Sleep(500);
                        ProcessSend(SockAsyncEventArgs); // получаем их
                    }
        }
        catch(Exception e)
        {
            Debug.Log(e.Message);
        }
    
        yield return new WaitForSeconds(0.25f); //отправка данных 4 раза в секунду
        }
        
    }
    
 
    
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
08.01.2013, 00:16
Ответы с готовыми решениями:

Как вызвать юнити методы из не основного потока?
Кто знает обходной путь как вызвать юнити методы из не основного потока.

Многопоточность: вызвать метод главного потока из второстепенного потока
Здравствуйте. Эта тема всеми избита, знаю. Но у меня очень ограничено время, поэтому рискую и пишу вопрос тут: Пишу приложение...

VC++6.0, как из порожденного потока прочитать переменную главного потока?
Visual C++ 6.0 SP5 Простое диалоговое окно, (MFC) созданное мастером среды VC По нажатию на кнопку создаю поражденный поток, в...

1
Эксперт Python
 Аватар для dondublon
4651 / 2071 / 366
Регистрация: 17.03.2012
Сообщений: 10,180
Записей в блоге: 6
12.02.2013, 15:19
Делегаты тут не при чем, это просто такой тип.
Насколько я знаю, в Unity программисту многопоточность не даётся, там и так всё асинхронно.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
12.02.2013, 15:19
Помогаю со студенческими работами здесь

Не получается с вторичного потока обратиться напрямую к объекту из главного потока
Добрый день. Проблема заключается в том что не могу в WPF с вторичного потока обратится на прямую к объекту из главного потока. WPF пока...

Как из iframe вызвать функции главного окна ?
kak is iframe sourca vizivat funkcii glabnovo okna ?

(Assembly) Как вызвать из подключаемого файла метод главного?
Подключаю NET-овскую DLL с помощью Assembly.LoadFrom(). С помощью References не катит(мне нужна динамическая подгрузка, имени модулей я...

UiThread, как вынести процесс из главного потока?
Я - новичок в Android. Нужно в этом куске кода реализовать многопоточность. Очистить главный поток от операций, связанных с соединением с...

Как запустить метод в главном потоке из не главного потока?
Прив. У меня такая трабла, пишу клиент, для игры на одном движке, и если от сервера пришла какая-то определенная инфа, то мне необходимо...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
Новые блоги и статьи
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru