Написание псевдоскрипта для быстрого скриптинга уровней.
| |
alexsilent | Дата: Пятница, 17 Апреля 2015, 15:54 | Сообщение # 1 |
почти ветеран
Сейчас нет на сайте
| Приветствую друзья! Пишу псевдоскрипт, для быстрого написания мини скриптов, для меня очень удобно писать сокращённо, очень давно я придумал свой встроенный скрипт в Blitz Max, для скриптинга уровней, теперь хочу перенести его в Unity3d (ибо мой скрипт оптимизирован под "1 короткая строка - максимум результата", а в обычном скрипте я буду писать всё это очень долго, каждый раз забывая длинные фразы и поглядывая в документацию):
Код if collision player create obj1 100,100,0 send last Rename item talk hi1 talk hi2 delete end
И появились вопросы:
1) Появился пока барьер, который не могу обойти:
Нужно принять сообщение от SendMessage, оно может быть абсолютно любое, есть ли какие-то другие средства перехвата сообщения, кроме самого названия функции?
Либо придётся прописывать все возможные варианты принятия сообщений в виде функций, но это будет слегка тягомотно.
2) Можно ли как-то превращать строку String в математическое действие, чтобы это всё само посчиталось? Либо придётся по старинке, парсером. Но вдруг есть халявный метод?
Сообщение отредактировал alexsilent - Пятница, 17 Апреля 2015, 16:22 |
|
| |
MANMANA | Дата: Суббота, 18 Апреля 2015, 07:46 | Сообщение # 2 |
почти ветеран
Сейчас нет на сайте
| Цитата alexsilent ( ) 2) Можно ли как-то превращать строку String кхы, пока копался, нарыл вот такое http://www.blackbeltcoder.com/Article....aluator функционал можно дописать самому, а главное выражения можно брать от пользователей но все равно - это парсер
http://www.3dbuffer.com/ Текстуры, Unity3D, Blender: Эффекты, скрипты, моделирование, текстурирование, скульптинг VKонтакте 3Dbuffer
Последнее:
Новый раздел "Текстуры"
Как запатентовать, защитить техническое решение, игру, идею
|
|
| |
beril | Дата: Суббота, 18 Апреля 2015, 09:26 | Сообщение # 3 |
Я не ленивый, я — энергосберегающий
Сейчас нет на сайте
| Цитата MANMANA ( ) т SendMessage лучше бы ты не использовал часто этот метод и подобные ему
Накодил? Убери за собой! Инвентарь в Unity(UI) Инвентарь в Unity(GUI)
|
|
| |
alexsilent | Дата: Суббота, 18 Апреля 2015, 09:39 | Сообщение # 4 |
почти ветеран
Сейчас нет на сайте
| Цитата beril ( ) лучше бы ты не использовал часто этот метод и подобные ему дорогая операция? Просто у меня не стратегия (субъектов не много), я думаю сильно проблематично с этим не будет. Не так массивно у меня проводятся SendMessage как это было бы в играх жанра RTS Очень часто мне нужно именно SendMessage и BroadcastMessage, ибо я дизайнер, я не люблю много кода , много текста и много строк, из-за этого я и пишу этот псевдоскриптер, чтобы в будущем ограничить себя от большого кода, и мне нужна простая и универсальная передача данных, а не сложная. GetComponent сложная, статичная и не универсальная - чтобы передать данные из скрипта, надо во первых знать, как этот скрипт называется, (обязательно прописать название скрипта в качестве типа этой переменной принимающей скрипт), а что если я с разных скриптов передаю эту информацию? И тогда мне помогает SendMessage, чтобы не знать и не прописывать все варианты откуда эта информация может передаваться. А иногда нужно нескольким сразу поведениям на одном объекте принять один и тот же сигнал. Если б был ещё более простой и универсальный способ, я б им пользовался)
Мне нужно от кода минимум текста - максимум результата), даже если это дороже по затратам процессов.
PS В Юнити иногда требуется очень много писать, я каждый божий раз забываю даже избитую оскоминой фразу, как правильно писать: gameObject.SendMessage("Messsage",text, эту длинную фразу, которую я всегда забываю и ищу в документациях или копипаста) я о фразе SendMessageOptions.DontRequireReceiver (почему по дефолту не стоит эта опция?) Юнити совсем не способствует сокращению писанины, хотя бывают некоторые полезные упрощения, но фразы часто очень длинные и легко забываемые для дизайнеров, которые больше используют правое полушарие мозга и не всегда любят зубрёжку и логику.
Сообщение отредактировал alexsilent - Суббота, 18 Апреля 2015, 11:10 |
|
| |
beril | Дата: Суббота, 18 Апреля 2015, 09:50 | Сообщение # 5 |
Я не ленивый, я — энергосберегающий
Сейчас нет на сайте
| Что то типо того, если есть возможность избегай их (SendMessage, BroadcastMessage). Используй стандартные нетовские делегаты и события или можно, как вариант CSharpMessenger
Можешь почитать дискуссии по этому поводу на форуме unity. К примеру тут
Цитата So, on my (rather old) machine, a loop of 5000000 SendMessage calls, using an empty function, takes 9.872 seconds. A loop of 5000000 direct calls (using a cached GetComponent) takes .024 seconds. Обычно падение производительности если используес ПК не так критична, но вот под мобильные устройство очень сильно заметно
Цитата alexsilent ( ) Мне нужно от кода минимум текста - максимум результата), даже если это дороже по затратам процессов. Тогда CSharpMessenger, если нет желания разбираться с делегатами и событиями.
Накодил? Убери за собой! Инвентарь в Unity(UI) Инвентарь в Unity(GUI)
Сообщение отредактировал beril - Суббота, 18 Апреля 2015, 09:56 |
|
| |
alexsilent | Дата: Понедельник, 20 Апреля 2015, 10:13 | Сообщение # 6 |
почти ветеран
Сейчас нет на сайте
| Цитата MANMANA ( ) кхы, пока копался, нарыл вот такое http://www.blackbeltcoder.com/Article....aluator функционал можно дописать самому, а главное выражения можно брать от пользователей но все равно - это парсер MANMANA, спасибо большое! Интересная вещь.
Добавлено (20 апреля 2015, 10:10) --------------------------------------------- Сделал первую версию ускоренного скриптера для уровней) Не будет рекомпиляции после написания мини-кода, и вдобавок тот же самый код пишется быстрее в разы и не будет проблем с небольшими уникальными кодами (естественно, в скорости будет заметно проигрывать обычному коду, но это будет подходить для уникальных событий, коих будет не мало, но и не так уж и много на одной локации):
Добавлено (20 апреля 2015, 10:13) --------------------------------------------- Цитата beril ( ) Тогда CSharpMessenger, если нет желания разбираться с делегатами и событиями. beril, спасибо!
Сообщение отредактировал alexsilent - Понедельник, 20 Апреля 2015, 10:16 |
|
| |
MANMANA | Дата: Понедельник, 20 Апреля 2015, 12:09 | Сообщение # 7 |
почти ветеран
Сейчас нет на сайте
| на чем реализовал?
http://www.3dbuffer.com/ Текстуры, Unity3D, Blender: Эффекты, скрипты, моделирование, текстурирование, скульптинг VKонтакте 3Dbuffer
Последнее:
Новый раздел "Текстуры"
Как запатентовать, защитить техническое решение, игру, идею
|
|
| |
alexsilent | Дата: Понедельник, 20 Апреля 2015, 14:01 | Сообщение # 8 |
почти ветеран
Сейчас нет на сайте
| Цитата MANMANA ( ) на чем реализовал?
На ЯваСкрипт, конечно я не программист и получилось, как обычно г*код :3
Ещё switch не успел прикрутить к этой основе, не до конца наполнил скрипт.
Код #pragma strict
// загрузка уровней: резкая / плавная(игровая) // принимать и посылать мессаги // создавать объекты, двигать объекты, крутить их, ставить объекты в нужное место, удалять объекты // задержка скрипта для катсцены(пауза), delay // Global.Quake, Camera Fade Control, // контроль сутками и погодой (возможно) // контроль туманом и эмбинтом (возможно) // менять музыку, играть звук, играть анимацию // менять цвет и спрайт // управлять сторонними гейм-объектами // выводить сообщение игры
// особые переменные Global // присваивать переменные к гейм объекту // локальные и глобальные переменные в пределах скриптера для обмена между скриптерами // Global.Var
// проверка, удаление и запись квестов // проверка переменных Global.Var и других // проверка столкновения, проверка Fade Camera // проверка суток и погоды (возможно) // проверка использование вещи, проверка вещи в инвентаре(возможно) // проверка дистанции // проверять звук, анимацию
// генератор случайностей // abs // lerp lerpangle // vector3 ? // distance // sin cos time // clamp ? // int // sign
// switch (?) смогу ли реализовать?
@Multiline (15) var Code : String; // изначальный текст кода
// движение по строкам private var LastLine : int; // может стоит убрать или нет??
private var Text : Codes[]; // разобранный код
class Codes { var Word : String[]; }
private var CurrentLine : int; // текущая линия
private var LastCreatedObject : GameObject; // хранение последнего созданного объекта для каждого скрипта отдельно
// локальные переменные private var LocalInt : int[] = new int[10]; // библиотека объектов // слушатель // команды операторы
function Awake() { // инициализация локальных переменных
// взять код, парсить на линии Code = Code.Replace("\t", ""); // remove TAB char var words : String[] = Code.Split("\n"[0]); // создать массив слов Text = new Codes[words.length]; // парсить линии на слова, убирать пустые слова for (var num : int = 0; num < words.length; num++) { var words2 : String[] = words[num].Split(" "[0]); // парсить var newarr : Array = new Array (words2); // создать временный массив // проверка на пустые слова, и убирать их for (var a : int = newarr.length-1; a > 0-1; a--) { if ((newarr[a] as String) == "" || (newarr[a] as String) == null || (newarr[a] as String) == " ") { newarr.RemoveAt(a); } } // назад в свой массив Text[num] = new Codes(); // init Text[num].Word = newarr.ToBuiltin(String) as String[]; // debug log print("****** debug: "+num); var text : String; for (var num2 : int = 0; num2 < Text[num].Word.length; num2++) { text += Text[num].Word[num2]+"*"; } print(text); } }
function Update() { if (Global.Pause) return; ScriptReader(); }
function ScriptReader() { // читать скрипт от начала до конца if (Text.length == 0) return; // коррекция, если нет кода if (LastLine >= Text.length) {LastLine = 0;} // сначала
// читать for (CurrentLine = LastLine; CurrentLine < Text.length; CurrentLine++) { if (CurrentLine >= Text.length) return; // внезапный конец, коррекция при перемотке if end LastLine = CurrentLine+1; // последняя строка var check : String = ScriptCore(CurrentLine); // ядро скрипта, чтение оператора print("CurrentLine: "+CurrentLine+" Text "+Text[CurrentLine].Word[0]); switch (check) { case "stop": // внезапно остановить чтение скрипта LastLine = 0; return;break; default: break; } } LastLine = 0; // сброс строк }
// Конвертация слов в переменные int function GrabInt(name : String) : int { if (name == null) {return 0;} var words : String[] = name.Split("!"[0]); // Парсить слово switch (words[0]) { case "l": // возвращение локальной переменной внутри скрипта return LocalInt[System.Convert.ToInt32(words[1])]; default: return System.Convert.ToInt32(name); break; } }
// Конвертация слов в объекты function GrabObject(name : String) : GameObject { if (name == null) {return gameObject;} // этот объект по умолчанию, когда не понятно, что возвращать var words : String[] = name.Split("!"[0]); // Парсить слово switch (words[0]) { case "it": // этот объект return gameObject; default: // этот объект по умолчанию, когда не понятно, что возвращать return gameObject; break; } }
// Конвертация слов в вектор function GrabVector(name : String) : Vector3 { if (name == null) {return Vector3.zero;} // возвращение пустого вектора var words : String[] = name.Split("!"[0]); // Парсить слово switch (words[0]) { case "v": // свой вектор return Vector3(System.Convert.ToInt32(words[1]),System.Convert.ToInt32(words[2]),System.Convert.ToInt32(words[3])); case "t": case "trans": // возвращение позиции трансформа if (words.length > 1) { // если больше одного слова if (words[1] == "last" || words[1] == "l") {return LastCreatedObject.transform.position;} // возвращение позиции недавно созданного объекта } else { return transform.position; // возвращение позиции себя по умолчанию } break; default: return Vector3.zero; // возвращение пустого вектора break; } }
// If проверка function IfCore(WORD : String[]) : boolean { if (WORD[1] == null) {return false;} switch(WORD[1]) { // проверка второго слова после "If" case "": break; default: // остальные проверки, к примеру локальные переменные var words : String[] = WORD[1].Split("!"[0]); // Парсить второе слово switch (words[0]) { case "l": // проверка локальной переменной [if <A> {< > != ==} <B>] var loc : int = LocalInt[System.Convert.ToInt32(words[1])]; return (IfAction(loc,WORD[2],WORD[3])); // возвращать результат проверки } break; } }
function IfAction(A : int, B : String, B2 : String) { // if (A) (B < > = >= <=) <B2> var C : int = GrabInt(B2);
switch(B) { case "=": case "==": if (A == C) {return true;} break; case "<": if (A < C) {return true;} break; case ">": if (A > C) {return true;} break; case "<=": if (A <= C) {return true;} break; case ">=": if (A >= C) {return true;} break; case "!=": if (A != C) {return true;} break; } return false; }
// Математические операции function MathAction(A : float,WORD : String[]) : int { // {A} {=+-*/} {B} ( {+-*/} {C} ) var B : float = GrabInt(WORD[2]); var C : float = GrabInt(WORD[4]); switch (WORD[1]+WORD[3]) { case "=": return B;break; // A = B
case "=+": return B+C; break; // A = B + C case "=-": return B-C; break; // A = B - C case "=*": return B*C; break; // A = B * C case "=/": return B/C; break; // A = B / C
case "+": return A+B; break; // A += B case "-": return A-B; break; // A -= B case "*": return A*B; break; // A *= B case "/": return A/B; break; // A /= B
default: return B; break; // A = B } }
// Ядро движка скриптов function ScriptCore(num : int) : String { if (Text[num].Word.length == 0) return; // коррекция if (Text[num].Word[0].Substring(0,1) == "/") return ""; // комментарий пропускаем
var ifnum : int = 0; var a : int;
var WORD : String[] = new String[7]; if (Text[num].Word.length > 0) WORD[0] = Text[num].Word[0]; if (Text[num].Word.length > 1) WORD[1] = Text[num].Word[1]; if (Text[num].Word.length > 2) WORD[2] = Text[num].Word[2]; if (Text[num].Word.length > 3) WORD[3] = Text[num].Word[3]; if (Text[num].Word.length > 4) WORD[4] = Text[num].Word[4];
switch(WORD[0]) { case "print": // принт для отладки if (WORD[2]) { print(""+WORD[1]+" "+GrabInt(WORD[2])); } else { print(""+WORD[1]); } break;
/*case "switch": // switch [switch <GrabInt>] Switcher = GrabInt(WORD[1]); break; case "case": // case [case <name$/num$>] if (Switcher != GrabInt) break; case "def": case "default": // default case if () break;*/
case "if": // оператор если if (IfCore(WORD)) { // читать дальше скрипт, потому-что выполнено условие print("IfCore() "+num); } else { print("else: "+num); // искать конец ветви, потому-что не выполнено условие ifnum = 0; for (a = num+1; a < Text.length; a++) { // пройти по всему скрипту от текущего места, в поисках конца условия if (Text[a].Word.length > 0) { // если в строке есть хоть одно слово if (Text[a].Word[0] == "if") {ifnum++;} // новое условие, углубиться дальше if (Text[a].Word[0] == "get") {ifnum++;} // новое условие, углубиться дальше if (Text[a].Word[0] == "switch") {ifnum++;} // свитч if (Text[a].Word[0] == "end") {ifnum--;} // вслпыть с условия
if (Text[a].Word[0] == "else" && ifnum == 0) { // else условие CurrentLine=a;return "ok"; // найден конец ветви else }
if (ifnum < 0) {CurrentLine=a;return "ok";} // найден конец ветви } } return "stop"; } break; case "else": // оператор иначе // искать конец ветви для Else т.е. искать свой END ifnum = 0; for (a = num+1; a < Text.length; a++) { // пройти по всему скрипту от текущего места, в поисках конца условия if (Text[a].Word.length > 0) { // если в строке есть хоть одно слово if (Text[a].Word[0] == "if") {ifnum++;} // новое условие, углубиться дальше if (Text[a].Word[0] == "get") {ifnum++;} // новое условие, углубиться дальше if (Text[a].Word[0] == "switch") {ifnum++;} // свитч if (Text[a].Word[0] == "end") {ifnum--;} // вслпыть с условия
if (ifnum < 0) {CurrentLine=a; return "ok";} // найден конец ветви } } return "stop"; break; // конец if get switch etc case "end": // end if / end get / etc break;
// остановить скрипт case "stop": // [stop] stop the script return "stop"; break; // отключить (удалить) скрипт до перегрузки уровня[off] case "off": Destroy(this); return "stop"; break; // задержка скрипта для катсцены(пауза), case "delay": // delay [] // взять время, и потом проверять время в Update // ????????????????????????????????????? break;
// загрузка уровней: резкая / плавная(игровая) case "load": // load level [load <name$> <id$>] Global.LoadLEVEL(WORD[1],WORD[2]); break; // принимать и посылать мессаги case "send": // send message [send <game object> <name$> <mode$>] GrabObject(WORD[1]).SendMessage(WORD[2],WORD[3],SendMessageOptions.DontRequireReceiver); break;
// создавать объекты, двигать объекты, крутить их, ставить объекты в нужное место, удалять объекты case "create": // [create <game object> <position>] LastCreatedObject = Instantiate(GrabObject(WORD[1]),GrabVector(WORD[2]),Quaternion.identity); break; case "pos": case "position":// изменять позицию объекта [pos <GO> <position>] GrabObject(WORD[1]).transform.position = GrabVector(WORD[2]); break; case "locPos": // изменять локальную позицию объекта [locPos <GO> <position>] GrabObject(WORD[1]).transform.localPosition = GrabVector(WORD[2]); break; // Global.Quake, Camera Fade Control case "ang": case "angle": // set angle [ang <GO> <vector>] GrabObject(WORD[1]).transform.eulerAngles = GrabVector(WORD[2]); break; case "locAng":// local angle [locAng <GO> <vector>] GrabObject(WORD[1]).transform.localEulerAngles = GrabVector(WORD[2]); break; // удалить объект case "delete": // [delete <game object>] delete object Destroy(GrabObject(WORD[1])); return "stop"; break; // контроль сутками и погодой (возможно) // контроль туманом и эмбинтом (возможно) // менять музыку, играть звук, играть анимацию // менять цвет и спрайт // управлять сторонними гейм-объектами // выводить сообщение игры default: // различные действия присвоения var words : String[] = WORD[0].Split("!"[0]); // Парсить первое слово switch (words[0]) { case "l": // [l.2 = <A> <+ - * /> <B>] var loc : int = System.Convert.ToInt32(words[1]); var nn : int = MathAction(LocalInt[loc],WORD); LocalInt[loc] = nn; // математические операции break; default: // ??????? break; } break; } }
Сообщение отредактировал alexsilent - Понедельник, 20 Апреля 2015, 14:29 |
|
| |
Storm54 | Дата: Понедельник, 20 Апреля 2015, 14:54 | Сообщение # 9 |
постоянный участник
Сейчас нет на сайте
| Цитата alexsilent ( ) Приветствую друзья! Пишу псевдоскрипт, для быстрого написания мини скриптов, для меня очень удобно писать сокращённо, очень давно я придумал свой встроенный скрипт в Blitz Max, для скриптинга уровней, теперь хочу перенести его в Unity3d (ибо мой скрипт оптимизирован под "1 короткая строка - максимум результата", а в обычном скрипте я буду писать всё это очень долго, каждый раз забывая длинные фразы и поглядывая в документацию): Ставишь студию и решарпер. И не нужно никуда подсматривать.
|
|
| | |
|