You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Сегодня поговорим о tween-анимациях и как их реализовать в рамках ecs. Рассматривать реализацию будем через фреймворк Actors для Unity, однако данную систему можно повторить в любом языке/движке. О
Что такое tween-анимация?
Tween-анимация позволяет анимировать любое свойство предмета и с помощью интерполяции рассчитывает промежуточные значения. Повторюсь, любое свойство: от позиции до смены цвета.
Такие анимации часто незаменимы при работах с UI, например для всплывающих окошек или индикаторов. Например как в Until We Die ( игра над которой наша команда сейчас трудится )
Описываем задачу
Нам понадобятся:
Функции интерполяции. Их достать легко в интернете. Есть прекрасный сайт с шпаргалками.
Компонент. Компонент будет хранить
Кол-во шагов. Это сколько раз анимация повторится. Полезно если мы хотим сделать мигающую лампочку например.
Время шага. Это как долго шаг будет длиться.
Ссылку на абстрактный класс TweenBase. Мы хотим иметь возможность анимировать любые свойства объекта а раз так нам потребуются вспомогательные классы которые будут хранить реализацию твина. Мы не будем использовать для этого делегаты, анонимные методы.
Процессор. Код отвечающий за обработку поступивших твинов.
Вспомогательные статик методы. Сахар который позволит нам быстро и красиво создавать новые tween-анимации.
Компонент
// тип интерполяцииpublicenumTween{Linear,Cubicin,Cubicout}publicclassComponentTween{publicfloatdir=1;// вспомогательный указатель в какую сторону движется tweenpublicintsteps=1;// кол-во шагов. -1 значит анимация бесконечнаpublicTweentype;// тип интерполяцииpublicfloattime_step;// время на шагpublicfloattime;// текущее времяpublicTweenBasesource;// источник анимации}staticpartialclassComponent{publicconststringTween="Game.Source.ComponentTween";publicstaticref ComponentTween componentTween(inthisent entity)=>refStorage<ComponentTween>.components[entity.id];}sealedclassStorageComponentTween:Storage<ComponentTween>{publicoverride ComponentTween Create()=>new ComponentTween();// Use for cleaning components that were removed at the current frame.publicoverridevoidDispose(indexesdisposed){foreach(var id in disposed){refvarcomponent=ref components[id];
component.steps =1;
component.time =0f;
component.source.Dispose();
component.source =null;}}}
Каждый раз когда мы хотим запустить новую анимацию мы будем создавать новую сущность и передавать ей компонент выше. Напишем простой метод расширения чтобы потом нам было легче жить. Это будет утилитарный метод и как пользователи мы вызывать его не будем.
Это абстрактный класс через который мы будем создавать все многообразие tween анимаций.
publicabstractclassTweenBase{// задержка перед запуском твинаpublicfloatdelay;// метод реализации твина// возвращаем bool чтобы иметь возможность оборвать твин в нештатной ситуацииpublicabstractboolHandle(floatstep);// чистимся если надоpublicabstractvoidDispose();// удобно выставляем задержкуpublic TweenBase setDelay(floatarg){delay=arg;returnthis;}}
ProcessorTween
Имея на руках все это безобразие мы можем приступить к обработке твинов в процессоре.
sealedclassProcessorTween:Processor<ComponentTween>,ITick{publicvoidTick(floatdelta){foreach(ent entity in source){varcTween= entity.componentTween();refvart=ref cTween.time;refvardir=ref cTween.dir;refvardelay=ref cTween.source.delay;refvarsteps=ref cTween.steps;// если шагов осталось 0 то убрать компонент tween, игнорируем выполнение кода на кадре.if(steps==0){
entity.Remove<ComponentTween>();continue;}// если задержка твина больше 0 то игнорируем выполнение кода на кадреif((delay-=delta)>0.0f)continue;// Умножая на dir мы указываем в каком направлении сдвигать время t+=delta/ cTween.time_step *dir;// Если направление 1 и время равно 1 то отнять шаг и сменить направлениеif(dir==1){if(t >= 1){--steps;dir *= -1;t=1;}}// если направление -1 и время равно 0 то отнять шаг и сменить направлениеelse{if(t <= 0){--steps;dir *= -1;t=0;}}// передать интерполяцию времени t в источник твина. Если твин вернул false то удалить компонент твина.if(!cTween.source.Handle(math.calculateTween(cTween.type, t,0,1)))
entity.Remove<ComponentTween>();}}}
Считаем интерполяцию
Формул гораздо больше и их нужно добавлять в этот метод.
Однако метода doColor у нас пока нет. Исправим это :)
Но прежде чем нам нужно создать "тело" анимации цвета. Для этого создаем класс TweenColor и наследуем его от TweenBase
publicclassTweenColor:TweenBase{// Наш спрайт рендерерpublicSpriteRendererrenderer;// начальный цветpublicColorval_from;// конечный цветpublicColorval_to;// step - это интерполированное время шага от 0 до 1publicoverrideboolHandle(floatstep){if(renderer==null)returnfalse;// Формула замены цвета
renderer.color =new Color(val_from.r +(val_to.r - val_from.r)*step, val_from.g +(val_to.g - val_from.g)*step, val_from.b +(val_to.b - val_from.b)*step, val_from.a +(val_to.a - val_from.a)*step);// Это тоже самое что и код выше// renderer.color = Color.Lerp(val_from, val_to, step);returntrue;}// Убиваем ссылку на спрайт рендерерpublicoverridevoidDispose()=>renderer=null;}
Теперь наконец делаем сахарный метод doColor();
Его можно будет вызвать как метод SpriteRenderer, дальше останется указать конечный цвет, время шага, кол-во шагов и тип анимации.
У нас получилось реализовать базовый tween-обработчик. Несмотря на его простоту он покрывает нужды большинства игр и легко расширяем. До написания своего tween-обработчика я пользовался замечательной библиотекой DoTweenPro ( как и большинство Unity разработчиков )
Однако жирным плюсом ECS является возможность без лишних усилий и зависимостей внедрить новый функционал в едином с проектом архитектурном стиле.
А как вы пишите tween анимации? Делитесь своими работами и примерами : )
The text was updated successfully, but these errors were encountered:
Сегодня поговорим о tween-анимациях и как их реализовать в рамках ecs. Рассматривать реализацию будем через фреймворк Actors для Unity, однако данную систему можно повторить в любом языке/движке. О
Что такое tween-анимация?
Tween-анимация позволяет анимировать любое свойство предмета и с помощью интерполяции рассчитывает промежуточные значения. Повторюсь, любое свойство: от позиции до смены цвета.
Такие анимации часто незаменимы при работах с UI, например для всплывающих окошек или индикаторов. Например как в Until We Die ( игра над которой наша команда сейчас трудится )
Описываем задачу
Нам понадобятся:
Компонент
Каждый раз когда мы хотим запустить новую анимацию мы будем создавать новую сущность и передавать ей компонент выше. Напишем простой метод расширения чтобы потом нам было легче жить. Это будет утилитарный метод и как пользователи мы вызывать его не будем.
TweenBase
Это абстрактный класс через который мы будем создавать все многообразие tween анимаций.
ProcessorTween
Имея на руках все это безобразие мы можем приступить к обработке твинов в процессоре.
Считаем интерполяцию
Формул гораздо больше и их нужно добавлять в этот метод.
Создаем первую анимацию
Итак, у нас почти все готово и сейчас мы сделаем что-то вроде анимации ниже:
Кубик ждет 1 секунду а после этого дважды мигает красным с интервалом в 0.1 сек.
Как пользователи мы используем следующее API:
Однако метода
doColor
у нас пока нет. Исправим это :)Но прежде чем нам нужно создать "тело" анимации цвета. Для этого создаем класс
TweenColor
и наследуем его отTweenBase
Теперь наконец делаем сахарный метод
doColor();
Его можно будет вызвать как метод SpriteRenderer, дальше останется указать конечный цвет, время шага, кол-во шагов и тип анимации.
Заключение
У нас получилось реализовать базовый tween-обработчик. Несмотря на его простоту он покрывает нужды большинства игр и легко расширяем. До написания своего tween-обработчика я пользовался замечательной библиотекой DoTweenPro ( как и большинство Unity разработчиков )
Однако жирным плюсом ECS является возможность без лишних усилий и зависимостей внедрить новый функционал в едином с проектом архитектурном стиле.
А как вы пишите tween анимации? Делитесь своими работами и примерами : )
The text was updated successfully, but these errors were encountered: