Пятница, 26 Апреля 2024, 18:02

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Форум игроделов » Движки для разработки игр и сложные системы разработки » Unity » Написание псевдоскрипта для быстрого скриптинга уровней.
Написание псевдоскрипта для быстрого скриптинга уровней.
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
Код
"1 + 25 * 2"
в математическое действие, чтобы это всё само посчиталось?
Либо придётся по старинке, парсером. Но вдруг есть халявный метод?


Сообщение отредактировал alexsilent - Пятница, 17 Апреля 2015, 16:22
MANMANAДата: Суббота, 18 Апреля 2015, 07:46 | Сообщение # 2
почти ветеран
Сейчас нет на сайте
Цитата alexsilent ()
2) Можно ли как-то превращать строку String

кхы, пока копался, нарыл вот такое http://www.blackbeltcoder.com/Article....aluator
функционал можно дописать самому, а главное выражения можно брать от пользователей smile
но все равно - это парсер


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 smile
как это было бы в играх жанра 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, спасибо большое! Интересная вещь. smile

Добавлено (20 апреля 2015, 10:10)
---------------------------------------------
Сделал первую версию ускоренного скриптера для уровней)
Не будет рекомпиляции после написания мини-кода, и вдобавок тот же самый код пишется быстрее в разы
и не будет проблем с небольшими уникальными кодами
(естественно, в скорости будет заметно проигрывать обычному коду,
но это будет подходить для уникальных событий, коих будет не мало, но и не так уж и много на одной локации):


Добавлено (20 апреля 2015, 10:13)
---------------------------------------------
Цитата beril ()
Тогда CSharpMessenger, если нет желания разбираться с делегатами и событиями.

beril, спасибо! smile


Сообщение отредактировал 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 короткая строка - максимум результата",
а в обычном скрипте я буду писать всё это очень долго, каждый раз забывая длинные фразы и поглядывая в документацию):

Ставишь студию и решарпер. И не нужно никуда подсматривать.
berilДата: Понедельник, 20 Апреля 2015, 15:34 | Сообщение # 10
Я не ленивый, я — энергосберегающий
Сейчас нет на сайте
LUA не пробовал ? biggrin
Ты получил ответы на свои вопросы? Или еще есть?




Накодил? Убери за собой!
Инвентарь в Unity(UI)
Инвентарь в Unity(GUI)
Форум игроделов » Движки для разработки игр и сложные системы разработки » Unity » Написание псевдоскрипта для быстрого скриптинга уровней.
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг