Unity3d обращение к скрипту на другом объекте. Управление игровыми объектами (GameObjects) с помощью компонентов

JavaScript is designed on a simple object-based paradigm. An object is a collection of properties, and a property is an association between a name (or key ) and a value. A property"s value can be a function, in which case the property is known as a method. In addition to objects that are predefined in the browser, you can define your own objects. This chapter describes how to use objects, properties, functions, and methods, and how to create your own objects.

Objects overview

Objects in JavaScript, just as in many other programming languages, can be compared to objects in real life. The concept of objects in JavaScript can be understood with real life, tangible objects.

In JavaScript, an object is a standalone entity, with properties and type. Compare it with a cup, for example. A cup is an object, with properties. A cup has a color, a design, weight, a material it is made of, etc. The same way, JavaScript objects can have properties, which define their characteristics.

Objects and properties

A JavaScript object has properties associated with it. A property of an object can be explained as a variable that is attached to the object. Object properties are basically the same as ordinary JavaScript variables, except for the attachment to objects. The properties of an object define the characteristics of the object. You access the properties of an object with a simple dot-notation:

ObjectName.propertyName

Like all JavaScript variables, both the object name (which could be a normal variable) and property name are case sensitive. You can define a property by assigning it a value. For example, let"s create an object named myCar and give it properties named make , model , and year as follows:

Var myCar = new Object(); myCar.make = "Ford"; myCar.model = "Mustang"; myCar.year = 1969; myCar.color; // undefined

Properties of JavaScript objects can also be accessed or set using a bracket notation (for more details see property accessors). Objects are sometimes called associative arrays , since each property is associated with a string value that can be used to access it. So, for example, you could access the properties of the myCar object as follows:

MyCar["make"] = "Ford"; myCar["model"] = "Mustang"; myCar["year"] = 1969;

An object property name can be any valid JavaScript string, or anything that can be converted to a string, including the empty string. However, any property name that is not a valid JavaScript identifier (for example, a property name that has a space or a hyphen, or that starts with a number) can only be accessed using the square bracket notation. This notation is also very useful when property names are to be dynamically determined (when the property name is not determined until runtime). Examples are as follows:

// four variables are created and assigned in a single go, // separated by commas var myObj = new Object(), str = "myString", rand = Math.random(), obj = new Object(); myObj.type = "Dot syntax"; myObj["date created"] = "String with space"; myObj = "String value"; myObj = "Random Number"; myObj = "Object"; myObj[""] = "Even an empty string"; console.log(myObj);

Please note that all keys in the square bracket notation are converted to string unless they"re Symbols, since JavaScript object property names (keys) can only be strings or Symbols (at some point, private names will also be added as the class fields proposal progresses, but you won"t use them with form). For example, in the above code, when the key obj is added to the myObj , JavaScript will call the obj.toString() method, and use this result string as the new key.

You can also access properties by using a string value that is stored in a variable:

Var propertyName = "make"; myCar = "Ford"; propertyName = "model"; myCar = "Mustang";

Using a constructor function

Alternatively, you can create an object with these two steps:

  1. Define the object type by writing a constructor function. There is a strong convention, with good reason, to use a capital initial letter.
  2. Create an instance of the object with new .

To define an object type, create a function for the object type that specifies its name, properties, and methods. For example, suppose you want to create an object type for cars. You want this type of object to be called Car , and you want it to have properties for make, model, and year. To do this, you would write the following function:

Function Car(make, model, year) { this.make = make; this.model = model; this.year = year; }

Notice the use of this to assign values to the object"s properties based on the values passed to the function.

Now you can create an object called mycar as follows:

Var mycar = new Car("Eagle", "Talon TSi", 1993);

This statement creates mycar and assigns it the specified values for its properties. Then the value of mycar.make is the string "Eagle", mycar.year is the integer 1993, and so on.

You can create any number of Car objects by calls to new . For example,

Var kenscar = new Car("Nissan", "300ZX", 1992); var vpgscar = new Car("Mazda", "Miata", 1990);

An object can have a property that is itself another object. For example, suppose you define an object called person as follows:

Function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; }

and then instantiate two new person objects as follows:

Var rand = new Person("Rand McKinnon", 33, "M"); var ken = new Person("Ken Jones", 39, "M");

Then, you can rewrite the definition of Car to include an owner property that takes a person object, as follows:

Function Car(make, model, year, owner) { this.make = make; this.model = model; this.year = year; this.owner = owner; }

To instantiate the new objects, you then use the following:

Var car1 = new Car("Eagle", "Talon TSi", 1993, rand); var car2 = new Car("Nissan", "300ZX", 1992, ken);

Notice that instead of passing a literal string or integer value when creating the new objects, the above statements pass the objects rand and ken as the arguments for the owners. Then if you want to find out the name of the owner of car2, you can access the following property:

Car2.owner.name

Note that you can always add a property to a previously defined object. For example, the statement

Car1.color = "black";

adds a property color to car1, and assigns it a value of "black." However, this does not affect any other objects. To add the new property to all objects of the same type, you have to add the property to the definition of the Car object type.

Using the Object.create method

See also

  • To dive deeper, read about the details of javaScript"s objects model .
  • To learn about ECMAScript 2015 classes (a new way to create objects), read the JavaScript classes chapter.

У меня много скриптов. Я хочу иметь возможность управлять ими все в 1 скрипте. Я хочу, чтобы основной скрипт активировал определенный скрипт, а затем, когда вторичный скрипт завершен, он возвращает значение основному скрипту. После этого главный скрипт вызывает другой вторичный скрипт и т. Д. ...

Есть ли правильный способ сделать это?

Более точный вопрос:

    Можно ли активировать скрипт AHK из другого скрипта AHK?

    В настоящий момент, чтобы обнаружить, что на вторичном скрипте завершен, способ, которым я в настоящее время пользуюсь, заключается в том, что прямо перед завершением вторичного скрипта я нажимаю комбинацию ключей, которые обнаружит основной скрипт. И как только он будет обнаружен, он увеличит основную переменную сценария на один, и это вызовет активацию следующего скрипта. Есть ли лучший способ достичь этого?

0

3 ответы

Ниже приведен рабочий пример из документации:

; Example: Send a string of any length from one script to another. This is a working example. ; To use it, save and run both of the following scripts then press Win+Space to show an ; InputBox that will prompt you to type in a string. ; Save the following script as "Receiver.ahk" then launch it: #SingleInstance OnMessage(0x4a, "Receive_WM_COPYDATA") ; 0x4a is WM_COPYDATA return Receive_WM_COPYDATA(wParam, lParam) { StringAddress:= NumGet(lParam + 2*A_PtrSize) ; Retrieves the CopyDataStruct"s lpData member. CopyOfData:= StrGet(StringAddress) ; Copy the string out of the structure. ; Show it with ToolTip vs. MsgBox so we can return in a timely fashion: ToolTip %A_ScriptName%`nReceived the following string:`n%CopyOfData% return true ; Returning 1 (true) is the traditional way to acknowledge this message. } ; Save the following script as "Sender.ahk" then launch it. After that, press the Win+Space hotkey. TargetScriptTitle = Receiver.ahk ahk_class AutoHotkey #space:: ; Win+Space hotkey. Press it to show an InputBox for entry of a message string. InputBox, StringToSend, Send text via WM_COPYDATA, Enter some text to Send: if ErrorLevel ; User pressed the Cancel button. return result:= Send_WM_COPYDATA(StringToSend, TargetScriptTitle) if result = FAIL MsgBox SendMessage failed. Does the following WinTitle exist?:`n%TargetScriptTitle% else if result = 0 MsgBox Message sent but the target window responded with 0, which may mean it ignored it. return Send_WM_COPYDATA(ByRef StringToSend, ByRef TargetScriptTitle) ; ByRef saves a little memory in this case. ; This function sends the specified string to the specified window and returns the reply. ; The reply is 1 if the target window processed the message, or 0 if it ignored it. { VarSetCapacity(CopyDataStruct, 3*A_PtrSize, 0) ; Set up the structure"s memory area. ; First set the structure"s cbData member to the size of the string, including its zero terminator: SizeInBytes:= (StrLen(StringToSend) + 1) * (A_IsUnicode ? 2: 1) NumPut(SizeInBytes, CopyDataStruct, A_PtrSize) ; OS requires that this be done. NumPut(&StringToSend, CopyDataStruct, 2*A_PtrSize) ; Set lpData to point to the string itself. Prev_DetectHiddenWindows:= A_DetectHiddenWindows Prev_TitleMatchMode:= A_TitleMatchMode DetectHiddenWindows On SetTitleMatchMode 2 SendMessage, 0x4a, 0, &CopyDataStruct, %TargetScriptTitle% ; 0x4a is WM_COPYDATA. Must use Send not Post. DetectHiddenWindows %Prev_DetectHiddenWindows% ; Restore original setting for the caller. SetTitleMatchMode %Prev_TitleMatchMode% ; Same. return ErrorLevel ; Return SendMessage"s reply back to our caller. }

теоретически вы также можете использовать файловый объект между сценариями как метод stdin/stdout, так как при открытии файла с файловым объектом вы можете установить его как общий.

Вы также можете установить переменную окружения и передать имя переменной скрипту, учитывая, что у вас есть настройка аргумента в целевом скрипте, который затем устанавливает значение переменной среды при закрытии. используя RunWait, и вы можете узнать, что результат возврата скрипта после запуска.

Наконец, изучите использование функции, поскольку это, вероятно, «лучшая практика» для того, что вы пытаетесь сделать. Поскольку функция может делать все, что может сделать сценарий, и вы можете передать ей массив для работы с или с помощью ByRef в параметре массива. Это означало бы, что вам не нужно писать в кучу параметров при записи функции, и переменные будут освобождать память после завершения функции автоматически. Вы даже можете записать свои функции в отдельный файл и использовать #Include, чтобы использовать их в своем скрипте.

Слово "спрайт" часто используется в программировании игр для обозначения фигурок героев и предметов. Такие фигурки – это на самом деле рисунки или фотографии, то есть компьютерная графика.

Однако спрайт – не только картинка, это объект, наделенный программным кодом и как следствие свойствами и способностями. Со спрайтом можно взаимодействовать как с виртуальной сущностью, отдавать ей команды и получать от нее данные.

Кот в Scratch – не единственный объект-спрайт. Добавить на сцену другие можно несколькими способами: загрузить картинку с компьютера, нарисовать в самой среде программирования, выбрать из библиотеки. Для всего этого в Scratch предусмотрено специальное меню, которое находится внизу справа на панели спрайтов:

Пока ограничимся тем, что будем выбирать готовые спрайты из библиотеки. Для этого надо нажать лупу. Откроется библиотека, где можно найти подходящего героя.

После клика по нему он появится на сцене. Также на панели спрайтов под свойствами появится его иконка. Рядом с иконкой кота. Свойства объекта, где вы задаете ему имя, положение, размер и поворот, отображаются только для того спрайта, который выделен.

Если вы захотите удалить один из спрайтов, кликните по его иконке под свойствами. Этот спрайт станет выделенным, выбранным, иконка обрамится синим цветом и у нее появится крестик, кликнув по которому можно убрать спрайт из игры.

Когда в Scratch мы собираем блоки в программный код, этот код не существует в прострации сам по себе. Чаще всего он относится к какому-то спрайту. Другими словами, у каждого спрайта свой программный код, своя программа, свое предназначение. Герои могут "общаться" между собой через сигналы, которые посылают друг к другу. Но это другая история.

Сейчас надо запомнить, что когда мы работаем с блоками, следует обращать внимание на то, какой объект выделен. В Scratch появляется подсказка в верхнем правом углу поля редактора кода. Там бледным цветом отображается фигурка выделенного на данный момент спрайта. А значит весь код, который вы видите в рабочей области, относится только к данному герою.

Когда выделяется другой спрайт, то код предыдущего становится невидимым.

Нередко код одного спрайта оказывается похожим на другой. Например, оба героя ходят по сцене, просто с разной скоростью и в разные направления. Собирать два раза почти одинаковую комбинацию блоков – не слишком удачное решение. Проще скопировать программу одного спрайта, добавить ее другому, а потом немного изменить.

В Scratch копировать собранные в программу блоки можно как в пределах одного проекта, так и переносить копию в "рюкзаке" из одного проекта в другой. Рюкзак находится внизу интерфейса среды разработки.

Допустим, у нас есть проект под названием "Проект 1", где мы составили программу движения кота туда-сюда. Мы хотим скопировать этот код в "Проект 2". Тогда мы заходим в первый проект, открываем рюкзак и перетаскиваем сюда конструкцию блоков.

При этом надо помнить правило: переносится участок кода от верхнего блока, за который мы держимся, и блоки, расположенные ниже него. Если вы взялись за блок, расположенный где-то в середине программы, то верхние блоки оторвутся и не будут захвачены.

Положив в рюкзак программу, мы возвращаемся во второй проект. Выделяем спрайт, которому хотим добавить код. Открываем рюкзак и достаем из него нашу программу.

Чтобы скопировать программу одного спрайта на другой в пределах одного проекта, достаточно захватить код и бросить его на иконку другого спрайта, которая расположена под свойствами на панели спрайтов.

Если надо скопировать код в пределах одного спрайта, надо кликнуть по конструкции правой кнопкой мыши и в контекстном меню выбрать "Дублировать".

Также обратите внимание на пункт "Добавить комментарий". Программисты часто пользуются комментариями, чтобы пояснить себе и остальным, что делает та или иная часть программы. Ведь при взгляде на сложный код не всегда сразу можно понять, для чего он, и как все это работает.

Когда на сцене обитают несколько спрайтов, становится важным их положение относительно друг друга, их место на сцене. Как вы уже должны были понять, изучая панель свойств спрайта, положение героя задается координатами, то есть точкой на плоскости.

В Scratch начало отсчета, то есть точка с координатами (0; 0), находится в центре сцены. Общая ширина сцены составляет 480 точек. Это значит, что координата x может принимать значения от -240 до 240. Общая высота сцены составляет 360 точек. Это значит, что координата y может принимать значения от -180 до 180.

Хотя работу с фонами мы будем изучать позже, добавим на сцену координатную сетку. Это поможет нам сориентироваться в системе координат Скретча. Чтобы выбрать фон из библиотеки, надо нажать на лупу в меню сцены, которое находится в нижнем правом углу окна, на панели "Сцена".

Откроется библиотека фонов, прокрутите ее в самый низ и выберите фон "Xy-grid". На сцене появится координатная сетка.

Давайте уменьшим размер наших спрайтов раза в два, то есть примерно до 50%, чтобы они не занимали большую площадь сцены, а больше походили на точку. Теперь поиграем с их координатами. Для этого можно менять значения x и y на панели свойств и смотреть, где после этого окажется герой. Или просто перетаскивать мышью спрайт на сцене и смотреть как меняются x и y в свойствах.

Например, если x = 0, y = 150, спрайт окажется в центре по горизонтали и вверху по вертикали. Если x = 200, y = 0, то спрайт окажется справа по горизонтали и в центре по вертикали.

На самом деле не обязательно до запуска программы устанавливать спрайты в нужное место с помощью мыши или панели свойств. Обычно это делают программно, с помощью специальных блоков кода, находящихся в разделе "Движение". Одним из управляющих местоположением блоков является команда "перейти в x: … y: …". Вместо точек указываются желаемые координаты.

Эта команда быстро перебрасывает спрайт в заданную точку, поэтому ее часто используют в начале программы:

В приведенном примере, где бы ни стоял на сцене спрайт до запуска программы, как только будет нажат зеленый флажок, герой тут же окажется в точке (0; 50).

Отметим напоследок про слои. Наше пространство не двумерное, как плоскость, а трехмерное. У нас есть высота, ширина и длина. Хотя Scratch позволяет создавать только двумерные анимации, на самом деле даже в 2D-анимации есть своего рода третье измерение. Это слои.

Пусть по сцене перемещаются два спрайта. Что будет когда их координаты совпадут? Ничего. Они не столкнуться и не затормозят друг друга. Один спрайт пройдет как бы позади другого, а другой – поверх первого. Каждый живет на своем слое плоскости и ему нет дела до другого.

Однако бывает важно, слой какого спрайта расположен выше, то есть впереди. Посмотрите на рисунок:

Слева слой ракеты расположен выше, слоя кота. Справа, наоборот, кот находится над ракетой.

В Scratch изменить очередность слоев можно как мышкой на сцене, так и с помощью блоков кода. Чтобы это сделать первым способом, надо взять тот спрайт, который должен быть над, и кинуть его на спрайт, чей слой должен быть под.

Блоки изменения очередности слоев находятся в фиолетовой секции "Внешний вид". Это команды "перейти на передний/задний фон" и "перейти вперед/назад на … слоя".

Задание

Составьте программу, в которой один спрайт постоянно ходит за указателем мыши, а второй – находится в центре сцены и, стоя на одном месте, медленно крутится по часовой стрелке. Слой первого объекта должен быть над слоем второго.

2018-06-22T12:41:05+00:00

Проблема корректного создания и освобождения COM-объектов в любом managed языке (со сборщиком мусора) сложна и многогранна - столько всего уже написано на эту тему и всё равно возникают постоянные споры и недопонимания на форумах.

Постараюсь быть кратким и лаконичным, так как данная статья носит больше практический характер и не претендует на истину в последней инстанции.

Я лишь опишу свой опыт применительно к использованию OneScript для общения с базами 1С через внешнее соединение при запуске из Обновлятора (хотя способ запуска на самом деле не имеет значения).

При этом я не буду останавливаться на самом понятии COM-объекта (в этом смысле я всех отсылаю к замечательной книге "Основы COM" Дейла Роджерсона).

Также я не буду останавливаться на том, как COM-объекты уживаются в языках с автоматическим управлением памятью, к которым относится в том числе OneScript.

В этой статье будут лишь практические выводы.

Суть проблемы

А проблема состоит в том, что при выполнении кода через внешнее соединение с базой (которое само по себе является COM-объектом) порождается большое количество как явных (которые мы сами объявили), так и неявных COM-объектов.

И если мы не уничтожаем эти объекты напрямую, то они уничтожаются автоматически в порядке и в момент, когда это сочтёт нужным сделать среда выполнения.

В целом в идеальном мире это не должно быть проблемой и COM-библиотеки должны учитывать этот момент. И если бы это было всегда так - мне не пришлось бы вообще писать эту статью.

К сожалению, практика в целом и применительно к COM-библиотеке для внешнего подключения к базам 1С в частности показывает, что порядок уничтожения всех COM-объектов должен быть задан явно и он должен быть обратным порядку их создания.

И если этого не делать, то наш скрипт будет отлично работать на одних компьютерах (или с одной платформой 1с) и при этом валиться с ошибкой на других компьютерах (других платформах 1с).

Ошибка будет возникать в самом конце работы скрипта при уничтожении COM-объектов сборщиком мусора. Такая ошибка будет нестабильной и в лучшем случае будет просто приводить к тому, что не будет корректно завершаться соединение с базой. То есть скрипт уже отработает, а консоль сервера 1с будет показывать, что соединение с базой ещё есть.

При этом сам скрипт отработает замечательно и выполнит всё, что мы от него хотим, но вот само соединение с базой будет завершено некорректно и код ошибки от OneScript чаще всего будет -1073741819.

При этом в самих примерах на OneScript в Обновляторе я изначально не буду делать явное освобождение ресурсов, чтобы не отпугивать пользователей. Вместо этого я буду давать ссылку на эту статью с разбором простейших примеров.

Первый пример

Рассмотрим простейший скрипт по выводу списка пользователей:

Какие здесь COM-объекты мы видим:

  1. v8 - этот объект был создан обновлятором явно и уничтожается он в процедуре ПриОкончанииРаботы.
  2. v8.ПользователиИнформационнойБазы - здесь мы обратились через точку к менеджеру пользователей информационной базы и новый COM-объект был создан неявно средой выполнения OneScript. Это недопустимая для нас ситуация, так как мы не сможем освободить такой объект в нужный нам момент. Ниже я покажу как избавиться от такого неявного создания объекта.
  3. СписокПользователей - этот COM-объект нам вернул метод ПолучитьПользователей.
  4. Пользователь - этот COM-объект создаётся на каждой итерации цикла.

Вроде бы всё? А вот и нет. Здесь присутствует ещё один неявно создаваемый COM-объект внутри среды выполнения. И причина его создания - использование цикла Для Каждого. При использовании такого цикла создаётся итератор для СписокПользователей и этот итератор содержит внутренний COM-объект, который мы также не сможем освободить. Отсюда сразу правило - следует избегать циклов Для Каждого при обходе COM-коллекций.

А вот как следует переписать этот код, чтобы после его выполнения были явно и в нужном порядке освобождены все созданные в нём COM-объекты:

ПользователиИнформационнойБазы = Неопределено ; СписокПользователей = Неопределено ; Попытка ПользователиИнформационнойБазы = v8. ПользователиИнформационнойБазы; СписокПользователей = ПользователиИнформационнойБазы. ПолучитьПользователей() ; Сообщить("Выводим всех пользователей базы:" ) ; Для Индекс = 0 По СписокПользователей. Количество() - 1 Цикл Пользователь = СписокПользователей. Получить(Индекс) ; Сообщить(Пользователь. Имя) ; ОсвободитьОбъект(Пользователь) ; КонецЦикла ; Исключение КонецПопытки; Если СписокПользователей <> Неопределено Тогда ОсвободитьОбъект(СписокПользователей) ; КонецЕсли ; Если ПользователиИнформационнойБазы <> Неопределено Тогда ОсвободитьОбъект(ПользователиИнформационнойБазы) ; КонецЕсли ;

Обратите внимание, что здесь мы:

  1. Сохранили обращение к менеджеру информационных баз в отдельную переменную, чтобы затем явно вызвать его освобождение.
  2. Избавились от цикла Для Каждого.
  3. На каждом шаге цикла освобождаем объект Пользователь.
  4. Обернули весь код в блок Попытка Исключение, чтобы после его выполнения (целиком или частично в случае ошибок) гарантированно освободить все созданные COM-объекты. При этом мы опустили обработку ошибок (ничего не написали внутри блока Исключение КонецПопытки).

Второй пример

Предположим, что мы программно создаём обработку из конфигурации базы, чтобы запустить её выполнение из нашего кода.

Код создания обработки будет таким:

  1. Неявно создаётся COM-объект v8.Обработки
  2. Неявно создаётся COM-объект v8.Обработки.ИмпортКейса
  3. Явно создаётся COM-объект обработки и сохраняется в переменной МодульЗагрузки.

При таком коде мы сможем явно освободить только МодульЗагрузки, а вот с двумя неявно созданными COM-объектами мы ничего поделать не сможем.

Поэтому такой код должен быть переписан вот так:

Обработки = Неопределено ; ИмпортКейса = Неопределено ; МодульЗагрузки = Неопределено ; Попытка Обработки = v8. Обработки; ИмпортКейса = Обработки. ИмпортКейса; МодульЗагрузки = ИмпортКейса. Создать() ; // остальной код... Исключение КонецПопытки; Если МодульЗагрузки <> Неопределено Тогда ОсвободитьОбъект(МодульЗагрузки) ; КонецЕсли ; Если ИмпортКейса <> Неопределено Тогда ОсвободитьОбъект(ИмпортКейса) ; КонецЕсли ; Если Обработки <> Неопределено Тогда ОсвободитьОбъект(Обработки) ; КонецЕсли ;

Третий пример

А что будет, если мы в нашем скрипте выполним вот такой код (выдержка из предыдущего примера):

Обработки = v8. Обработки; ИмпортКейса = Обработки. ИмпортКейса; ИмпортКейса. Создать() ;

Обратите внимание на то, что мы вызвали метод Создать(), который вернул нам COM-объект, но мы его никуда не сохранили.

Такой код будет ошибкой, так как если метод возвращает COM-объект, то этот объект остаётся висеть в памяти, даже если мы его не сохранили и не работаем с ним в коде.

Да, в этом случае такой код не имел бы смысла (зачем создавать экземпляр обработки и не использовать его), но могут быть ситуации, когда мы вызываем некоторый метод у COM-объекта и не обрабатываем результат этого метода, так как он нам не важен. И вот если в этой ситуации окажется, что результат метода тоже COM-объект, который мы не сохранили и соотв. не освободили явно - нас ждут проблемы.

Большой пример скрипта

В качестве реального примера скрипта, который написан по всем правилам освобождения COM-объектов я предлагаю рассмотреть код загрузки комплектов отчётности в формате Repx. Его можно найти на github .

И это всё?

К сожалению, не всё и есть более сложные ситуации связанные с подсчётом ссылок на COM-объекты, которые могут приводить к проблемам. Я не буду приводить их в статье, чтобы не запутать вас окончательно.

Вы можете присылать ([email protected]) мне примеры кода, когда вам так и не удалось добиться корректного освобождения COM-объектов, и я постараюсь вам помочь в меру своих сил.

А можно не заморачиваться?

Я согласен, что написание реального кода, в котором явно и в нужном порядке освобождаются все COM-объекты задача не из лёгких, так как способов "выстрелить себе в ногу" при этом предостаточно.

Вы можете писать код точно также, как будто он выполняется прямо в базе, и игнорировать код ошибки, который вам возвращает OneScript.

При такой стратегии я рекомендую процедуру ПриОкончанииРаботы переписать с достаточно большой паузой в конце - как показывает практика это несколько повышает шансы на то, что оставшиеся в памяти COM-объекты будут завершены без ошибок.

Вот этот код:

Процедура ПриОкончанииРаботы() Если v8 <> Неопределено Тогда Попытка ОсвободитьОбъект(v8) ; v8 = Неопределено ; Исключение КонецПопытки; КонецЕсли ; Если connector <> Неопределено Тогда Попытка ОсвободитьОбъект(connector) ; connector = Неопределено ; Исключение КонецПопытки; КонецЕсли ; Если updater <> Неопределено Тогда Попытка ОсвободитьОбъект(updater) ; updater = Неопределено ; Исключение КонецПопытки; КонецЕсли ; // Ожидание в конце выполнения программы // магическим образом помогает избежать // проблем с освобождением ресурсов, если // мы использовали внешнее подключение к // базе. Приостановить(10000 ) ; // 10 секунд Если errors Тогда ЗавершитьРаботу(1 ) ; КонецЕсли ; КонецПроцедуры

А есть ли альтернатива?

Есть альтернативный способ пакетного выполнения программного кода в базах.

Функции событий

Управление игровыми объектами (GameObjects) с помощью компонентов

В редакторе Unity вы изменяете свойства Компонента используя окно Inspector. Так, например, изменения позиции компонента Transform приведет к изменению позиции игрового объекта. Аналогично, вы можете изменить цвет материала компонента Renderer или массу твёрдого тела (RigidBody) с соответствующим влиянием на отображение или поведение игрового объекта. По большей части скрипты также изменяют свойства компонентов для управления игровыми объектами. Разница, однако, в том, что скрипт может изменять значение свойства постепенно со временем или по получению ввода от пользователя. За счет изменения, создания и уничтожения объектов в заданное время может быть реализован любой игровой процесс.

Обращение к компонентам

Наиболее простым и распространенным является случай, когда скрипту необходимо обратиться к другим компонентам, присоединенных к тому же GameObject. Как упоминалось во разделе Введение, компонент на самом деле является экземпляром класса, так что первым шагом будет получение ссылки на экземпляр компонента, с которым вы хотите работать. Это делается с помощью функции GetComponent . Типично, объект компонента сохраняют в переменную, это делается в C# посредством следующего синтаксиса:

(); }

В UnityScript синтаксис немного отличается:

Function Start () { var rb = GetComponent.(); }

Void Start () { Rigidbody rb = GetComponent(); // Change the mass of the object"s Rigidbody. rb.mass = 10f; }

Дополнительная возможность, недоступная в окне Inspector - вызов функций экземпляра компонента:

Void Start () { Rigidbody rb = GetComponent(); // Add a force to the Rigidbody. rb.AddForce(Vector3.up * 10f); }

Имейте ввиду, что нет причины, по которой вы не можете иметь больше одного пользовательского скрипта, присоединенного к одному и тому же объекту. Если вам нужно обратиться к одному скрипту из другого, вы можете использовать, как обычно, GetComponent, используя при этом имя класса скрипта (или имя файла), чтобы указать какой тип Компонента вам нужен.

Если вы попытаетесь извлечь Компонент, который не был добавлен к Игровому Объекту, тогда GetComponent вернет null; возникнет ошибка пустой ссылки при выполнении (null reference error at runtime), если вы попытаетесь изменить какие-либо значения у пустого объекта.

Обращение к другим объектам

Пусть иногда они и существуют изолированно, все же, обычно, скрипты отслеживают другие объекты. Например, преследующий враг должен знать позицию игрока. Unity предоставляет несколько путей получения других объектов, каждый подходит для конкретной ситуации.

Связывание объектов через переменные

Самый простой способ найти нужный игровой объект - добавить в скрипт переменную типа GameObject с уровнем доступа public:

Public class Enemy: MonoBehaviour { public GameObject player; // Other variables and functions... }

Переменная будет видна в окне Inspector, как и любые другие:

Теперь вы можете перетащить объект со сцены или из панели Hierarchy в эту переменную, чтобы назначить его. Функция GetComponent и доступ к переменным компонента доступны как для этого объекта, так и для других, то есть вы можете использовать следующий код:

Public class Enemy: MonoBehaviour { public GameObject player; void Start() { // Start the enemy ten units behind the player character. transform.position = player.transform.position - Vector3.forward * 10f; } }

Кроме того, если объявить переменную с доступом public и заданным типом компонента в вашем скрипте, вы сможете перетащить любой объект, который содержит присоединенный компонент такого типа. Это позволит обращаться к компоненту напрямую, а не через игровой объект.

Public Transform playerTransform;

Соединение объектов через переменные наиболее полезно, когда вы имеете дело с отдельными объектами, имеющими постоянную связь. Вы можете использовать массив для хранения связи с несколькими объектами одного типа, но связи все равно должны быть заданы в редакторе Unity, а не во время выполнения. Часто удобно находить объекты во время выполнения, и Unity предоставляет два основных способа сделать это, описанных ниже.

Нахождение дочерних объектов

Иногда игровая сцена может использовать несколько объектов одного типа, таких как враги, путевые точки и препятствия. Может возникнуть необходимость отслеживания их в определенном скрипте, который управляет или реагирует на них (например, все путевые точки могут потребоваться для скрипта поиска пути). Можно использовать переменные для связывания этих объектов, но это сделает процесс проектирования утомительным, если каждую новую путевую точку нужно будет перетащить в переменную в скрипте. Аналогично, при удалении путевой точки придется удалять ссылку на отсутствующий объект. В случаях, наподобие этого, чаще всего удобно управлять набором объектов, сделав их дочерними одного родительского объекта. Дочерние объекты могут быть получены, используя компонент Transform родителя (так как все игровые объекты неявно содержат Transform):

Using UnityEngine; public class WaypointManager: MonoBehaviour { public Transform waypoints; void Start() { waypoints = new Transform; int i = 0; foreach (Transform t in transform) { waypoints = t; } } }

Вы можете также найти заданный дочерний объект по имени, используя функцию