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

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

08.01.2013, 00:16. Показов 6321. Ответов 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
4652 / 2072 / 366
Регистрация: 17.03.2012
Сообщений: 10,182
Записей в блоге: 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
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru