Затухающее колебание переменной (Damped Oscillation)

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

Затухающее колебание переменной (Damped Oscillation)

Сообщение AM-Games 27 июн 2013, 20:47

Делал красивое меню и решил поделиться одним достаточно универсальным скриптом. Даже график в паинте описал :D
Принцип:
График функции

Ось абсцисс (х) - время; ось ординат (у) - значение переменной oscillatingVar.
Единственное отличие графика от скрипта в том, что график начинается в точке (0;0), а скрипт стартует с точки (0;amplitude), что странно, потому что и для графика, и для скрипта я использовал одну и ту же функцию.

Синтаксис:
Используется javascript
#pragma strict                          //прагма стрикт

var amplitude : float = 10f;    //Амплитуда. Модуль максимального отклонения тела от положения равновесия. Чем больше амплитуда, тем сильнее будет изменятся переменная.
var decay : float = 1f;         //Коэффициент затухания. Чем больше коэффициент, тем быстрее затухнут колебания.
var frequence : float = 2f;             //Частота колебания. Чем больше частота колебания, тем чаще колеблется, кто бы мог подумать только. На графике частота равна трём (3).
@HideInInspector
var oscillatingVar : float;             //Собственно, сама переменная, которую мы будем менять. Просто приравниваете то, что хотите колебать, к этой переменной.
var minVelocity : float;                //Минимальная допустимая разница между двумя кадрами. Это первый параметр (ниже второй), который не даёт циклу быть бесконечным. Не рекомендуется ставить ноль.
var maxMVTimes : int;           //Максимальное количество регистрации разницы меньше minVelocity. Чем больше число, тем меньше шанс, что колебания остановятся до значительного затухания, например, на пиках колебаний (самая верхняя граница по модулю).
@HideInInspector
var mvt : int;                          //Счетчик регистраций разницы меньше minVelocity


function Start () {
        Oscillation();                                  //При старте сцены сразу начнется колебание переменной. Уберите это ваще: оно тут только для проверки.
}

function Update () {
                                                                //Тут можно что-нибудь приравнять к переменной.
}

function Oscillation(){                                         //Один раз вызываем функцию. Не надо её в апдейт пихать.
        var startTime = Time.time;                              //Регистрируем время вызова функции.
        var t : float;                                                  //Переменная для оси абсцисс.
        for(;;){                                                                //Бесконечный цикл, разрыв внутри.
                yield WaitForEndOfFrame;                                //Ждём. Иначе не работает ничего.
                var z = oscillatingVar;                                 //Переменная для расчета разницы между значениями в двух соседних кадрах.
                t = Time.time - startTime;                              //Измеряем время между "вот прямо сейчас" и началом функции.
                oscillatingVar = amplitude * Mathf.Sin(t * frequence * Mathf.PI * 2) / Mathf.Exp(t * decay);                   //Самая главная часть скрипта. Сама функция, по которой и построен график.
                Debug.Log(oscillatingVar);                              //Тут можно посмотреть за значениями переменной. Уберите это.
                if(Mathf.Abs(oscillatingVar - z) < minVelocity && mvt > maxMVTimes){                              //Тут, в зависимости от количества регистраций разницы между двумя кадрами меньше minVelocity, разрывается цикл.
                        break;
                }else{if(Mathf.Abs(oscillatingVar - z) < minVelocity){mvt++;}}
        }
}

Ну, в принципе, это все. Приму любой совет по оптимизации, ибо жрет немало. Использовать скрипт можно вообще везде. Маятники, пружины, качели. Я это написал для гуя.
Демо, управление цифрами 1-4 на клаве:
HTML код для вашего блога :
Код: Выделить всё
<script language='javascript' type="text/javascript"> document.write("<iframe marginheight='0' src='http://unity3d.ru/distribution/player.php?url=https://dl.dropbox.com/s/3rea7mstxq0lzkx/DemoOscillation.unity3d?dl=1&w=600&h=400&t=false&preview=1' height='"+(400+30)+"' width='600' frameborder='0' scrolling='no'></iframe>"); </script>
У вас нет доступа для просмотра вложений в этом сообщении.
Последний раз редактировалось AM-Games 30 июн 2013, 14:23, всего редактировалось 2 раз(а).
AM-Games
UNIт
 
Сообщения: 139
Зарегистрирован: 21 окт 2012, 11:30

Re: Затухающее колебание переменной (Damped Oscillation)

Сообщение Макс 27 июн 2013, 21:00

Неплохо!
Но совет, применить Mathf.PingPong()
наверняка получится сделать проще, и с более простыми вычислениями.
Макс
UNIверсал
 
Сообщения: 372
Зарегистрирован: 20 июн 2013, 23:05

Re: Затухающее колебание переменной (Damped Oscillation)

Сообщение AM-Games 27 июн 2013, 21:15

Макс писал(а):Неплохо!
Но совет, применить Mathf.PingPong()
наверняка получится сделать проще, и с более простыми вычислениями.

Ууууу. Нет. PingPong на графике выглядел бы зигзагами, а в моём скрипте всё плавно, и сами колебания, и затухание.
AM-Games
UNIт
 
Сообщения: 139
Зарегистрирован: 21 окт 2012, 11:30

Re: Затухающее колебание переменной (Damped Oscillation)

Сообщение Макс 27 июн 2013, 21:23

Макс писал(а):Неплохо!
Но совет, применить Mathf.PingPong()
наверняка получится сделать проще, и с более простыми вычислениями.


да блин... пинг-понг создаёт колебания в рамках от первого параметра до второго.
Это и будут колебания по оси Y.
А ось x = это время. Остаётся только подобрать скорость движения по оси x, и задать небольшую формулу, постоянно изменяющую оба входных параметра пинг-понг, с течением времени.
В принципе можно получить любые линейные или нелинейные огибающие.
Макс
UNIверсал
 
Сообщения: 372
Зарегистрирован: 20 июн 2013, 23:05

Re: Затухающее колебание переменной (Damped Oscillation)

Сообщение Neodrop 27 июн 2013, 23:34

А может демкой подкрепить ? :-?
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8426
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: Затухающее колебание переменной (Damped Oscillation)

Сообщение AM-Games 28 июн 2013, 01:44

Neodrop писал(а):А может демкой подкрепить ? :-?

Вот я думал об этом. Но не придумал, что в эту демку отправить. Шатающийся куб, GUI, просто число или ешё чего.
AM-Games
UNIт
 
Сообщения: 139
Зарегистрирован: 21 окт 2012, 11:30

Re: Затухающее колебание переменной (Damped Oscillation)

Сообщение nile 28 июн 2013, 09:14

Куб с текстурной пружиной было бы достаточно наглядно, я считаю, аля динамометр + реалтайм график.
Camera control by FreeTrackIR: FreeTrackIR + Unity3d
Аватара пользователя
nile
Старожил
 
Сообщения: 847
Зарегистрирован: 25 фев 2011, 17:17
Skype: dennis.sadovsky

Re: Затухающее колебание переменной (Damped Oscillation)

Сообщение Макс 28 июн 2013, 09:59

Neodrop писал(а):А может демкой подкрепить ? :-?

Попробую на пинг-понге сделать демку. вчера поэксперементировал - очень интересные результаты получаются. Вот только каким макаром в юньке график чертить? не из объектов же ))
Макс
UNIверсал
 
Сообщения: 372
Зарегистрирован: 20 июн 2013, 23:05

Re: Затухающее колебание переменной (Damped Oscillation)

Сообщение Acrobat 28 июн 2013, 11:02

Почему бы Вам не засунуть тело Вашей функциии в Update, дополнительно убрав из тела for(;;) и Waitfoendofframe? Че то мне кажется работать будет.
Acrobat
UNITрон
 
Сообщения: 182
Зарегистрирован: 08 дек 2011, 16:16
Откуда: г. Нижний Новгород

Re: Затухающее колебание переменной (Damped Oscillation)

Сообщение nile 28 июн 2013, 11:17

Макс писал(а): Вот только каким макаром в юньке график чертить? не из объектов же ))


http://catlikecoding.com/unity/tutorials/graphs/
http://docs.unity3d.com/Documentation/C ... derer.html


Но лучшее, что я видел, реализация графиков сцепления в Edy's vechicle physics
Изображение
Вот скрипты оттуда:
GUICanvas (отрисовка)
Синтаксис:
Используется javascript
//========================================================================================================================
// Edy Vehicle Physics - (c) Angel Garcia "Edy" - Oviedo, Spain
// Live demo: http://www.edy.es/unity/offroader.html
//
// Terms & Conditions:
//  - Use for unlimited time, any number of projects, royalty-free.
//  - Keep the copyright notices on top of the source files.
//  - Resale or redistribute as anything except a final product to the end user (asset / library / engine / middleware / etc.) is not allowed.
//  - Put me (Angel Garcia "Edy") in your game's credits as author of the vehicle physics.
//
// Bug reports, improvements to the code, suggestions on further developments, etc are always welcome.
// Unity forum user: Edy
//========================================================================================================================
//
// GUICanvas
//
// Standalone class (not derived from MonoBehavior) for common GUI drawing operations.
//
//========================================================================================================================


class GUICanvas
        {
        private var m_texture : Texture2D;
        private var m_pixelsWd : float;
        private var m_pixelsHt : float;
        private var m_canvasWd : float;
        private var m_canvasHt : float;
        private var m_scaleX : float;
        private var m_scaleY : float;
       
        private var m_moveX : float;
        private var m_moveY : float;
       
        private var m_pixels : Color[];
        private var m_buffer : Color[];
       
        private var m_alpha = -1.0;
        private var m_changed = false;
       
        // Constructor e información
       
        function GUICanvas (PixelsWd, PixelsHt : int, CanvasWd, CanvasHt : float)
                {
                m_texture = new Texture2D(PixelsWd, PixelsHt, TextureFormat.ARGB32, false);
                m_scaleX = (PixelsWd*1.0)/CanvasWd;             // Pasar los ints a float antes de hacer la division
                m_scaleY = (PixelsHt*1.0)/CanvasHt;
                m_pixelsWd = PixelsWd;
                m_pixelsHt = PixelsHt;
                m_canvasWd = CanvasWd;
                m_canvasHt = CanvasHt;
               
                m_moveX = 0.0;
                m_moveY = 0.0;
               
                m_pixels = new Color[PixelsWd * PixelsHt];
                }
               
        function CanvasWidth () : float { return m_canvasWd; }
        function CanvasHeight () : float { return m_canvasHt; }
        function PixelsWidth () : float { return m_pixelsWd; }
        function PixelsHeight () : float { return m_pixelsHt; }
        function ScaleX () : float      { return m_scaleX; }
        function ScaleY () : float      { return m_scaleY; }
               
        // Establecer automáticamente la transparencia. Indicar -1 para que se use siempre la del color indicado.
       
        function SetAlpha (alpha : float)
                {
                m_alpha = alpha;
                }
               
        // Dibujar Lineas
       
        function Line (x0, y0, x1, y1 : float, col : Color)
                {
                MoveTo(x0, y0);
                LineTo(x1, y1, col);
                }
               
        function MoveTo (x0, y0 : float)
                {
                m_moveX = x0;
                m_moveY = y0;
                }
               
        function LineTo (xn, yn : float, col : Color)
                {
                if (m_alpha >= 0) col.a = m_alpha;
               
                var x0 = m_moveX;
                var y0 = m_moveY;
                var x1 = xn;
                var y1 = yn;
               
                m_moveX = xn;
                m_moveY = yn;          
               
                // Asegurar que x0 <= x1. Así organizamos mejor el crop.
               
                if (x0 > x1)
                        {
                        var tmp = x0; x0 = x1; x1 = tmp;
                        tmp = y0; y0 = y1; y1 = tmp;
                        }
                       
                // Cropear por izquierda y derecha
               
                var sl = (y1-y0)/(x1-x0);
               
                if (x0 < 0.0) { y0 = y0 - x0 * sl; x0 = 0.0; }
                if (x1 > m_canvasWd) { y1 = y1 - (x1-m_canvasWd) * sl; x1 = m_canvasWd; }
               
                // Ya podemos descartar las lineas que no cruzarán el cuadro
                       
                if (x0 > m_canvasWd || x1 < 0.0 ||
                        (y0 < 0.0 && y1 < 0.0) || (y0 > m_canvasHt && y1 > m_canvasHt))
                        return;
                       
                // Si llega aquí la linea cruza el cuadro necesariamente.
                // Ajustar las coordenadas "Y" que pudieran estar fuera.
               
                if (y0 < 0.0) { x0 = x0 - y0 * sl; y0 = 0.0; }
                if (y0 > m_canvasHt) { x0 = x0 - (y0-m_canvasHt) / sl; y0 = m_canvasHt; }

                if (y1 < 0.0) { x1 = x1 - y1 * sl; y1 = 0.0; }
                if (y1 > m_canvasHt) { x1 = x1 - (y1-m_canvasHt) / sl; y1 = m_canvasHt; }

                // Dibujar la linea

                TexLine(m_texture, x0*m_scaleX, y0*m_scaleY, x1*m_scaleX, y1*m_scaleY, col);
                m_changed = true;
                }
       
        // Lineas con Vector2
               
        function Line (P0, P1 : Vector2, col : Color)
                {
                MoveTo(P0.x, P0.y);
                LineTo(P1.x, P1.y, col);
                }
               
        function MoveTo (P0 : Vector2)
                {
                MoveTo(P0.x, P0.y);
                }
               
        function LineTo (P1 : Vector2, col : Color)
                {
                LineTo(P1.x, P1.y, col);
                }

        // Lineas horizontales / verticales
       
        function LineX (y : float, col : Color)
                {
                Line (0, y, m_canvasWd, y, col);
                }
               
        function LineY (x : float, col : Color)
                {
                Line (x, 0, x, m_canvasHt, col);
                }
               
        // Dibujar círculo. El radio se mide en la escala X.
       
        function Circle (x, y, radius : float, col : Color)
                {
                if (m_alpha >= 0) col.a = m_alpha;
                TexCircle(m_texture, x*m_scaleX, y*m_scaleY, radius*m_scaleX, col);
                m_changed = true;
                }
               
        // Rellenar bloques
       
        function Clear (col : Color)
                {
                var count = m_pixelsWd * m_pixelsHt;
               
                if (m_alpha >= 0) col.a = m_alpha;
                for (var i=0; i<count; i++)
                        m_pixels[i] = col;
                       
                m_texture.SetPixels(m_pixels);
                m_changed = true;
                }
               
        function Fill (x, y, width, height : float, col : Color)
                {
                var xi : int = x*m_scaleX;
                var yi : int = y*m_scaleY;
                var wdi : int = width*m_scaleX;
                var hti : int = height*m_scaleY;

                var count = wdi * hti;
               
                if (m_alpha >= 0) col.a = m_alpha;
                for (var i=0; i<count; i++)
                        m_pixels[i] = col;
                       
                m_texture.SetPixels(xi, yi, wdi, hti, m_pixels);
                m_changed = true;
                }
               
        // Dibujar spline
       
        function SpLine (P0, T0, P1, T1 : Vector2, col : Color)
                {
                var Steps = 20;
               
                var s : float;
                var s2 : float;
                var s3 : float;
                var h1 : float;
                var h2 : float;
                var h3 : float;
                var h4 : float;
                var P : Vector2;
               
                MoveTo(P0);
                for (var t=0; t<=Steps; t++)
                        {
                        s = t;
                        s /= Steps;
                        s2 = s*s;
                        s3 = s2*s;
                       
                        // Valores de las funciones de Hermite
                       
                        h1 =  2*s3 - 3*s2 + 1;
                        h2 = -2*s3 + 3*s2;
                        h3 =    s3 - 2*s2 + s;
                        h4 =    s3 - s2;
                       
                        /* Estas son las ecuaciones para curvas de Bezier - yo no he notado absolutamente ninguna diferencia.
                        h1 =   -s3 + 3*s2 - 3*s + 1;
                        h2 =  3*s3 - 6*s2 + 3*s;
                        h3 = -3*s3 + 3*s2;
                        h4 =    s3;
                        */

                       
                        // Punto interpolado
                       
                        P = h1*P0 + h2*P1 + h3*T0 + h4*T1;
                        LineTo(P, col);
                        }
                }
                       
        // Especializadas
        // -----------------------------------------------------------

        // Dibujar una rejilla a intervalos dados
       
        function Grid (stepX, stepY : float, col : Color)
                {
                var f : float;
               
                for (f=0.0; f<=m_canvasWd; f+=stepX) LineY(f, col);
                for (f=0.0; f<=m_canvasHt; f+=stepY) LineX(f, col);
                }

       
        // Dibujar una curva de fricción de WheelCollider
       
        function FrictionCurve (Slip0, Value0, Slip1, Value1, Slope : float, col : Color)
                {
                var P0 = new Vector2(Slip0, Value0);
                var P1 = new Vector2(Slip1, Value1);
                var sl0 = Value0/Slip0;
                var sl1 = Value1/Slip1;
               
                SpLine(Vector2.zero, Vector2(Slip0, 0), P0, P0, col);          
                SpLine(P0,
                                Vector2(Slip1-Slip0, sl0*Slip1 - Value0) * (1 + (Slip1-Slip0) / (Slip1-Slip0+1)) * CarWheelFriction.MCt0,
                                P1,
                                Vector2(Slip1-Slip0, 0) * CarWheelFriction.MCt1,                       
                                col);
                Line(Slip1, Value1, m_canvasWd, Value1 + (m_canvasWd-Slip1)*Slope, col);
                }
               
        // Dibujar una curva progresiva (Bias) entre dos puntos con el coeficiente dado
       
        function BiasCurve (P0, P1 : Vector2, bias : float, col : Color)
                {
                var Steps = 20;
               
                var s : float;
                var c : float;
               
                var dX = P1.x - P0.x;
                var dY = P1.y - P0.y;
               
                MoveTo(P0);
                for (var t=0; t<=Steps; t++)
                        {
                        s = t;
                        s /= Steps;                    
                        c = Bias(s, bias);
                       
                        LineTo(P0.x + dX*s, P0.y + dY*c, col);
                        }
                }
               
       
        // Gráfica de lineas con los valores dados.
        // - Para una sola gráfica Values debe llevar pares consecutivos X,Y con ValueSize=2
        // - Para varias gráficas indicar valores consecutivos X,Y1,Y2,Y3..Yn con ValueSize=n+1
        //   Se dibujarán las gráficas (X,Y1), (X,Y2), (X,Y3) .. (X,Yn)
       
        private var COLORS = [Color.green, Color.yellow, Color.cyan, Color.magenta, Color.white, Color.blue, Color.red, Color.gray];
       
        function LineGraph (Values : Array, ValueSize : int)
                {
                var X : float;
                var Y : float;
               
                if (ValueSize < 2) return;
                if (Values.Count < 2*ValueSize) return;

                for (var i=1; i<ValueSize; i++)
                        {
                        MoveTo(Values[0], Values[i]);
                       
                        for (var v=1; v<Values.Count/ValueSize; v++)
                                LineTo(Values[v*ValueSize], Values[v*ValueSize + i], COLORS[(i-1) % 8]);
                        }
                }
       
        // Guardar / Restaurar
        // -----------------------------------------------------------

        function Save ()
                {
                m_buffer = m_texture.GetPixels();
                }
               
        function Restore ()
                {
                if (m_buffer)
                        {
                        m_texture.SetPixels(m_buffer);
                        m_changed = true;
                        }
                }
       
        // Dibujar en el GUI. Invocar sólo desde función OnGUI
        // -----------------------------------------------------------
       
        function ApplyChanges()
                {
                if (m_changed)
                        {
                        m_texture.Apply(false);
                        m_changed = false;
                        }
                }
       
        function GUIDraw (posX, posY : int)
                {
                ApplyChanges();
                GUI.DrawTexture(Rect(posX, posY, m_pixelsWd, m_pixelsHt), m_texture);
                }
               
        function GUIStretchDraw(posX, posY, width, height : int)
                {
                ApplyChanges();
                GUI.DrawTexture(Rect(posX, posY, width, height), m_texture);
                }
        }


// ----------- función de curva progresiva (Bias)

private var m_lastExponent = 0.0;
private var m_lastBias = -1.0;

private function BiasRaw(x : float, fBias : float) : float
        {
        if (x <= 0.0) return 0.0;
        if (x >= 1.0) return 1.0;

        if (fBias != m_lastBias)
                {
                if (fBias <= 0.0) return x >= 1.0? 1.0 : 0.0;
                else if (fBias >= 1.0) return x > 0.0? 1.0 : 0.0;
                else if (fBias == 0.5) return x;

                m_lastExponent = Mathf.Log(fBias) * -1.4427;
                m_lastBias = fBias;
                }

        return Mathf.Pow(x, m_lastExponent);
        }

       
// Bias simétrico usando sólo la curva inferior (fBias < 0.5)
// Admite rango -1, 1 aplicando efecto simétrico desde 0 hacia +1 y -1.

private function Bias(x : float, fBias : float) : float
        {
        var fResult : float;
               
        fResult = fBias <= 0.5? BiasRaw(Mathf.Abs(x), fBias) : 1.0 - BiasRaw(1.0 - Mathf.Abs(x), 1.0 - fBias);
       
        return x<0.0? -fResult : fResult;
        }

       

// ----------- funciones de UnifyWiki  
       
private function TexLine (tex : Texture2D, x0 : int, y0 : int, x1 : int, y1 : int, col : Color) {
    var dy = y1-y0;
    var dx = x1-x0;
   
    if (dy < 0) {dy = -dy; var stepy = -1;}
    else {stepy = 1;}
    if (dx < 0) {dx = -dx; var stepx = -1;}
    else {stepx = 1;}
    dy <<= 1;
    dx <<= 1;
       
    tex.SetPixel(x0, y0, col);
    if (dx > dy) {
        var fraction = dy - (dx >> 1);
        while (x0 != x1) {
            if (fraction >= 0) {
                y0 += stepy;
                fraction -= dx;
            }
            x0 += stepx;
            fraction += dy;
            tex.SetPixel(x0, y0, col);
        }
    }
    else {
        fraction = dx - (dy >> 1);
        while (y0 != y1) {
            if (fraction >= 0) {
                x0 += stepx;
                fraction -= dy;
            }
            y0 += stepy;
            fraction += dx;
            tex.SetPixel(x0, y0, col);
        }
    }
}


private function TexCircle (tex : Texture2D, cx : int, cy : int, r : int, col : Color) {
    var y = r;
    var d = 1/4 - r;
    var end = Mathf.Ceil(r/Mathf.Sqrt(2));
   
    for (x = 0; x <= end; x++) {
        tex.SetPixel(cx+x, cy+y, col);
        tex.SetPixel(cx+x, cy-y, col);
        tex.SetPixel(cx-x, cy+y, col);
        tex.SetPixel(cx-x, cy-y, col);
        tex.SetPixel(cx+y, cy+x, col);
        tex.SetPixel(cx-y, cy+x, col);
        tex.SetPixel(cx+y, cy-x, col);
        tex.SetPixel(cx-y, cy-x, col);
       
        d += 2*x+1;
        if (d > 0) {
            d += 2 - 2*y--;
        }
    }
}


CarTelemetry (использование)
Синтаксис:
Используется javascript
//========================================================================================================================
// Edy Vehicle Physics - (c) Angel Garcia "Edy" - Oviedo, Spain
// Live demo: http://www.edy.es/unity/offroader.html
//
// Terms & Conditions:
//  - Use for unlimited time, any number of projects, royalty-free.
//  - Keep the copyright notices on top of the source files.
//  - Resale or redistribute as anything except a final product to the end user (asset / library / engine / middleware / etc.) is not allowed.
//  - Put me (Angel Garcia "Edy") in your game's credits as author of the vehicle physics.
//
// Bug reports, improvements to the code, suggestions on further developments, etc are always welcome.
// Unity forum user: Edy
//========================================================================================================================
//
// CarTelemetry
//
// Realtime display with all the information available from the internal components.
// Also shows the graphic tire telemetry (realtime friction curves) and the debugging gizmos (force lines).
//
//========================================================================================================================

var Target : CarControl;
var Enabled : boolean;
var Gizmos : boolean;
var Velocity : boolean;
var Curves : boolean;

var m_Style = new GUIStyle();


private var SizeX = 160;
private var SizeY = 64;

private var m_graphF : GUICanvas;
private var m_graphS : GUICanvas;

private var m_graphStabF : GUICanvas;
private var m_graphStabR : GUICanvas;

private var m_graphSpring : GUICanvas;

private var m_graphBar0 : GUICanvas;
private var m_graphBar1 : GUICanvas;
private var m_graphBar2 : GUICanvas;


function Start ()
        {
        // Preparar los gráficos de las curvas de fricción
       
        m_graphF = new GUICanvas(SizeX, SizeY, 10, 10);
        m_graphS = new GUICanvas(SizeX, SizeY, 10, 25);
        m_graphF.SetAlpha(0.5);
        m_graphS.SetAlpha(0.5);

        m_graphF.Clear(Color.black);
        m_graphF.Grid(1, 2, Color(0,0.2,0));
        for (i=10; i<m_graphF.CanvasHeight(); i+=10)
                m_graphF.LineX(i, Color(0,0.5,0));     
        m_graphF.Save();
       
        m_graphS.Clear(Color.black);
        m_graphS.Grid(1, 2, Color(0,0.2,0));
        for (i=10; i<m_graphS.CanvasHeight(); i+=10)
                m_graphS.LineX(i, Color(0,0.5,0));
        m_graphS.Save();
       
        // Preparar los gráficos de las barras estabilizadoras
       
        m_graphStabF = new GUICanvas(96, 64, 1, 1);
        m_graphStabR = new GUICanvas(96, 64, 1, 1);
        m_graphStabF.SetAlpha(0.5);
        m_graphStabR.SetAlpha(0.5);
       
        m_graphStabF.Clear(Color.black);
        m_graphStabF.Grid(.25, .25, Color(0,0.2,0));
        m_graphStabF.Save();   
        m_graphStabR.Clear(Color.black);
        m_graphStabR.Grid(.25, .25, Color(0,0.2,0));
        m_graphStabR.Save();   
       
        if (Target)
                {
                UpdateFrictionCurves();
                UpdateStabBarCurves();
                }
               
        // Preparar los gráficos de la suspensión
               
        m_graphSpring = new GUICanvas(32, 64, 1, 1);
        m_graphSpring.SetAlpha(0.5);
        m_graphSpring.Clear(Color.black);
        m_graphSpring.Grid(.50, .25, Color(0,0.2,0));
        m_graphSpring.Save();  
               
        // Gráficos de las barras de valor
       
        m_graphBar0 = new GUICanvas(16, 16, 1, 1);
        m_graphBar0.Clear(Color(0.0, 0.5, 0.0, 0.5));
        m_graphBar1 = new GUICanvas(16, 16, 1, 1);
        m_graphBar1.Clear(Color(0.5, 0.5, 0.0, 0.5));
        m_graphBar2 = new GUICanvas(16, 16, 1, 1);
        m_graphBar2.Clear(Color(0.75, 0.0, 0.0, 0.5)); 
        }


       
private var SavedForwardCurve = new CarFrictionCurve();
private var SavedSidewaysCurve = new CarFrictionCurve();
private var savedForwardScale = 1.0;

private var SavedStabBarFront = 1.0;
private var SavedStabBarRear = 1.0;


function IsSameCurve(c1, c2: CarFrictionCurve)
        {
        return c1.grip == c2.grip && c1.gripRange == c2.gripRange && c1.drift == c2.drift && c1.driftSlope == c2.driftSlope;
        }
       
function CloneCurve(original, cloned : CarFrictionCurve)
        {
        cloned.grip = original.grip;
        cloned.gripRange = original.gripRange;
        cloned.drift = original.drift;
        cloned.driftSlope = original.driftSlope;
        }

       
function UpdateFrictionCurves ()
        {
        if (Target.WheelFL.getWheelCollider() != null)
                {
                // Curva longitudinal
               
                m_graphF.Restore();
                m_graphF.LineY(Target.WheelFL.getForwardPeakSlip(), Color.gray);
                m_graphF.LineY(Target.WheelFL.getForwardMaxSlip(), Color.gray);        
                CarWheelFriction.DrawScaledFrictionCurve(m_graphF, CarWheelFriction.MCforward, Target.ForwardWheelFriction, Target.WheelFL.getWheelCollider().forwardFriction.extremumSlip, Color.green);
                CloneCurve(Target.ForwardWheelFriction, SavedForwardCurve);
               
                // Curva lateral
               
                m_graphS.Restore();
                CarWheelFriction.DrawFrictionCurve(m_graphS, CarWheelFriction.MCsideways, Target.SidewaysWheelFriction, Color.green);
                m_graphS.LineY(Target.WheelFL.getSidewaysPeakSlip(), Color.gray);
                m_graphS.LineY(Target.WheelFL.getSidewaysMaxSlip(), Color.gray);
                CloneCurve(Target.SidewaysWheelFriction, SavedSidewaysCurve);
                }
        }      
       
       
function UpdateStabBarCurves ()
        {
        m_graphStabF.Restore();
        m_graphStabF.BiasCurve(Vector2.zero, Vector2.one, Target.AntiRollFront.AntiRollBias, Color.green);
        SavedStabBarFront = Target.AntiRollFront.AntiRollBias;
       
        m_graphStabR.Restore();
        m_graphStabR.BiasCurve(Vector2.zero, Vector2.one, Target.AntiRollRear.AntiRollBias, Color.green);
        SavedStabBarRear = Target.AntiRollRear.AntiRollBias;   
        }


function Update ()
        {
        var forwardScale = 1.0;
       
        if (Target.WheelFL.getWheelCollider() != null)
                forwardScale = Target.WheelFL.getWheelCollider().forwardFriction.extremumSlip;
       
        if (Target && (!IsSameCurve(Target.ForwardWheelFriction, SavedForwardCurve) || !IsSameCurve(Target.SidewaysWheelFriction, SavedSidewaysCurve) || forwardScale != savedForwardScale))
                {
                UpdateFrictionCurves();
                savedForwardScale = forwardScale;
                }
               
        if (Target.AntiRollFront.AntiRollBias != SavedStabBarFront || Target.AntiRollRear.AntiRollBias != SavedStabBarRear)
                UpdateStabBarCurves();
               
        // Dibujar los gizmos
       
        if (Gizmos)
                {
                DoWheelGizmos(Target.WheelFL);
                DoWheelGizmos(Target.WheelFR);
                DoWheelGizmos(Target.WheelRL);
                DoWheelGizmos(Target.WheelRR);
               
                var CoM = Target.CenterOfMass.position;
                var F = Target.transform.forward * 0.05;
                var U = Target.transform.up * 0.05;
                var R = Target.transform.right * 0.05;
               
                Debug.DrawLine(CoM - F, CoM + F, Color.white);
                Debug.DrawLine(CoM - U, CoM + U, Color.white);
                Debug.DrawLine(CoM - R, CoM + R, Color.white);
                }      
        }

       
       
private var m_sDescription = "";


function GetSlipColor(Slip : float) : Color
        {
        Slip = Mathf.Abs(Slip);
       
        if (Slip <= 1.0) return Color.green;
        else if (Slip < 2.0) return Color.yellow;
        else return Color.red;
        }
       
function DoWheelTelemetry(Wheel : CarWheel, Compression : float) : String
        {
        var Hit : WheelHit;
        var WheelCol = Wheel.getWheelCollider();
        var bGrounded = WheelCol.GetGroundHit(Hit);

        if (bGrounded)
                {
                var forwardSlipRatio = Wheel.getForwardSlipRatio();
                var sidewaysSlipRatio = Wheel.getSidewaysSlipRatio();
               
                return String.Format("{0} RPM:{1,4:0.} S:{2,5:0.00} F:{3,5:0.} FS:{4,5:0.00} SS:{5,5:0.00} FSR:{6,5:0.00} SSR:{7,5:0.00}\n", // SM:{8,5:0.00} FM:{9,5:0.00}\n",
                                Wheel.gameObject.name, WheelCol.rpm, Compression, Hit.force, Hit.forwardSlip, Hit.sidewaysSlip,                                                        
                                forwardSlipRatio, sidewaysSlipRatio,
                               
                                WheelCol.sidewaysFriction.stiffness, WheelCol.forwardFriction.stiffness
                                );
                }
        else
                return String.Format("{0} RPM:{1,4:0.} S:{2,5:0.00}\n", Wheel.gameObject.name, WheelCol.rpm, Compression);
        }
       
       
       
function DoWheelGizmos(Wheel : CarWheel)
        {
        var Hit : WheelHit;
        var WheelCol = Wheel.getWheelCollider();
        var bGrounded = WheelCol.GetGroundHit(Hit);
       
        if (bGrounded)
                {
                var forwardSlipRatio = Wheel.getForwardSlipRatio();
                var sidewaysSlipRatio = Wheel.getSidewaysSlipRatio();

                var extension = (-WheelCol.transform.InverseTransformPoint(Hit.point).y - WheelCol.radius) / WheelCol.suspensionDistance;
               
                var RayHit : RaycastHit;       
                if (Physics.Raycast(Wheel.transform.position, -Wheel.transform.up, RayHit, (WheelCol.suspensionDistance + WheelCol.radius) * Wheel.transform.lossyScale.y))
                        Hit.point = RayHit.point;
               
                Debug.DrawLine(Hit.point, Hit.point + Wheel.transform.up * (Hit.force / 10000.0), extension <= 0.0 ? Color.magenta : Color.white);
                Debug.DrawLine(Hit.point, Hit.point - Wheel.transform.forward * Hit.forwardSlip, GetSlipColor(forwardSlipRatio));
                Debug.DrawLine(Hit.point, Hit.point - Wheel.transform.right * Hit.sidewaysSlip, GetSlipColor(sidewaysSlipRatio));
                if (Velocity) Debug.DrawLine(Hit.point, Hit.point + Target.rigidbody.GetPointVelocity(Hit.point), Color.blue);
                }
        }
 

private var m_LastSpeedMS = 0.0;
private var m_LastSpeedLatMS = 0.0;

private var m_MaxAngularVelocity = Vector3(0,0,0);


function DoTelemetry ()
        {
        m_sDescription = "";

        if (!Enabled || !Target) return;
       
        // Datos de las barras estabilizadoras, si hay
       
        var extFL = 0.0;
        var extFR = 0.0;
        var extRL = 0.0;
        var extRR = 0.0;
        var antiRollForceF = 0.0;
        var antiRollForceR = 0.0;
       
        if (Target.AntiRollFront)
                {
                extFL = Target.AntiRollFront.getExtensionL();
                extFR = Target.AntiRollFront.getExtensionR();
                antiRollForceF = Target.AntiRollFront.getAntiRollRatio();
                }
               
        if (Target.AntiRollRear)
                {
                extRL = Target.AntiRollRear.getExtensionL();
                extRR = Target.AntiRollRear.getExtensionR();
                antiRollForceR = Target.AntiRollRear.getAntiRollRatio();
                }              

        // Telemetría de las ruedas

        m_sDescription += DoWheelTelemetry(Target.WheelFL, extFL);
        m_sDescription += DoWheelTelemetry(Target.WheelFR, extFR);
        m_sDescription += DoWheelTelemetry(Target.WheelRL, extRL);
        m_sDescription += DoWheelTelemetry(Target.WheelRR, extRR);
       
        m_sDescription += String.Format("Friction F: [{0,5:0.000}, {1,5:0.000}] S: [{2,5:0.000}, {3,5:0.000}]\n", Target.WheelFL.getForwardPeakSlip(), Target.WheelFL.getForwardMaxSlip(), Target.WheelFL.getSidewaysPeakSlip(), Target.WheelFL.getSidewaysMaxSlip());
        m_sDescription += String.Format("Grip F:{0,4:0.00} R:{1,4:0.00} Stab F:{2,5:0.000} R:{3,5:0.000} Steer L:{4,5:0.0} R:{5,5:0.0}\n", Target.WheelFL.getDriftFactor(), Target.WheelRL.getDriftFactor(), antiRollForceF, antiRollForceR, Target.getSteerL(), Target.getSteerR());

        // Telemetría del vehículo

        var SpeedMS = Vector3.Dot(Target.rigidbody.velocity, Target.transform.forward);
        var SpeedLatMS = Vector3.Dot(Target.rigidbody.velocity, Target.transform.right);
       
        var roll = Target.transform.localEulerAngles.z; if (roll > 180.0) roll -= 360.0;
        var pitch = Target.transform.localEulerAngles.x; if (pitch > 180.0) pitch -= 360.0;
       
        var AngV = Target.rigidbody.angularVelocity;
        if (Mathf.Abs(AngV.x) > m_MaxAngularVelocity.x) m_MaxAngularVelocity.x = Mathf.Abs(AngV.x);
        if (Mathf.Abs(AngV.y) > m_MaxAngularVelocity.y) m_MaxAngularVelocity.y = Mathf.Abs(AngV.y);
        if (Mathf.Abs(AngV.z) > m_MaxAngularVelocity.z) m_MaxAngularVelocity.z = Mathf.Abs(AngV.z);

        m_sDescription += String.Format("\nSpeed:{0,6:0.00} m/s {1,5:0.0} km/h {2,5:0.0} mph\n  Abs:{3,6:0.00} m/s Lat:{4,5:0.00} m/s\n  Acc:{5,5:0.00} m/s2 Lat:{6,5:0.00} m/s2\nPitch:{7,6:0.00} Roll:{8,6:0.00}  Max:{9,6:0.00}\n",
                                                SpeedMS, SpeedMS*3.6, SpeedMS*2.237, Target.rigidbody.velocity.magnitude, SpeedLatMS, (SpeedMS-m_LastSpeedMS) / Time.deltaTime, (SpeedLatMS-m_LastSpeedLatMS) / Time.deltaTime, pitch, roll, Target.getMaxRollAngle());
        m_sDescription += String.Format(" AngV: {0,5:0.00},{2,5:0.00} Max:{3,5:0.00},{5,5:0.00}\n", AngV.x, AngV.y, AngV.z, m_MaxAngularVelocity.x, m_MaxAngularVelocity.y, m_MaxAngularVelocity.z);

        m_LastSpeedMS = SpeedMS;
        m_LastSpeedLatMS = SpeedLatMS;

        // Telemetría del script de control

        m_sDescription += String.Format("\nGear: {0} Accel:{1,5:0.00} Brake:{2,5:0.00} Handbrake:{3,5:0.00} Steer:{4,5:0.00}\nMotorMax:{5,4:0.0} BrakeMax:{6,4:0.0}\n",
                                                Target.getGear(), Target.getMotor(), Target.getBrake(), Target.getHandBrake(), Input.GetAxis("Horizontal"),
                                                Target.motorMax, Target.brakeMax);
       
        // Telemetría de las configuraciones

        var Settings : CarSettings = Target.GetComponent(CarSettings);
        if (Settings)
                m_sDescription += String.Format("StabMode: {0}{1}{2}\n{3}{4}{5}{6}{7}\n",
                                                Settings.stabilizerMode == 0? "Auto (" : "",
                                                Settings.getStabilizerModeStr(),
                                                Settings.stabilizerMode == 0? ") " : "",
                                                Settings.abs? "ABS " : "",
                                                Settings.tc? "TC " : "",
                                                Settings.esp? "ESP " : "",
                                                Settings.getTractionAxleStr() + " ",
                                                Time.timeScale < 1.0? "Slow-Motion " : "");
        }


function FixedUpdate ()
        {
        DoTelemetry();
        }
       
       
       
       
function DrawCurvePerformance(x, y : int, graph : GUICanvas, slip, slipRatio : float)
        {
        var graphBar : GUICanvas;
       
        slip = Mathf.Abs(slip);
        slipRatio = Mathf.Abs(slipRatio);
       
        if (slip > 0.0)
                {
                if (slip > graph.CanvasWidth()) slip = graph.CanvasWidth();
                 
                if (slipRatio < 1.0) graphBar = m_graphBar0;
                else if (slipRatio < 2.0) graphBar = m_graphBar1;
                else graphBar = m_graphBar2;
               
                graphBar.GUIStretchDraw(x, y, slip*graph.ScaleX(), graph.PixelsHeight());
                }
        }
       

function DrawWheelCurves(x, y : int, forwardCurve, sidewaysCurve : GUICanvas, Wheel : CarWheel)
        {
        forwardCurve.GUIDraw(x, y);
        sidewaysCurve.GUIDraw(x, y + forwardCurve.PixelsHeight()*1.1);
       
        var Hit : WheelHit;
        var WheelCol = Wheel.getWheelCollider();
        var bGrounded = WheelCol.GetGroundHit(Hit);

        if (bGrounded)
                {
                DrawCurvePerformance(x, y, forwardCurve, Hit.forwardSlip, Wheel.getForwardSlipRatio());
                DrawCurvePerformance(x, y + forwardCurve.PixelsHeight()*1.1, sidewaysCurve, Hit.sidewaysSlip, Wheel.getSidewaysSlipRatio());
                }
        }
       
       
function DrawStabBarCurve(x, y : int, graph : GUICanvas, Bar : CarAntiRollBar)
        {
        var graphBar : GUICanvas = m_graphBar0;
        var ratio = Mathf.Abs(Bar.getAntiRollRatio());
        var travel = Mathf.Abs(Bar.getAntiRollTravel());
       
        if (ratio > 0.75) graphBar = m_graphBar2;
        else if (ratio > 0.5) graphBar = m_graphBar1;  
       
        graph.GUIDraw(x, y);   
        graphBar.GUIStretchDraw(x, y, travel * graph.ScaleX(), graph.PixelsHeight());
        }
       

       

       
function DrawSuspensionPerformance(x, y : int, graph : GUICanvas, WheelCol : WheelCollider, travel : float)
        {
        var graphBarTravel : GUICanvas;
        var graphBarForce : GUICanvas;
       
        var Hit : WheelHit;
        var bGrounded = WheelCol.GetGroundHit(Hit);
       
        travel = 1.0 - travel; // Representar compresión: 0.0 = extendido, 1.0 = comprimido
        forceRatio = Hit.force / WheelCol.suspensionSpring.spring;
       
        if (bGrounded)
                {
                if (travel >= 1.0) graphBarTravel = m_graphBar2;
                else graphBarTravel = m_graphBar0;
                       
                if (forceRatio >= 1.0) graphBarForce = m_graphBar1;
                else graphBarForce = m_graphBar0;
                       
                travel = Mathf.Clamp01(travel);
                forceRatio = Mathf.Clamp01(forceRatio);
               
                graphBarTravel.GUIStretchDraw(x, y + (1.0-travel)*graph.PixelsHeight(), 0.5*graph.ScaleX(), travel*graph.PixelsHeight());
                graphBarForce.GUIStretchDraw(x+0.5*graph.ScaleX(), y + (1.0-forceRatio)*graph.PixelsHeight(), 0.5*graph.ScaleX(), forceRatio*graph.PixelsHeight());
                }
        }
       
       

function DrawSuspension(x, y : int, Bar : CarAntiRollBar)
        {
        m_graphSpring.GUIDraw(x, y);
        m_graphSpring.GUIDraw(x+m_graphSpring.PixelsWidth()+4, y);
        DrawSuspensionPerformance(x, y, m_graphSpring, Bar.WheelL, Bar.getExtensionL());
        DrawSuspensionPerformance(x+m_graphSpring.PixelsWidth()+4, y, m_graphSpring, Bar.WheelR, Bar.getExtensionR());
        }
       
       
function OnGUI ()
        {
        if (!Enabled) return;

        GUI.Box(Rect (8, 8, 440, 231), "Telemetry (B to hide)");
        GUI.Label (Rect (16, 28, 600, 205), m_sDescription, m_Style);
       
        if (Curves)
                {
                DrawWheelCurves(460, 4, m_graphF, m_graphS, Target.WheelFL);
                DrawWheelCurves(460+m_graphF.PixelsWidth()*1.1, 4, m_graphF, m_graphS, Target.WheelFR);
               
                DrawSuspension(460+m_graphF.PixelsWidth()*2.2 + 14, 4, Target.AntiRollFront);
                DrawStabBarCurve(460+m_graphF.PixelsWidth()*2.2, 4+m_graphF.PixelsHeight()*1.1, m_graphStabF, Target.AntiRollFront);
               
                DrawWheelCurves(460, 4+m_graphF.PixelsHeight()*2.2, m_graphF, m_graphS, Target.WheelRL);
                DrawWheelCurves(460+m_graphF.PixelsWidth()*1.1, 4+m_graphF.PixelsHeight()*2.2, m_graphF, m_graphS, Target.WheelRR);            
               
                DrawSuspension(460+m_graphF.PixelsWidth()*2.2 + 14, 4+m_graphF.PixelsHeight()*2.2, Target.AntiRollRear);
                DrawStabBarCurve(460+m_graphF.PixelsWidth()*2.2, 4+m_graphF.PixelsHeight()*3.3, m_graphStabR, Target.AntiRollRear);
                }
        }

 



Да вообще я про графики к слову сказал, показалось так будет очень наглядно.
Camera control by FreeTrackIR: FreeTrackIR + Unity3d
Аватара пользователя
nile
Старожил
 
Сообщения: 847
Зарегистрирован: 25 фев 2011, 17:17
Skype: dennis.sadovsky

Re: Затухающее колебание переменной (Damped Oscillation)

Сообщение AM-Games 28 июн 2013, 14:03

Acrobat писал(а):Почему бы Вам не засунуть тело Вашей функциии в Update, дополнительно убрав из тела for(;;) и Waitfoendofframe? Че то мне кажется работать будет.

Я планирую сделать так, чтобы можно было для какой-нибудь переменной выполнить функцию, типа "Oscillation(this.transform.position.x, amp, decay, freq);". А это удобно делать именно тем способом, что у меня, но надо дорабатывать, причем не мало.
AM-Games
UNIт
 
Сообщения: 139
Зарегистрирован: 21 окт 2012, 11:30

Re: Затухающее колебание переменной (Damped Oscillation)

Сообщение AM-Games 28 июн 2013, 15:27

Вот демка со всеми плюшками для сравнения.
Активируются кубы цифрами 1-4.
Куб 1:
Мой скрипт. Деактивируется автоматически.
Куб 2:
Голый ПингПонг. Деактивируется нажатием на 2.
Куб 3:
ПингПонг с линейным спадением амплитуды. Деактивируется нажатием на 3.
Куб 4:
Тот же куб три, но с линейным спадением скорости и амплитуды. Деактивируется нажатием на 4.

Графики тут не особо нужны, потому что всё очевидно. Для первого куба график в первом сообщении.

Лучше не становиться на кубы.
HTML код для вашего блога :
Код: Выделить всё
<script language='javascript' type="text/javascript"> document.write("<iframe marginheight='0' src='http://unity3d.ru/distribution/player.php?url=https://dl.dropbox.com/s/3rea7mstxq0lzkx/DemoOscillation.unity3d?dl=1&w=600&h=400&t=false&preview=1' height='"+(400+30)+"' width='600' frameborder='0' scrolling='no'></iframe>"); </script>
AM-Games
UNIт
 
Сообщения: 139
Зарегистрирован: 21 окт 2012, 11:30

Re: Затухающее колебание переменной (Damped Oscillation)

Сообщение Макс 28 июн 2013, 16:23

AM-Games писал(а):Вот демка со всеми плюшками для сравнения.
Активируются кубы цифрами 1-4.

А что происходить то там должно? в 2х браузерах смотрел - ничего не увидел, только голая пустыня и кубы, после щелчка на которые, пропалает курсор и ничего больше.
Макс
UNIверсал
 
Сообщения: 372
Зарегистрирован: 20 июн 2013, 23:05

Re: Затухающее колебание переменной (Damped Oscillation)

Сообщение Макс 28 июн 2013, 16:34

А я вот поэксперементировал с пинг-понгом, в принципе можно получать интересные эффекты вполне.
Вот скомпилированую демку с интерфейсом управления, прилагаю в архиве. Можно моделировать различные эффекты.
У вас нет доступа для просмотра вложений в этом сообщении.
Макс
UNIверсал
 
Сообщения: 372
Зарегистрирован: 20 июн 2013, 23:05

Re: Затухающее колебание переменной (Damped Oscillation)

Сообщение AM-Games 28 июн 2013, 17:28

Макс писал(а):
AM-Games писал(а):Вот демка со всеми плюшками для сравнения.
Активируются кубы цифрами 1-4.

А что происходить то там должно? в 2х браузерах смотрел - ничего не увидел, только голая пустыня и кубы, после щелчка на которые, пропалает курсор и ничего больше.

Циферки на клаве нажимай от 1 до 4
AM-Games
UNIт
 
Сообщения: 139
Зарегистрирован: 21 окт 2012, 11:30

След.

Вернуться в Исходники (Копилка)

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1