블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2845)
Unity3D (891)
Programming (479)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (188)
협업 (64)
3DS Max (3)
Game (12)
Utility (141)
Etc (99)
Link (33)
Portfolio (19)
Subject (90)
iOS,OSX (52)
Android (16)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (19)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday

OnBecameVisible/OnBecameInvisible 이벤트 함수가 스크립트가 꺼져 있어도 상관없이 동작 한다길래,


신기해서 테스트 해보려고 Empty GameObject에 넣고 테스트 해봤는데 이벤트가 발생하질 않아서 뭔가 하고 찾아봤다.


OnBecameVisible/OnBecameInvisible 두 함수는 Renderer 관련 함수여서 Mesh Renderer Component가 추가 돼 있어야 이벤트가 발생한다.


삽질 좀 하고..


좀 유용하게 써먹어야겠다.

반응형

'Unity3D > Tips' 카테고리의 다른 글

C# 사용할때 주의할 점  (0) 2013.01.15
Expand/Collapse All(모두 펴기/접기)  (0) 2013.01.04
iOS 프로젝트 포팅/최적화 팁  (0) 2012.12.06
2D 게임을 위한 텍스쳐(Texture) 설정  (0) 2012.11.28
성능 최적화  (0) 2012.11.18
Posted by blueasa
, |

Unity3D iOS 프로젝트 포팅/최적화 팁

원저 : Itay Keren, Untame Games - 31 Dec 2010


아래의 글은 유니티3D로 만들었던 제 게임 'Rope Racket'을
iOS(iPhone/iPad)로 이식하면서 얻은 팁들에 대해 대략적으로 정리해놓은,
미완성된 리스트입니다.
아래 리스트를 필요하면 그때그때 업데이트할 예정이니,
종종 들러서 확인해보시기 바랍니다.


물리엔진 관련 Physics


유니티3D는 매우 잘 최적화된 PhysX 물리엔진을 사용합니다.
일반적으로 물리에 관련된 모든 기능들은 이 엔진에 의해 자동적으로 처리됩니다.
하지만 iOS에 적용할 경우 고려해 볼 만한 점이 좀 있습니다 :
  • 충돌자Colliders
    불필요한 충돌자들을 없애고, 하나로 묶으세요.  Ex) 적 오브젝트는 한개의 충돌자만 쓰게끔

  • 겹쳐진 충돌자들Overlapping colliders은 매 프레임당 (많으면)3번까지의 반복 처리를 유발할 수 있으므로,
    충돌자가 붙은 오브젝트의 위치를 강제로 배치할 경우 특별히 유념하시기 바랍니다.
    (씬 에디터 상에서의 수동 배치나, transform값 수정에 의한 배치 등 직접 position값을 주는 경우를 말함 - 역주)

  • 좀 더 간단한 형태의 충돌자를 사용
    메쉬mesh 충돌자보다는 입방체cube, 입방체 보다 구체sphere 충돌자가 더 간단합니다.

  • 조인트Joints의 연쇄 반응에 주의
    조인트 사용시, 한쪽 끝의 움직임은 항상 반대쪽 끝까지의 연쇄적인 움직임을 유발합니다.
    서로 연결된 몇개의 조인트를 사용하게 되면 필연적으로 연쇄 반응하는 움직임을 양산하므로,
    사용에 주의하시기 바랍니다.

일반적인 최적화 General Optimization


코드 최적화는 성능을 두드러지게 향상시킬 수 있습니다.
대부분의 경우, 최적화가 안돼서 성능이 떨어지는 주된 원인은 프로그래밍이 (애초에) 부적절하게된 점에서 발생합니다.
  • 몇가지 작업들은 굳이 매 프레임마다 돌릴 필요가 없는 경우가 있습니다.
    Ex) 버튼의 상태 체크, 거리 체크, AI 전략 판단 등등
    이런 동작들 대부분은 초당 10번 정도만 하게끔 바꿔도 아무도 모를 겁니다.

  • Get...()류의 함수들은 개념적으로는 좋습니다만, 성능적으로 (처리 비용이) 비쌀 경우가 있습니다.
    public 변수 정의로 값을 빼놓는 방법은 지저분해보이긴 합니다만, 외부에서 값을 억세스할 경우 더 빠릅니다.

  • transform도 알고 보면 Get...()류의 함수를 쓰고 있습니다.  
    반복해서 사용할 경우 변수값에다 따로 빼놓으세요.

  • 종종 CPU 사용량이 비정상적으로 튀는(CPU spikes) 현상을 방지하려면,
    System.GC.Collect()를 사용, 적절히 정해진 간격으로 가비지 컬렉터를 호출하세요.

  • sin/cos/atan/sqrt등의 수학 함수는 가능한 한 미리 계산된 테이블값을 사용하거나,
    최소한 자주 변하지 않는 값들을 찾아 변수에 담아놓고 불러다 사용하세요.


그래픽 Graphics


iOS에서 사용되는 GPU는 PC에서 사용되는 것과는 많이 다릅니다.
잘 알려진 제약 사항들 몇 가지를 살펴보자면 :
  • 폴리곤 수
    7,000개가 HW 한계라던지(3GS 기준인 듯 - 역주) 같은 글들을 많이 읽어봤습니다만,
    경험적으로는 폴리곤 수가 다른 요인에 비해 특별히 더 중요한 영향을 끼친다고 생각되진 않습니다.
    한 씬에서 10,000개 이하로 유지하기 위해 가능한 한 노력해보세요.

  • 메모리 최적화
    iOS 플랫폼에서 사용할 최대 텍스쳐 사이즈값Maximum Texture Size for iOS지정을,
    디테일을 잃어버리지 않는 한도에서 최대한 줄여보시기 바랍니다.
    (해당 Texture의 Inspector 메뉴 하단에서, 
     각 빌드 플랫폼별로 Override for... 체크박스를 켜고 최대 텍스쳐 사이즈 및 포맷 지정 가능.
     자세한 사항은 http://unity3d.com/support/documentation/Manual/Textures.html
      위 링크에서 Per-Platform Overrides 항목 및 플랫폼별 사용 가능한 텍스쳐 포맷 설명을 참조 - 역주)
    제 경우는 대부분의 오브젝트에서 최대 256x256, 또는 그 이하로도 충분했었습니다.
    또한 이것을 각각의 대상 플랫폼별로도 지정하실 수가 있는데 (위의 역주 참고)
    PC에선 디테일하게, iOS에선 메모리 사용을 줄이는 식으로 지정할 수도 있습니다.

  • iPhone의 GPU상에서 복잡하고 여러번의 패스multi-pass를 거쳐야 하는 셰이더를 쓰면 느려집니다.
    예를 들어 Toon 계열 셰이더라든지, Transparent/Cutout 계열 셰이더는 가능한 한 사용을 피해야 합니다.

  • 라이팅은 (처리 비용이) 매우 비쌉니다.
    일반적으로 조명이 추가될때마다 (영향받는 모든 오브젝트들에 대한) 
    그리기 패스drawing pass 또한 추가가 됩니다.
    밝은 지향성 조명directional light 하나만 사용하세요.  
    다른 조명, 특히 점point 광원이나 스포트라이트를 사용할 땐 주의하시기 바랍니다.
    조명을 추가하는 데엔 두 가지 문제점이 있음을 기억하세요 -
    그 조명을 받는 모든 물체에 대해 렌더링 작업이 늘어난다는 점과,
    그 조명이 켜지는 시점에서  조명 초기화를 위해 몇밀리초를 더 잡아먹게 된다는 점.

  • 정점vertex의 위치/노말/탄젠트 값을 바꾸는 것은 (처리 비용이) 비싸며, 반복적으로 해선 안됩니다.
    반면, UV(텍스쳐 내에서의 픽셀 위치) 값을 바꾸는 것은 빠릅니다.

  • OnGUI()는 매 프레임마다, 추가적으로  매 이벤트마다 호출됩니다.
    게다가, 연속되는 OnGUI() 내에서 같은 리소스, 매터리얼을 반복 사용하더라도
    이를 공유해서 최적화해준다던가 하지 않습니다.
    (예를 들어, 텍스트와 그 그림자를 그리면 그대로 2번의 그리기 호출2 calls이 발생)
    그러니 가능한 한 사용을 피하세요.


그리기 호출Draw Calls


그리기 호출Draw Call 은 (카메라를 통해 한 프레임의 화면을 만들어내는 동안)
하나의 셰이더 패스, 하나의 매터리얼로 오브젝트를 한 번 그리는 작업의 단위를 말합니다.
(같은 셰이더/같은 매터리얼을 갖는 여러 개의 오브젝트라도 한번의 draw call 작업에서 그릴 수 있음 - 역주)

iPad같은 하이엔드급 모바일 장치에서조차, 이 그리기 호출Draw Call 수를 줄이는 일이
제 경험상 최적화에서 가장 중요한 요소라고 생각이 됩니다. 
확실히 모바일 장비는 비-모바일 장비non-mobile devices에 비해 
CPU와 GPU간의 파이프라인이 그리 효율적이지가 않습니다.
  • 동적 배칭Dynamic Batching 기능이 켜져있는가 확인하세요
    (File 메뉴 > Build Settings... 메뉴 > Player Settings 버튼 >
     Inspector창에서 Other Settings 항목 > Rendering 항목 밑에 Dynamic Batching 체크박스 선택.
     자세한 설명은 http://unity3d.com/support/documentation/Manual/iphone-DrawCall-Batching.html
     위 링크에서 Dynamic Batching 부분을 참조 - 역주)

  • 이것이 켜져있으면, 게임 엔진은 모든 오브젝트를 공유된 매터리얼 단위로 묶습니다.
    이 경우, (스크립트에서 건드릴 땐) material 멤버 대신 sharedMaterial 멤버를 사용하도록 해야 합니다.

  • 나아가, 배치 처리될 모든 오브젝트all batched object는 같은 셰이더 큐 패스queue pass를 공유해야 합니다.
    각각의 카메라는 여러 개의 그리기 패스drawing pass를 가지고 있습니다.
    몇몇 매터리얼이 같은 그리기 패스를 공유하고 있다 하더라도,
    같은 매터리얼을 사용하는 모든 오브젝트가 한번에 배치 처리된다는 보장은 없습니다.
    그러므로, 매터리얼의 셰이더 패스 순서pass order를 직접 지정해줌으로써
    그 매터리얼이 특정 그리기 패스 안에서 동작하도록 강제할 수 있습니다.
    예를 들자면, 셰이더 명령어 Tags {"Queue" = "Transparent-1" } 을 사용하면
    해당 셰이더가 Transparent pass 직후(*주1*)에 동작하도록 강제할 수 있습니다.
    이렇게 Transparent-1로 셋팅하게 되면, 이 새로운 매터리얼은 기존의 Transparent 셰이더와 분리되며,
    이 새로운 셰이더를 사용하는 모든 오브젝트를 묶어 한 패스 안에서 배치batch 처리하게 됩니다.
    주 : 이 방법은 깊이값 소팅이나 Z값 관련 문제를 해결하는데도 도움이 됩니다.
    (이 항목의 내용은 제가 셰이더를 공부 안해서 제대로 번역이 되었는지 확신이 없네요 - 역주)

  • 가장 중요한 사항: 가능한 한 많은 오브젝트를 한 매터리얼(한 장의 텍스쳐)로 묶어야 합니다.
    예를 들어, 한장의 아이콘 맵icon atlas을 만들고 필요한 상황에 따라 UV위치값을 바꿔가며 쓰는 방법이 있습니다.

  • 대안책: 폰트를 하나 읽어들이고 이 텍스쳐를 export합니다.  
    찍고싶은 이미지를 조각내서 이 export된 폰트 텍스쳐 위치에 갖다 붙입니다.
    그리고, Text Mesh를 사용해서 이것들을 가져다 적절한 아이콘으로 사용합니다.


그 외의 팁들More Tips

최적화와는 관계없지만 몇가지 편리한 팁들이 더 있습니다 :
  • OnGUI()나 GUITexture를 사용하는 대신, 별도의 카메라로 모든 GUI를 그려주기

    • GUI를 위한 별도의 카메라를 만듭니다
      평행isometric 카메라로 지정하고, 별도로 만든 GUI 오브젝트 레이어 이외의 모든 다른 레이어를 끄고,
        (메인 카메라보다 나중에 찍도록) Depth값을 1로 주고, Clear flag를 Don't Clear로 맞추세요.

    • 텍스트를 찍기 위해선 Text Mesh 와 Mesh Renderer를 사용합니다.
      만들어진 GUI용 GameObject들은 별도로 만든 GUI 오브젝트 레이어 쪽으로 넣어줍니다.
      이렇게 하면 유니티에서 현지화된 텍스트를 사용할때 매우 빠르고 융통성있게끔 만들 수 있습니다.
      이런 덱스트는 변경 가능하고, 회전, 확대/축소할 수도 있으며 
      기본 폰트대신 사용자 정의된 매터리얼로 대치할수도 있습니다.

    • 비슷한 형태로, 로고나 이미지는 박스를 이용해 찍을 수 있습니다.
      평행isometric 카메라 상에서 상각 폴리곤을 찍는 처리비용은 거의 미미하며, 
      불필요한 옆면 등은 알아서 무시됩니다.
      투명값을 가진 이미지를 사용할때는, 뒷면이 없어지게끔 컬링이 적용된 셰이더를 사용하거나
      박스 자체를 카메라에 아주 가깝게 가져와서, 박스 앞면은 카메라 평면 뒤로 보내고 박스 뒷면만 보이게 합니다.

  • (투명값을 갖는 텍스쳐의 경우) 텍스쳐 테두리의 흰색 띠가 보일 경우는
    알파값 0를 가진 픽셀 색이 주변으로 일부 번지기 때문에 발생합니다.
    이 경우, 테두리의 주변 RGB값들이 영향을 미치고 있는 것인데, 포토샵에서 이를 수정하려면 :
    • 알파값 0 인 배경 픽셀들을 전부 선택한다
    • 이미지 테두리를 따라 원하는 경계선 색을 다 칠해준다 (이미지 안쪽은 선택 영역이 보호해준다)
    • Layar Mask를 만들어, 방금 칠해준 선택 영역을 hide 시킨다

결과적으로 알파값이 0인 픽셀들도 원하는 테두리 색을 가지게 되어 보기 좋게 섞여진다.

More tips to follow soon.

Enjoy,
— Itay

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

*주1*
원문에는 
will make sure that this shader is drawn right after Transparent pass. 라고 되어 있어서
원 저자의 의도대로 '
Transparent pass 직후' 라고 번역이 되었습니다만...
http://unity3d.com/support/documentation/Components/SL-SubshaderTags.html 을 보시면,
각 렌더 패스마다 내부적으로 1000단위의 숫자가 매겨져 있고, Transparent의 값이 3000이니
저 Transparent-1 패스의 경우는 2999가 되어, 실제론 'Transparent pass 직전'이 맞습니다.

하지만 원문 내용은 Transparent pass 앞이냐 뒤냐가 중요한게 아니고, 저런 식으로 태그를 부여해서
원하는 drawing 작업을 분리된 하나의 drawing pass로 통합하는 방법을 보여주는 것이니
틀린 내용이라 하더라도 원 저자의 문맥대로 일단 번역하고 별도로 각주를 남깁니다.
* 원문에 이렇게 애매모호(?)한 부분이 두어 군데 더 보입니다만, 마찬가지로 패스... *

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 
 

반응형
Posted by blueasa
, |

NGUI Virtual Joystick

Unity3D/NGUI / 2012. 12. 5. 15:23


nguijoystick.unitypackage



NGUI에서 제공하는(맞나? 홈페이지에서 찾아도 못찾겠는데..) 조이스틱이 있어서 구해서 올려놓음..


버전이 달라져서 그런지 좀 바꿔야 될 부분이 있다..


1. 우선 Import 하고나면 UIJoystick.cs가 별도의 Plugin 폴더에 빠져 있다.

    이걸 NGUI-Scripts-UI 폴더로 옮겨주자.


2. UIJoystick.cs 스크립트에도 에러가 4개 난다.

    파일을 열어서 아래 두가지를 수정해주자.

    1) Tweener -> UITweener

    2) UICamera.lastCamera -> UICamera.currentCamera


3. 예제의 조이스틱 컨트롤은 Layer가 Default가 아니라서 Culling Mask 때문에 조이스틱이 제대로 작동 안할 수 도 있다.

    다른 Layer로 바꾸던지 Default로 바꾸자.(이것때문에 조작 안된다고 삽질을..)


위 까지만 수정하면 우선 돌아간다.


참조 : http://www.tasharen.com/forum/index.php?topic=55.0

반응형
Posted by blueasa
, |

ScriptableWizard.DisplayWizard

static function DisplayWizard.<T> (title : String) : T

Parameters

NameDescription
TThe class implementing the wizard. It has to derive from ScriptableWizard.
titleThe title shown at the top of the wizard window.

Returns

T - The wizard.

Description

Creates a wizard.

When the user hits the Create button OnWizardCreate function will be called. DisplayWizard will only show one wizard for every wizard class.


Simple Wizard Window that copies a GameObject several times.

// C#
// Simple Wizard that clones an object.

using UnityEngine;
using UnityEditor;
using System.Collections;

public class ScriptableWizardDisplayWizard : ScriptableWizard {

public GameObject ObjectToCopy = null;
public int numberOfCopies = 2;
[MenuItem ("Example/Show DisplayWizard usage")]
static void CreateWindow() {
// Creates the wizard for display
ScriptableWizard.DisplayWizard("Copy an object.",
typeof(ScriptableWizardDisplayWizard),
"Copy!");
}
void OnWizardUpdate() {
helpString = "Clones an object a number of times";
if(!ObjectToCopy) {
errorString = "Please assign an object";
isValid = false;
} else {
errorString = "";
isValid = true;
}
}
void OnWizardCreate () {
for(int i = 0; i < numberOfCopies; i++)
Instantiate(ObjectToCopy, Vector3.zero, Quaternion.identity);
}
}

static function DisplayWizard.<T> (title : String, createButtonName : String) : T

static function DisplayWizard.<T> (title : String, createButtonName : String, otherButtonName : String) : T

static function DisplayWizard (title : String, klass : System.Type, createButtonName : String = "Create", otherButtonName : String = "") : ScriptableWizard

Parameters

NameDescription
TThe class implementing the wizard. It has to derive from ScriptableWizard.
titleThe title shown at the top of the wizard window.
classThe class implementing the wizard. It has to derive from ScriptableWizard.
createButtonNameThe text shown on the create button.
otherButtonNameThe text shown on the optional other button. Leave this parameter out to leave the button out.

Returns

ScriptableWizard - The wizard.

Description

Creates a wizard.

When the user hits the Create button OnWizardCreate function will be called. DisplayWizard will only show one wizard for every wizard class.



출처 : http://docs.unity3d.com/Documentation/ScriptReference/ScriptableWizard.DisplayWizard.html

반응형

'Unity3D > Script' 카테고리의 다른 글

InGame Button  (0) 2012.12.14
InvokeRepeating  (0) 2012.12.07
Replace game object with prefab?  (0) 2012.12.04
폰트의 픽셀정보로 문자열을 Mesh들로 생성하여 보여주기  (0) 2012.11.24
Interpolate  (0) 2012.11.22
Posted by blueasa
, |

[추가]

유니티가 버전업(추가글 쓰는 현재 5.4버전) 되면서 프리팹 관련 함수가 EditorUtilty에서 PrefabUtility로 옮겨졌습니다.

아래 링크를 참조해 주세요.


[참조] https://docs.unity3d.com/ScriptReference/PrefabUtility.html





Hierachy에 Prefab으로 만들어 진 Gameobject들이 어떤 이유로 Prefab과의 링크가 깨져서 자동으로 링크할 방법을 궁리하던 중..


EditorUtility.ReplacePrefab 이란 함수를 써봤는데, 


되긴 하지만, 마지막 Replace 된 오브젝트의 정보가 프리팹에 동기화 돼서 나머지 모든 오브젝트의 정보가 똑같이 바껴버렸다.


어떻게 보면 정상이지만 내가 원하는 게 아녀서 다시 고민..


[방법]

1. 해당 프리팹을 참조

2. 프리팹과 name이 같은 오브젝트를 Hierarchy에서 찾는다.

3. 프리팹을 참조해서 새로운 오브젝트를 생성 기존 오브젝트의 정보를 대입.

4. 기존 오브젝트 삭제.


라고 생각하고..


만들기 귀찮아서 찾아보니.. 있다.. -_-;


생각한 방법에서 궁금했던 프리팹 생성 함수(EditorUtility.InstantiatePrefab)가 안에 있있다.

  1.         foreach (GameObject go in OldObjects)
  2.         {
  3.             GameObject newObject;
  4.             newObject = (GameObject)EditorUtility.InstantiatePrefab(NewType);
  5.             newObject.transform.parent = go.transform.parent;
  6.             newObject.transform.localPosition = go.transform.localPosition;
  7.             newObject.transform.localRotation = go.transform.localRotation;
  8.             newObject.transform.localScale = go.transform.localScale;
  9.  
  10.             DestroyImmediate(go);
  11.         }



참조 : http://forum.unity3d.com/threads/24311-Replace-game-object-with-prefab

반응형
Posted by blueasa
, |

2D 게임을 만들기 위해 유니티에서 이미지를 임포트하면 웬지 모르게 이미지가 뭉게져 보이는데요. 이는 유니티가 3D 엔진이기 때문에, 임포트되는 텍스쳐에 대해서 자동으로 밉맵(Min Map)을 생성하기 때문입니다.

이를 해결하고 선명한 이미지를 만들기 얻기 위해서는 텍스쳐 타입을 "GUI" 로 설정하면 간단히 해결됩니다.

하지만, 만약 "Alpha from Grayscale" 을 사용해 이미지를 투명하게 처리해야할 필요가 있다면 텍스쳐 타입을 "Advanced" 로 선택 후 "Generate Mip Maps" 을 꺼 주시면 됩니다... ^^

마지막으로, 텍스처 "Max Size" 는 실제 게임에서 사용할 크기에 맞게 적절하게 설정하시고.. "Texture Format" 은 웬만하시면 Automatic Truecolor 을 선택하세요... 2D 게임의 경우, 압축 이미지를 사용하면 티가 많이 나더군요.. =ㅁ=

참... 쉽죠? ^^ㅋ;;



출처 : http://mobilism.tistory.com/entry/Unity3D-2D-%EA%B2%8C%EC%9E%84%EC%9D%84-%EC%9C%84%ED%95%9C-%ED%85%8D%EC%8A%A4%EC%B3%90-%EC%84%A4%EC%A0%95

반응형
Posted by blueasa
, |

입력된 문자열의 픽셀을 Mesh로 대체하여 표시해 주도록 하는 스크립트 입니다.

문자열의 각각의 문자들의 값을 알아내어, 폰트텍스쳐 정보와 비교하여 원하는 위치에 Mesh를 위치시키는 스크립트입니다.

아래 데모에서 보여지는 <Mesh 1개 = 1 Pixel>와 같습니다.
아래는 프로젝트 파일입니다.

반응형
Posted by blueasa
, |

SpriteManager

Unity3D/Extensions / 2012. 11. 24. 16:41

데모입니다. 축구공 이미지에 물리를 연결해서 제작한 데모입니다.

유니티에서 2D구현을 편하게하기 위해서, 버텍스 설정해서 텍스쳐 씌우고 하는 수작업보다는 그나마 좀더 편하게 사용할 수 있는 SpriteManager가 있습니다. 이거 만든 곳에서 SM2도 만들었는데, 그건 유료구요. 이건 제한없이 사용가능 합니다.

Sprite 조작 및 Animation 도 생성가능해서 2D게임 만드실 때 유용하게 사용하실 수 있습니다.

http://www.unifycommunity.com/wiki/index.php?title=SpriteManager - 유니티 위키입니다. SM에 대한 설명서가 있습니다.


http://www.3dbuzz.com - 메뉴보시면 Unity 메뉴눌러서 카테고리보시면 [Unity Standard] -> [SpriteManager & Unity] 보시면 강좌를 보실 수 있습니다. 이 강좌 결과물이 위 데모와 같습니다.(가입해야함)


위 데모 소스 입니다. (SpriteManager 포함)

SpriteMgr1_src.zip



출처 : http://kpro.tistory.com/63


반응형

'Unity3D > Extensions' 카테고리의 다른 글

ObjectPool  (0) 2014.04.22
인스펙터 상의 GUI를 비활성화 시키고 싶을 때..  (0) 2014.04.02
Save Scene while on play mode  (0) 2014.01.12
Auto-Save Scene on Run  (0) 2014.01.12
Combine Children Extented (sources to share)  (0) 2013.01.17
Posted by blueasa
, |

iTween

Unity3D/iTween / 2012. 11. 24. 16:38

유니티에서 유용한 많이 유명한(?) 무료 스크립트인 iTween 입니다.


            

이 마크만 봐도 아시는 분들이 있을겁니다. 오픈소스이고, 소스코드는 C#기반으로 작성되어 있습니다. 예전에는 자바용으로 작성되어 있었는데, 이제는 c#으로만 작성하나 봅니다. SVN(Subversion)쓰시면 저장소로 받아서 사용하셔도 좋습니다.

이 스크립트의 용도는 유니티안에서 객체의 애니메이션, 이동등 Tweening을 쉽게 해주는 역할을 합니다. 응용해서 사용할 곳이 많은 스크립트입니다.

글보단 영상으로 보는 예제가 확실히 눈에 들어오겠죠.
개발자분께서 직접 사용예제 동영상도 YouTube에 만들어서 올려놓았습니다.


iTween에 보면 많은 애니메이션 타입을 설정해 줄 수 있는데, 아래의 내용을 참고하세요.

enum EaseType{
easeInQuad,
easeOutQuad,
easeInOutQuad,
easeInCubic,
easeOutCubic,
easeInOutCubic,
easeInQuart,
easeOutQuart,
easeInOutQuart,
easeInQuint,
easeOutQuint,
easeInOutQuint,
easeInSine,
easeOutSine,
easeInOutSine,
easeInExpo,
easeOutExpo,
easeInOutExpo,
easeInCirc,
easeOutCirc,
easeInOutCirc,
linear,
spring,
bounce,
easeInBack,
easeOutBack,
easeInOutBack,
elastic,
punch
}
http://www.robertpenner.com/easing/ - flash로 제작된 데모도 있으니 쉽게 참고하실 수 있습니다.(iTween은 이 사이트의 주인장의 기술을 기반으로 사용했습니다.)


- 그리고, 개발자분 블로그에 가시면 여러가지 유용한 정보들을 접하실 수 있습니다.
 Visual iTween Path Editor, Doc Search for Unity, Image Background in Unity, Stressball for Unity, Masking in Unity, Understanding iTween's Callbacks 등등


출처 : http://kpro.tistory.com/72

반응형

'Unity3D > iTween' 카테고리의 다른 글

iTween Visual Editor v0.6.1(with Unity2019+)  (0) 2015.03.04
iTween의 easetype  (0) 2015.03.04
Posted by blueasa
, |

Interpolate

Unity3D/Script / 2012. 11. 22. 16:31

Interpolate

Author: Fernando Zapata (fernando@cpudreams.com)

Contents

 [hide

Description

Interpolation utility functions for easing, Bezier splines, and Catmull-Rom splines. Provides consistent calling conventions across these three interpolation types. Provides low level access via individual easing functions, for example EaseInOutCirc(), Bezier(), and CatmullRom(). Provides high level access using sequence generators, NewEase(), NewBezier(), and NewCatmullRom(). Functionality is available at different levels of abstraction, making the functions easy to use and making your own high level abstractions easy to build.

Usage

You can use the low level functions similar to how you might use Unity's built-in Mathf.Lerp().

var start = 0.0;
var distance = 3.0;
var duration = 2.0;
private var elapsedTime = 0.0;
 
function Update() {
    transform.position.y = Interpolate.EaseOutSine(start, distance,
                                                   elapsedTime, duration);
    elapsedTime += Time.deltaTime;
}

Instead of hard coding the easing function you can use the Ease(EaseType) function to look up a concrete easing function.

// set using Unity's property inspector to any easing type (ex. EaseInCirc)
var easeType : EaseType; 
var ease : Function;
 
function Awake() {
  ease = Interpolate.Ease(easeType); // get easing function by type
   // ease can now be used:
  // transform.position.y = ease(start, distance, elapsedTime, duration);
}

You can also use higher level sequence generator functions to quickly build a reusable component. For example, this SplinePath component will move a GameObject smoothly along a path using Catmull-Rom to make sure the GameObject passes through each control point. Using the interpolation utility function this component takes less than ten lines of code (minus the visualization function OnDrawGizmos).

// SplinePath.js
var path : Transform[]; // path's control points
var loop : boolean;
// number of nodes to generate between path nodes, to smooth out the path
var betweenNodeCount : int;
private var nodes : IEnumerator;
 
function Awake() {
  nodes = Interpolate.NewCatmullRom(path, betweenNodeCount, loop);
}
 
function Update() {
  if (nodes.MoveNext()) {
    transform.position = nodes.Current;
  }
}
 
// optional, use gizmos to draw the path in the editor
function OnDrawGizmos() {
  if (path && path.length >= 2) {
 
    // draw control points
    for (var i = 0; i < path.length; i++) {
      Gizmos.DrawWireSphere(path[i].position, 0.15);
    }
 
    // draw spline curve using line segments
    var sequence = Interpolate.NewCatmullRom(path, betweenNodeCount, loop);
    var firstPoint = path[0].position;
    var segmentStart = firstPoint;
    sequence.MoveNext(); // skip the first point
    // use "for in" syntax instead of sequence.MoveNext() when convenient
    for (var segmentEnd in sequence) {
      Gizmos.DrawLine(segmentStart, segmentEnd);
      segmentStart = segmentEnd;
      // prevent infinite loop, when attribute loop == true
      if (segmentStart == firstPoint) { break; }
    }
  }
}

SplinePath.png


For the complete details on all available functions please read the doc comments. If you have any questions feel free to contact me directly at fernando@cpudreams.com.

Code

The code is organized top-down for easy reading.

Interpolate.js

#pragma strict
 
/**
 * Interpolation utility functions: easing, bezier, and catmull-rom.
 * Consider using Unity's Animation curve editor and AnimationCurve class
 * before scripting the desired behaviour using this utility.
 *
 * Interpolation functionality available at different levels of abstraction.
 * Low level access via individual easing functions (ex. EaseInOutCirc),
 * Bezier(), and CatmullRom(). High level access using sequence generators,
 * NewEase(), NewBezier(), and NewCatmullRom().
 *
 * Sequence generators are typically used as follows:
 *
 * var sequence = Interpolate.New[Ease|Bezier|CatmulRom](configuration);
 * for (var newPoint in sequence) {
 *   transform.position = newPoint;
 *   yield;
 * }
 *
 * Or:
 *
 * var sequence = Interpolate.New[Ease|Bezier|CatmulRom](configuration);
 * function Update() {
 *   if (sequence.MoveNext()) {
 *     transform.position = sequence.Current;
 *   }
 * }
 *
 * The low level functions work similarly to Unity's built in Lerp and it is
 * up to you to track and pass in elapsedTime and duration on every call. The
 * functions take this form (or the logical equivalent for Bezier() and
 * CatmullRom()).
 *
 * transform.position = ease(start, distance, elapsedTime, duration);
 *
 * For convenience in configuration you can use the Ease(EaseType) function to
 * look up a concrete easing function:
 *
 * var easeType : EaseType; // set using Unity's property inspector
 * var ease : Function; // easing of a particular EaseType
 * function Awake() {
 *   ease = Interpolate.Ease(easeType);
 * }
 *
 * @author Fernando Zapata (fernando@cpudreams.com)
 */
 
/**
 * Different methods of easing interpolation.
 */
enum EaseType {
  Linear,
  EaseInQuad,
  EaseOutQuad,
  EaseInOutQuad,
  EaseInCubic,
  EaseOutCubic,
  EaseInOutCubic,
  EaseInQuart,
  EaseOutQuart,
  EaseInOutQuart,
  EaseInQuint,
  EaseOutQuint,
  EaseInOutQuint,
  EaseInSine,
  EaseOutSine,
  EaseInOutSine,
  EaseInExpo,
  EaseOutExpo,
  EaseInOutExpo,
  EaseInCirc,
  EaseOutCirc,
  EaseInOutCirc
}
 
/**
 * Returns sequence generator from start to end over duration using the
 * given easing function. The sequence is generated as it is accessed
 * using the Time.deltaTime to calculate the portion of duration that has
 * elapsed.
 */
static function NewEase(ease : Function, start : Vector3,
                        end : Vector3, duration : float) : IEnumerator {
  var timer = NewTimer(duration);
  return NewEase(ease, start, end, duration, timer);
}
 
/**
 * Instead of easing based on time, generate n interpolated points (slices)
 * between the start and end positions.
 */
static function NewEase(ease : Function, start : Vector3,
                        end : Vector3, slices : int) : IEnumerator {
  var counter = NewCounter(0, slices + 1, 1);
  return NewEase(ease, start, end, slices + 1, counter);
}
 
/**
 * Generic easing sequence generator used to implement the time and
 * slice variants. Normally you would not use this function directly.
 */
static function NewEase(ease : Function, start : Vector3, end : Vector3,
                        total : float, driver : IEnumerator) : IEnumerator {
  var distance = end - start;
  for (var i in driver) {
    yield Ease(ease, start, distance, i, total);
  }
}
 
/**
 * Vector3 interpolation using given easing method. Easing is done independently
 * on all three vector axis.
 */
static function Ease(ease : Function,
                     start : Vector3, distance : Vector3,
                     elapsedTime : float, duration : float) : Vector3 {
  start.x = ease(start.x, distance.x, elapsedTime, duration);
  start.y = ease(start.y, distance.y, elapsedTime, duration);
  start.z = ease(start.z, distance.z, elapsedTime, duration);
  return start;
}
 
/**
 * Returns the static method that implements the given easing type for scalars.
 * Use this method to easily switch between easing interpolation types.
 *
 * All easing methods clamp elapsedTime so that it is always <= duration.
 *
 * var ease = Interpolate.Ease(EaseType.EaseInQuad);
 * i = ease(start, distance, elapsedTime, duration);
 */
static function Ease(type : EaseType) : Function {
  // Source Flash easing functions:
  // http://gizma.com/easing/
  // http://www.robertpenner.com/easing/easing_demo.html
  //
  // Changed to use more friendly variable names, that follow my Lerp
  // conventions:
  // start = b (start value)
  // distance = c (change in value)
  // elapsedTime = t (current time)
  // duration = d (time duration)
 
  var f : Function;
  switch (type) {
  case EaseType.Linear: f = Interpolate.Linear; break;
  case EaseType.EaseInQuad: f = Interpolate.EaseInQuad; break;
  case EaseType.EaseOutQuad: f = Interpolate.EaseOutQuad; break;
  case EaseType.EaseInOutQuad: f = Interpolate.EaseInOutQuad; break;
  case EaseType.EaseInCubic: f = Interpolate.EaseInCubic; break;
  case EaseType.EaseOutCubic: f = Interpolate.EaseOutCubic; break;
  case EaseType.EaseInOutCubic: f = Interpolate.EaseInOutCubic; break;
  case EaseType.EaseInQuart: f = Interpolate.EaseInQuart; break;
  case EaseType.EaseOutQuart: f = Interpolate.EaseOutQuart; break;
  case EaseType.EaseInOutQuart: f = Interpolate.EaseInOutQuart; break;
  case EaseType.EaseInQuint: f = Interpolate.EaseInQuint; break;
  case EaseType.EaseOutQuint: f = Interpolate.EaseOutQuint; break;
  case EaseType.EaseInOutQuint: f = Interpolate.EaseInOutQuint; break;
  case EaseType.EaseInSine: f = Interpolate.EaseInSine; break;
  case EaseType.EaseOutSine: f = Interpolate.EaseOutSine; break;
  case EaseType.EaseInOutSine: f = Interpolate.EaseInOutSine; break;
  case EaseType.EaseInExpo: f = Interpolate.EaseInExpo; break;
  case EaseType.EaseOutExpo: f = Interpolate.EaseOutExpo; break;
  case EaseType.EaseInOutExpo: f = Interpolate.EaseInOutExpo; break;
  case EaseType.EaseInCirc: f = Interpolate.EaseInCirc; break;
  case EaseType.EaseOutCirc: f = Interpolate.EaseOutCirc; break;
  case EaseType.EaseInOutCirc: f = Interpolate.EaseInOutCirc; break;
  }
  return f;
}
 
/**
 * Returns sequence generator from the first node to the last node over
 * duration time using the points in-between the first and last node
 * as control points of a bezier curve used to generate the interpolated points
 * in the sequence. If there are no control points (ie. only two nodes, first
 * and last) then this behaves exactly the same as NewEase(). In other words
 * a zero-degree bezier spline curve is just the easing method. The sequence
 * is generated as it is accessed using the Time.deltaTime to calculate the
 * portion of duration that has elapsed.
 */
static function NewBezier(ease : Function, nodes : Transform[],
                          duration : float) : IEnumerator {
  var timer = NewTimer(duration);
  return NewBezier(ease, nodes, TransformDotPosition, duration, timer);
}
 
/**
 * Instead of interpolating based on time, generate n interpolated points
 * (slices) between the first and last node.
 */
static function NewBezier(ease : Function, nodes : Transform[],
                          slices : int) : IEnumerator {
  var counter = NewCounter(0, slices + 1, 1);
  return NewBezier(ease, nodes, TransformDotPosition, slices + 1, counter);
}
 
/**
 * A Vector3[] variation of the Transform[] NewBezier() function.
 * Same functionality but using Vector3s to define bezier curve.
 */
static function NewBezier(ease : Function, points : Vector3[],
                          duration : float) : IEnumerator {
  var timer = NewTimer(duration);
  return NewBezier(ease, points, Identity, duration, timer);
}
 
/**
 * A Vector3[] variation of the Transform[] NewBezier() function.
 * Same functionality but using Vector3s to define bezier curve.
 */
static function NewBezier(ease : Function, points : Vector3[],
                          slices : int) : IEnumerator {
  var counter = NewCounter(0, slices + 1, 1);
  return NewBezier(ease, points, Identity, slices + 1, counter);
}
 
/**
 * Generic bezier spline sequence generator used to implement the time and
 * slice variants. Normally you would not use this function directly.
 */
static function NewBezier(ease : Function, nodes : IList, toVector3 : Function,
                          maxStep : float, steps : IEnumerator) : IEnumerator {
  // need at least two nodes to spline between
  if (nodes.Count >= 2) {
    // copy nodes array since Bezier is destructive
    var points = new Vector3[nodes.Count];
 
    for (var step in steps) {
      // re-initialize copy before each destructive call to Bezier
      for (var i = 0; i < nodes.Count; i++) {
        points[i] = toVector3(nodes[i]);
      }
      yield Bezier(ease, points, step, maxStep);
      // make sure last value is always generated
    }
  }
}
 
/**
 * A Vector3 n-degree bezier spline.
 *
 * WARNING: The points array is modified by Bezier. See NewBezier() for a
 * safe and user friendly alternative.
 *
 * You can pass zero control points, just the start and end points, for just
 * plain easing. In other words a zero-degree bezier spline curve is just the
 * easing method.
 *
 * @param points start point, n control points, end point
 */
static function Bezier(ease : Function, points : Vector3[],
                        elapsedTime : float, duration : float) : Vector3 {
  // Reference: http://ibiblio.org/e-notes/Splines/Bezier.htm
  // Interpolate the n starting points to generate the next j = (n - 1) points,
  // then interpolate those n - 1 points to generate the next n - 2 points,
  // continue this until we have generated the last point (n - (n - 1)), j = 1.
  // We store the next set of output points in the same array as the
  // input points used to generate them. This works because we store the
  // result in the slot of the input point that is no longer used for this
  // iteration.
  for (var j = points.length - 1; j > 0; j--) {
    for (var i = 0; i < j; i++) {
      points[i].x = ease(points[i].x, points[i + 1].x - points[i].x,
                         elapsedTime, duration);
      points[i].y = ease(points[i].y, points[i + 1].y - points[i].y,
                         elapsedTime, duration);
      points[i].z = ease(points[i].z, points[i + 1].z - points[i].z,
                         elapsedTime, duration);
    }
  }
  return points[0];
}
 
/**
 * Returns sequence generator from the first node, through each control point,
 * and to the last node. N points are generated between each node (slices)
 * using Catmull-Rom.
 */
static function NewCatmullRom(nodes : Transform[], slices : int,
                              loop : boolean) : IEnumerator {
  return NewCatmullRom(nodes, TransformDotPosition, slices, loop);
}
 
/**
 * A Vector3[] variation of the Transform[] NewCatmullRom() function.
 * Same functionality but using Vector3s to define curve.
 */
static function NewCatmullRom(points : Vector3[], slices : int,
                              loop : boolean) : IEnumerator {
  return NewCatmullRom(points, Identity, slices, loop);
}
 
/**
 * Generic catmull-rom spline sequence generator used to implement the
 * Vector3[] and Transform[] variants. Normally you would not use this
 * function directly.
 */
static function NewCatmullRom(nodes : IList, toVector3 : Function,
                              slices : int, loop : boolean) : IEnumerator {
  // need at least two nodes to spline between
  if (nodes.Count >= 2) {
 
    // yield the first point explicitly, if looping the first point
    // will be generated again in the step for loop when interpolating
    // from last point back to the first point
    yield toVector3(nodes[0]);
 
    var last = nodes.Count - 1;
    for (var current = 0; loop || current < last; current++) {
      // wrap around when looping
      if (loop && current > last) {
        current = 0;
      }
      // handle edge cases for looping and non-looping scenarios
      // when looping we wrap around, when not looping use start for previous
      // and end for next when you at the ends of the nodes array
      var previous = (current == 0) ? ((loop) ? last : current) : current - 1;
      var start = current;
      var end = (current == last) ? ((loop) ? 0 : current) : current + 1;
      var next = (end == last) ? ((loop) ? 0 : end) : end + 1;
 
      // adding one guarantees yielding at least the end point
      var stepCount = slices + 1;
      for (var step = 1; step <= stepCount; step++) {
        yield CatmullRom(toVector3(nodes[previous]),
                         toVector3(nodes[start]),
                         toVector3(nodes[end]),
                         toVector3(nodes[next]),
                         step, stepCount);
      }
    }
  }
}
 
/**
 * A Vector3 Catmull-Rom spline. Catmull-Rom splines are similar to bezier
 * splines but have the useful property that the generated curve will go
 * through each of the control points.
 *
 * NOTE: The NewCatmullRom() functions are an easier to use alternative to this
 * raw Catmull-Rom implementation.
 *
 * @param previous the point just before the start point or the start point
 *                 itself if no previous point is available
 * @param start generated when elapsedTime == 0
 * @param end generated when elapsedTime >= duration
 * @param next the point just after the end point or the end point itself if no
 *             next point is available
 */
static function CatmullRom(previous : Vector3, start : Vector3, end :
                           Vector3, next : Vector3, elapsedTime : float,
                           duration : float) : Vector3 {
  // References used:
  // p.266 GemsV1
  //
  // tension is often set to 0.5 but you can use any reasonable value:
  // http://www.cs.cmu.edu/~462/projects/assn2/assn2/catmullRom.pdf
  //
  // bias and tension controls:
  // http://local.wasp.uwa.edu.au/~pbourke/miscellaneous/interpolation/
 
  var percentComplete = elapsedTime / duration;
  var percentCompleteSquared = percentComplete * percentComplete;
  var percentCompleteCubed = percentCompleteSquared * percentComplete;
 
  return previous * (-0.5*percentCompleteCubed +
                     percentCompleteSquared -
                     0.5*percentComplete) +
    start * (1.5*percentCompleteCubed +
             -2.5*percentCompleteSquared + 1.0) +
    end * (-1.5*percentCompleteCubed +
           2.0*percentCompleteSquared +
           0.5*percentComplete) +
    next * (0.5*percentCompleteCubed -
            0.5*percentCompleteSquared);
}
 
/**
 * Sequence of eleapsedTimes until elapsedTime is >= duration.
 *
 * Note: elapsedTimes are calculated using the value of Time.deltatTime each
 * time a value is requested.
 */
static function NewTimer(duration : float) : IEnumerator {
  var elapsedTime = 0.0;
  while (elapsedTime < duration) {
    yield elapsedTime;
    elapsedTime += Time.deltaTime;
    // make sure last value is never skipped
    if (elapsedTime >= duration) {
      yield elapsedTime;
    }
  }
}
 
/**
 * Generates sequence of integers from start to end (inclusive) one step
 * at a time.
 */
static function NewCounter(start : int, end : int, step : int) : IEnumerator {
  for (var i = start; i <= end; i += step) {
    yield i;
  }
}
 
static function Identity(v : Vector3) : Vector3 {
  return v;
}
 
static function TransformDotPosition(t : Transform) : Vector3 {
  return t.position;
}
 
/**
 * Linear interpolation (same as Mathf.Lerp)
 */
static function Linear(start : float, distance : float,
                       elapsedTime : float, duration : float) : float {
  // clamp elapsedTime to be <= duration
  if (elapsedTime > duration) { elapsedTime = duration; }
  return distance * (elapsedTime / duration) + start;
}
 
/**
 * quadratic easing in - accelerating from zero velocity
 */
static function EaseInQuad(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime so that it cannot be greater than duration
  elapsedTime = (elapsedTime > duration) ? 1.0 : elapsedTime / duration;
  return distance*elapsedTime*elapsedTime + start;
}
 
/**
 * quadratic easing out - decelerating to zero velocity
 */
static function EaseOutQuad(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime so that it cannot be greater than duration
  elapsedTime = (elapsedTime > duration) ? 1.0 : elapsedTime / duration;
  return -distance * elapsedTime*(elapsedTime-2) + start;
}
 
/**
 * quadratic easing in/out - acceleration until halfway, then deceleration
 */
static function EaseInOutQuad(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime so that it cannot be greater than duration
  elapsedTime = (elapsedTime > duration) ? 2.0 : elapsedTime / (duration / 2);
  if (elapsedTime < 1) return distance/2*elapsedTime*elapsedTime + start;
  elapsedTime--;
  return -distance/2 * (elapsedTime*(elapsedTime-2) - 1) + start;
}
 
/**
 * cubic easing in - accelerating from zero velocity
 */
static function EaseInCubic(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime so that it cannot be greater than duration
  elapsedTime = (elapsedTime > duration) ? 1.0 : elapsedTime / duration;
  return distance*elapsedTime*elapsedTime*elapsedTime + start;
}
 
/**
 * cubic easing out - decelerating to zero velocity
 */
static function EaseOutCubic(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime so that it cannot be greater than duration
  elapsedTime = (elapsedTime > duration) ? 1.0 : elapsedTime / duration;
  elapsedTime--;
  return distance*(elapsedTime*elapsedTime*elapsedTime + 1) + start;
}
 
/**
 * cubic easing in/out - acceleration until halfway, then deceleration
 */
static function EaseInOutCubic(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime so that it cannot be greater than duration
  elapsedTime = (elapsedTime > duration) ? 2.0 : elapsedTime / (duration / 2);
  if (elapsedTime < 1) return distance/2*elapsedTime*elapsedTime*elapsedTime +
                         start;
  elapsedTime -= 2;
  return distance/2*(elapsedTime*elapsedTime*elapsedTime + 2) + start;
}
 
/**
 * quartic easing in - accelerating from zero velocity
 */
static function EaseInQuart(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime so that it cannot be greater than duration
  elapsedTime = (elapsedTime > duration) ? 1.0 : elapsedTime / duration;
  return distance*elapsedTime*elapsedTime*elapsedTime*elapsedTime + start;
}
 
/**
 * quartic easing out - decelerating to zero velocity
 */
static function EaseOutQuart(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime so that it cannot be greater than duration
  elapsedTime = (elapsedTime > duration) ? 1.0 : elapsedTime / duration;
  elapsedTime--;
  return -distance * (elapsedTime*elapsedTime*elapsedTime*elapsedTime - 1) +
                         start;
}
 
/**
 * quartic easing in/out - acceleration until halfway, then deceleration
 */
static function EaseInOutQuart(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime so that it cannot be greater than duration
  elapsedTime = (elapsedTime > duration) ? 2.0 : elapsedTime / (duration / 2);
  if (elapsedTime < 1) return distance/2*
                         elapsedTime*elapsedTime*elapsedTime*elapsedTime +
                         start;
  elapsedTime -= 2;
  return -distance/2 * (elapsedTime*elapsedTime*elapsedTime*elapsedTime - 2) +
                         start;
}
 
 
/**
 * quintic easing in - accelerating from zero velocity
 */
static function EaseInQuint(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime so that it cannot be greater than duration
  elapsedTime = (elapsedTime > duration) ? 1.0 : elapsedTime / duration;
  return distance*elapsedTime*elapsedTime*elapsedTime*elapsedTime*elapsedTime +
                         start;
}
 
/**
 * quintic easing out - decelerating to zero velocity
 */
static function EaseOutQuint(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime so that it cannot be greater than duration
  elapsedTime = (elapsedTime > duration) ? 1.0 : elapsedTime / duration;
  elapsedTime--;
  return distance * (elapsedTime * elapsedTime * elapsedTime * elapsedTime *
                     elapsedTime + 1) + start;
}
 
/**
 * quintic easing in/out - acceleration until halfway, then deceleration
 */
static function EaseInOutQuint(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime so that it cannot be greater than duration
  elapsedTime = (elapsedTime > duration) ? 2.0 : elapsedTime / (duration / 2);
  if (elapsedTime < 1) return distance/2 * elapsedTime * elapsedTime *
                         elapsedTime * elapsedTime * elapsedTime + start;
  elapsedTime -= 2;
  return distance/2 * (elapsedTime * elapsedTime * elapsedTime * elapsedTime *
                       elapsedTime + 2) + start;
}
 
/**
 * sinusoidal easing in - accelerating from zero velocity
 */
static function EaseInSine(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime to be <= duration
  if (elapsedTime > duration) { elapsedTime = duration; }
  return -distance * Mathf.Cos(elapsedTime/duration * (Mathf.PI/2)) +
                         distance + start;
}
 
/**
 * sinusoidal easing out - decelerating to zero velocity
 */
static function EaseOutSine(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime to be <= duration
  if (elapsedTime > duration) { elapsedTime = duration; }
  return distance * Mathf.Sin(elapsedTime/duration * (Mathf.PI/2)) + start;
}
 
/**
 * sinusoidal easing in/out - accelerating until halfway, then decelerating
 */
static function EaseInOutSine(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime to be <= duration
  if (elapsedTime > duration) { elapsedTime = duration; }
  return -distance/2 * (Mathf.Cos(Mathf.PI*elapsedTime/duration) - 1) + start;
}
 
/**
 * exponential easing in - accelerating from zero velocity
 */
static function EaseInExpo(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime to be <= duration
  if (elapsedTime > duration) { elapsedTime = duration; }
  return distance * Mathf.Pow( 2, 10 * (elapsedTime/duration - 1) ) + start;
}
 
/**
 * exponential easing out - decelerating to zero velocity
 */
static function EaseOutExpo(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime to be <= duration
  if (elapsedTime > duration) { elapsedTime = duration; }
  return distance * ( -Mathf.Pow( 2, -10 * elapsedTime/duration ) + 1 ) + start;
}
 
/**
 * exponential easing in/out - accelerating until halfway, then decelerating
 */
static function EaseInOutExpo(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime so that it cannot be greater than duration
  elapsedTime = (elapsedTime > duration) ? 2.0 : elapsedTime / (duration / 2);
  if (elapsedTime < 1) return distance/2 *
                         Mathf.Pow( 2, 10 * (elapsedTime - 1) ) + start;
  elapsedTime--;
  return distance/2 * ( -Mathf.Pow( 2, -10 * elapsedTime) + 2 ) + start;
}
 
/**
 * circular easing in - accelerating from zero velocity
 */
static function EaseInCirc(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime so that it cannot be greater than duration
  elapsedTime = (elapsedTime > duration) ? 1.0 : elapsedTime / duration;
  return -distance * (Mathf.Sqrt(1 - elapsedTime*elapsedTime) - 1) + start;
}
 
/**
 * circular easing out - decelerating to zero velocity
 */
static function EaseOutCirc(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime so that it cannot be greater than duration
  elapsedTime = (elapsedTime > duration) ? 1.0 : elapsedTime / duration;
  elapsedTime--;
  return distance * Mathf.Sqrt(1 - elapsedTime*elapsedTime) + start;
}
 
/**
 * circular easing in/out - acceleration until halfway, then deceleration
 */
static function EaseInOutCirc(start : float, distance : float,
                     elapsedTime : float, duration : float) : float {
  // clamp elapsedTime so that it cannot be greater than duration
  elapsedTime = (elapsedTime > duration) ? 2.0 : elapsedTime / (duration / 2);
  if (elapsedTime < 1) return -distance/2 *
                         (Mathf.Sqrt(1 - elapsedTime*elapsedTime) - 1) + start;
  elapsedTime -= 2;
  return distance/2 * (Mathf.Sqrt(1 - elapsedTime*elapsedTime) + 1) + start;
}

Version C#: Andrea85cs 02:55, 5 April 2011 (PDT)

Interpolate.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/**
 * Interpolation utility functions: easing, bezier, and catmull-rom.
 * Consider using Unity's Animation curve editor and AnimationCurve class
 * before scripting the desired behaviour using this utility.
 *
 * Interpolation functionality available at different levels of abstraction.
 * Low level access via individual easing functions (ex. EaseInOutCirc),
 * Bezier(), and CatmullRom(). High level access using sequence generators,
 * NewEase(), NewBezier(), and NewCatmullRom().
 *
 * Sequence generators are typically used as follows:
 *
 * IEnumerable<Vector3> sequence = Interpolate.New[Ease|Bezier|CatmulRom](configuration);
 * foreach (Vector3 newPoint in sequence) {
 *   transform.position = newPoint;
 *   yield return WaitForSeconds(1.0f);
 * }
 *
 * Or:
 *
 * IEnumerator<Vector3> sequence = Interpolate.New[Ease|Bezier|CatmulRom](configuration).GetEnumerator();
 * function Update() {
 *   if (sequence.MoveNext()) {
 *     transform.position = sequence.Current;
 *   }
 * }
 *
 * The low level functions work similarly to Unity's built in Lerp and it is
 * up to you to track and pass in elapsedTime and duration on every call. The
 * functions take this form (or the logical equivalent for Bezier() and CatmullRom()).
 *
 * transform.position = ease(start, distance, elapsedTime, duration);
 *
 * For convenience in configuration you can use the Ease(EaseType) function to
 * look up a concrete easing function:
 * 
 *  [SerializeField]
 *  Interpolate.EaseType easeType; // set using Unity's property inspector
 *  Interpolate.Function ease; // easing of a particular EaseType
 * function Awake() {
 *   ease = Interpolate.Ease(easeType);
 * }
 *
 * @author Fernando Zapata (fernando@cpudreams.com)
 * @Traduzione Andrea85cs (andrea85cs@dynematica.it)
 */
 
public class Interpolate {
 
 
    /**
 * Different methods of easing interpolation.
 */
    public enum EaseType {
        Linear,
        EaseInQuad,
        EaseOutQuad,
        EaseInOutQuad,
        EaseInCubic,
        EaseOutCubic,
        EaseInOutCubic,
        EaseInQuart,
        EaseOutQuart,
        EaseInOutQuart,
        EaseInQuint,
        EaseOutQuint,
        EaseInOutQuint,
        EaseInSine,
        EaseOutSine,
        EaseInOutSine,
        EaseInExpo,
        EaseOutExpo,
        EaseInOutExpo,
        EaseInCirc,
        EaseOutCirc,
        EaseInOutCirc
    }
 
    /**
    * Sequence of eleapsedTimes until elapsedTime is >= duration.
    *
    * Note: elapsedTimes are calculated using the value of Time.deltatTime each
    * time a value is requested.
    */
    static Vector3 Identity(Vector3 v) {
        return v;
    }
 
    static Vector3 TransformDotPosition(Transform t) {
        return t.position;
    }
 
 
    static IEnumerable<float> NewTimer(float duration) {
        float elapsedTime = 0.0f;
        while (elapsedTime < duration) {
            yield return elapsedTime;
            elapsedTime += Time.deltaTime;
            // make sure last value is never skipped
            if (elapsedTime >= duration) {
                yield return elapsedTime;
            }
        }
    }
 
    public delegate Vector3 ToVector3<T>(T v);
    public delegate float Function(float a, float b, float c, float d);
 
    /**
     * Generates sequence of integers from start to end (inclusive) one step
     * at a time.
     */
    static IEnumerable<float> NewCounter(int start, int end, int step) {
        for (int i = start; i <= end; i += step) {
            yield return i;
        }
    }
 
    /**
     * Returns sequence generator from start to end over duration using the
     * given easing function. The sequence is generated as it is accessed
     * using the Time.deltaTime to calculate the portion of duration that has
     * elapsed.
     */
    public static IEnumerator NewEase(Function ease, Vector3 start, Vector3 end, float duration) {
        IEnumerable<float> timer = Interpolate.NewTimer(duration);
        return NewEase(ease, start, end, duration, timer);
    }
 
    /**
     * Instead of easing based on time, generate n interpolated points (slices)
     * between the start and end positions.
     */
    public static IEnumerator NewEase(Function ease, Vector3 start, Vector3 end, int slices) {
        IEnumerable<float> counter = Interpolate.NewCounter(0, slices + 1, 1);
        return NewEase(ease, start, end, slices + 1, counter);
    }
 
 
 
    /**
     * Generic easing sequence generator used to implement the time and
     * slice variants. Normally you would not use this function directly.
     */
    static IEnumerator NewEase(Function ease, Vector3 start, Vector3 end, float total, IEnumerable<float> driver) {
        Vector3 distance = end - start;
        foreach (float i in driver) {
            yield return Ease(ease, start, distance, i, total);
        }
    }
 
    /**
     * Vector3 interpolation using given easing method. Easing is done independently
     * on all three vector axis.
     */
    static Vector3 Ease(Function ease, Vector3 start, Vector3 distance, float elapsedTime, float duration) {
        start.x = ease(start.x, distance.x, elapsedTime, duration);
        start.y = ease(start.y, distance.y, elapsedTime, duration);
        start.z = ease(start.z, distance.z, elapsedTime, duration);
        return start;
    }
 
    /**
     * Returns the static method that implements the given easing type for scalars.
     * Use this method to easily switch between easing interpolation types.
     *
     * All easing methods clamp elapsedTime so that it is always <= duration.
     *
     * var ease = Interpolate.Ease(EaseType.EaseInQuad);
     * i = ease(start, distance, elapsedTime, duration);
     */
    public static Function Ease(EaseType type) {
        // Source Flash easing functions:
        // http://gizma.com/easing/
        // http://www.robertpenner.com/easing/easing_demo.html
        //
        // Changed to use more friendly variable names, that follow my Lerp
        // conventions:
        // start = b (start value)
        // distance = c (change in value)
        // elapsedTime = t (current time)
        // duration = d (time duration)
 
        Function f = null;
        switch (type) {
            case EaseType.Linear: f = Interpolate.Linear; break;
            case EaseType.EaseInQuad: f = Interpolate.EaseInQuad; break;
            case EaseType.EaseOutQuad: f = Interpolate.EaseOutQuad; break;
            case EaseType.EaseInOutQuad: f = Interpolate.EaseInOutQuad; break;
            case EaseType.EaseInCubic: f = Interpolate.EaseInCubic; break;
            case EaseType.EaseOutCubic: f = Interpolate.EaseOutCubic; break;
            case EaseType.EaseInOutCubic: f = Interpolate.EaseInOutCubic; break;
            case EaseType.EaseInQuart: f = Interpolate.EaseInQuart; break;
            case EaseType.EaseOutQuart: f = Interpolate.EaseOutQuart; break;
            case EaseType.EaseInOutQuart: f = Interpolate.EaseInOutQuart; break;
            case EaseType.EaseInQuint: f = Interpolate.EaseInQuint; break;
            case EaseType.EaseOutQuint: f = Interpolate.EaseOutQuint; break;
            case EaseType.EaseInOutQuint: f = Interpolate.EaseInOutQuint; break;
            case EaseType.EaseInSine: f = Interpolate.EaseInSine; break;
            case EaseType.EaseOutSine: f = Interpolate.EaseOutSine; break;
            case EaseType.EaseInOutSine: f = Interpolate.EaseInOutSine; break;
            case EaseType.EaseInExpo: f = Interpolate.EaseInExpo; break;
            case EaseType.EaseOutExpo: f = Interpolate.EaseOutExpo; break;
            case EaseType.EaseInOutExpo: f = Interpolate.EaseInOutExpo; break;
            case EaseType.EaseInCirc: f = Interpolate.EaseInCirc; break;
            case EaseType.EaseOutCirc: f = Interpolate.EaseOutCirc; break;
            case EaseType.EaseInOutCirc: f = Interpolate.EaseInOutCirc; break;
        }
        return f;
    }
 
    /**
     * Returns sequence generator from the first node to the last node over
     * duration time using the points in-between the first and last node
     * as control points of a bezier curve used to generate the interpolated points
     * in the sequence. If there are no control points (ie. only two nodes, first
     * and last) then this behaves exactly the same as NewEase(). In other words
     * a zero-degree bezier spline curve is just the easing method. The sequence
     * is generated as it is accessed using the Time.deltaTime to calculate the
     * portion of duration that has elapsed.
     */
    public static IEnumerable<Vector3> NewBezier(Function ease, Transform[] nodes, float duration) {
        IEnumerable<float> timer = Interpolate.NewTimer(duration);
        return NewBezier<Transform>(ease, nodes, TransformDotPosition, duration, timer);
    }
 
    /**
     * Instead of interpolating based on time, generate n interpolated points
     * (slices) between the first and last node.
     */
    public static IEnumerable<Vector3> NewBezier(Function ease, Transform[] nodes, int slices) {
        IEnumerable<float> counter = NewCounter(0, slices + 1, 1);
        return NewBezier<Transform>(ease, nodes, TransformDotPosition, slices + 1, counter);
    }
 
    /**
     * A Vector3[] variation of the Transform[] NewBezier() function.
     * Same functionality but using Vector3s to define bezier curve.
     */
    public static IEnumerable<Vector3> NewBezier(Function ease, Vector3[] points, float duration) {
        IEnumerable<float> timer = NewTimer(duration);
        return NewBezier<Vector3>(ease, points, Identity, duration, timer);
    }
 
    /**
     * A Vector3[] variation of the Transform[] NewBezier() function.
     * Same functionality but using Vector3s to define bezier curve.
     */
    public static IEnumerable<Vector3> NewBezier(Function ease, Vector3[] points, int slices) {
        IEnumerable<float> counter = NewCounter(0, slices + 1, 1);
        return NewBezier<Vector3>(ease, points, Identity, slices + 1, counter);
    }
 
    /**
     * Generic bezier spline sequence generator used to implement the time and
     * slice variants. Normally you would not use this function directly.
     */
    static IEnumerable<Vector3> NewBezier<T>(Function ease, IList nodes, ToVector3<T> toVector3, float maxStep, IEnumerable<float> steps) {
        // need at least two nodes to spline between
        if (nodes.Count >= 2) {
            // copy nodes array since Bezier is destructive
            Vector3[] points = new Vector3[nodes.Count];
 
            foreach (float step in steps) {
                // re-initialize copy before each destructive call to Bezier
                for (int i = 0; i < nodes.Count; i++) {
                    points[i] = toVector3((T)nodes[i]);
                }
                yield return Bezier(ease, points, step, maxStep);
                // make sure last value is always generated
            }
        }
    }
 
    /**
     * A Vector3 n-degree bezier spline.
     *
     * WARNING: The points array is modified by Bezier. See NewBezier() for a
     * safe and user friendly alternative.
     *
     * You can pass zero control points, just the start and end points, for just
     * plain easing. In other words a zero-degree bezier spline curve is just the
     * easing method.
     *
     * @param points start point, n control points, end point
     */
    static Vector3 Bezier(Function ease, Vector3[] points, float elapsedTime, float duration) {
        // Reference: http://ibiblio.org/e-notes/Splines/Bezier.htm
        // Interpolate the n starting points to generate the next j = (n - 1) points,
        // then interpolate those n - 1 points to generate the next n - 2 points,
        // continue this until we have generated the last point (n - (n - 1)), j = 1.
        // We store the next set of output points in the same array as the
        // input points used to generate them. This works because we store the
        // result in the slot of the input point that is no longer used for this
        // iteration.
        for (int j = points.Length - 1; j > 0; j--) {
            for (int i = 0; i < j; i++) {
                points[i].x = ease(points[i].x, points[i + 1].x - points[i].x, elapsedTime, duration);
                points[i].y = ease(points[i].y, points[i + 1].y - points[i].y, elapsedTime, duration);
                points[i].z = ease(points[i].z, points[i + 1].z - points[i].z, elapsedTime, duration);
            }
        }
        return points[0];
    }
 
    /**
     * Returns sequence generator from the first node, through each control point,
     * and to the last node. N points are generated between each node (slices)
     * using Catmull-Rom.
     */
    public static IEnumerable<Vector3> NewCatmullRom(Transform[] nodes, int slices, bool loop) {
        return NewCatmullRom<Transform>(nodes, TransformDotPosition, slices, loop);
    }
 
    /**
     * A Vector3[] variation of the Transform[] NewCatmullRom() function.
     * Same functionality but using Vector3s to define curve.
     */
    public static IEnumerable<Vector3> NewCatmullRom(Vector3[] points, int slices, bool loop) {
        return NewCatmullRom<Vector3>(points, Identity, slices, loop);
    }
 
    /**
     * Generic catmull-rom spline sequence generator used to implement the
     * Vector3[] and Transform[] variants. Normally you would not use this
     * function directly.
     */
    static IEnumerable<Vector3> NewCatmullRom<T>(IList nodes, ToVector3<T> toVector3, int slices, bool loop) {
        // need at least two nodes to spline between
        if (nodes.Count >= 2) {
 
            // yield the first point explicitly, if looping the first point
            // will be generated again in the step for loop when interpolating
            // from last point back to the first point
            yield return toVector3((T)nodes[0]);
 
            int last = nodes.Count - 1;
            for (int current = 0; loop || current < last; current++) {
                // wrap around when looping
                if (loop && current > last) {
                    current = 0;
                }
                // handle edge cases for looping and non-looping scenarios
                // when looping we wrap around, when not looping use start for previous
                // and end for next when you at the ends of the nodes array
                int previous = (current == 0) ? ((loop) ? last : current) : current - 1;
                int start = current;
                int end = (current == last) ? ((loop) ? 0 : current) : current + 1;
                int next = (end == last) ? ((loop) ? 0 : end) : end + 1;
 
                // adding one guarantees yielding at least the end point
                int stepCount = slices + 1;
                for (int step = 1; step <= stepCount; step++) {
                    yield return CatmullRom(toVector3((T)nodes[previous]),
                                     toVector3((T)nodes[start]),
                                     toVector3((T)nodes[end]),
                                     toVector3((T)nodes[next]),
                                     step, stepCount);
                }
            }
        }
    }
 
    /**
     * A Vector3 Catmull-Rom spline. Catmull-Rom splines are similar to bezier
     * splines but have the useful property that the generated curve will go
     * through each of the control points.
     *
     * NOTE: The NewCatmullRom() functions are an easier to use alternative to this
     * raw Catmull-Rom implementation.
     *
     * @param previous the point just before the start point or the start point
     *                 itself if no previous point is available
     * @param start generated when elapsedTime == 0
     * @param end generated when elapsedTime >= duration
     * @param next the point just after the end point or the end point itself if no
     *             next point is available
     */
    static Vector3 CatmullRom(Vector3 previous, Vector3 start, Vector3 end, Vector3 next, 
                                float elapsedTime, float duration) {
        // References used:
        // p.266 GemsV1
        //
        // tension is often set to 0.5 but you can use any reasonable value:
        // http://www.cs.cmu.edu/~462/projects/assn2/assn2/catmullRom.pdf
        //
        // bias and tension controls:
        // http://local.wasp.uwa.edu.au/~pbourke/miscellaneous/interpolation/
 
        float percentComplete = elapsedTime / duration;
        float percentCompleteSquared = percentComplete * percentComplete;
        float percentCompleteCubed = percentCompleteSquared * percentComplete;
 
        return previous * (-0.5f * percentCompleteCubed +
                                   percentCompleteSquared -
                            0.5f * percentComplete) +
                start   * ( 1.5f * percentCompleteCubed +
                           -2.5f * percentCompleteSquared + 1.0f) +
                end     * (-1.5f * percentCompleteCubed +
                            2.0f * percentCompleteSquared +
                            0.5f * percentComplete) +
                next    * ( 0.5f * percentCompleteCubed -
                            0.5f * percentCompleteSquared);
    }
 
 
 
 
    /**
     * Linear interpolation (same as Mathf.Lerp)
     */
    static float Linear(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime to be <= duration
        if (elapsedTime > duration) { elapsedTime = duration; }
        return distance * (elapsedTime / duration) + start;
    }
 
    /**
     * quadratic easing in - accelerating from zero velocity
     */
    static float EaseInQuad(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        return distance * elapsedTime * elapsedTime + start;
    }
 
    /**
     * quadratic easing out - decelerating to zero velocity
     */
    static float EaseOutQuad(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        return -distance * elapsedTime * (elapsedTime - 2) + start;
    }
 
    /**
     * quadratic easing in/out - acceleration until halfway, then deceleration
     */
    static float EaseInOutQuad(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
        if (elapsedTime < 1) return distance / 2 * elapsedTime * elapsedTime + start;
        elapsedTime--;
        return -distance / 2 * (elapsedTime * (elapsedTime - 2) - 1) + start;
    }
 
    /**
     * cubic easing in - accelerating from zero velocity
     */
    static float EaseInCubic(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        return distance * elapsedTime * elapsedTime * elapsedTime + start;
    }
 
    /**
     * cubic easing out - decelerating to zero velocity
     */
    static float EaseOutCubic(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        elapsedTime--;
        return distance * (elapsedTime * elapsedTime * elapsedTime + 1) + start;
    }
 
    /**
     * cubic easing in/out - acceleration until halfway, then deceleration
     */
    static float EaseInOutCubic(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
        if (elapsedTime < 1) return distance / 2 * elapsedTime * elapsedTime * elapsedTime + start;
        elapsedTime -= 2;
        return distance / 2 * (elapsedTime * elapsedTime * elapsedTime + 2) + start;
    }
 
    /**
     * quartic easing in - accelerating from zero velocity
     */
    static float EaseInQuart(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        return distance * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
    }
 
    /**
     * quartic easing out - decelerating to zero velocity
     */
    static float EaseOutQuart(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        elapsedTime--;
        return -distance * (elapsedTime * elapsedTime * elapsedTime * elapsedTime - 1) + start;
    }
 
    /**
     * quartic easing in/out - acceleration until halfway, then deceleration
     */
    static float EaseInOutQuart(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
        if (elapsedTime < 1) return distance / 2 * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
        elapsedTime -= 2;
        return -distance / 2 * (elapsedTime * elapsedTime * elapsedTime * elapsedTime - 2) + start;
    }
 
 
    /**
     * quintic easing in - accelerating from zero velocity
     */
    static float EaseInQuint(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        return distance * elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
    }
 
    /**
     * quintic easing out - decelerating to zero velocity
     */
    static float EaseOutQuint(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        elapsedTime--;
        return distance * (elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + 1) + start;
    }
 
    /**
     * quintic easing in/out - acceleration until halfway, then deceleration
     */
    static float EaseInOutQuint(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2f);
        if (elapsedTime < 1) return distance / 2 * elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
        elapsedTime -= 2;
        return distance / 2 * (elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + 2) + start;
    }
 
    /**
     * sinusoidal easing in - accelerating from zero velocity
     */
    static float EaseInSine(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime to be <= duration
        if (elapsedTime > duration) { elapsedTime = duration; }
        return -distance * Mathf.Cos(elapsedTime / duration * (Mathf.PI / 2)) + distance + start;
    }
 
    /**
     * sinusoidal easing out - decelerating to zero velocity
     */
    static float EaseOutSine(float start, float distance, float elapsedTime, float duration) {
        if (elapsedTime > duration) { elapsedTime = duration; }
        return distance * Mathf.Sin(elapsedTime / duration * (Mathf.PI / 2)) + start;
    }
 
    /**
     * sinusoidal easing in/out - accelerating until halfway, then decelerating
     */
    static float EaseInOutSine(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime to be <= duration
        if (elapsedTime > duration) { elapsedTime = duration; }
        return -distance / 2 * (Mathf.Cos(Mathf.PI * elapsedTime / duration) - 1) + start;
    }
 
    /**
     * exponential easing in - accelerating from zero velocity
     */
    static float EaseInExpo(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime to be <= duration
        if (elapsedTime > duration) { elapsedTime = duration; }
        return distance * Mathf.Pow(2, 10 * (elapsedTime / duration - 1)) + start;
    }
 
    /**
     * exponential easing out - decelerating to zero velocity
     */
    static float EaseOutExpo(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime to be <= duration
        if (elapsedTime > duration) { elapsedTime = duration; }
        return distance * (-Mathf.Pow(2, -10 * elapsedTime / duration) + 1) + start;
    }
 
    /**
     * exponential easing in/out - accelerating until halfway, then decelerating
     */
    static float EaseInOutExpo(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
        if (elapsedTime < 1) return distance / 2 *  Mathf.Pow(2, 10 * (elapsedTime - 1)) + start;
        elapsedTime--;
        return distance / 2 * (-Mathf.Pow(2, -10 * elapsedTime) + 2) + start;
    }
 
    /**
     * circular easing in - accelerating from zero velocity
     */
    static float EaseInCirc(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        return -distance * (Mathf.Sqrt(1 - elapsedTime * elapsedTime) - 1) + start;
    }
 
    /**
     * circular easing out - decelerating to zero velocity
     */
    static float EaseOutCirc(float start, float distance, float elapsedTime, float duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        elapsedTime--;
        return distance * Mathf.Sqrt(1 - elapsedTime * elapsedTime) + start;
    }
 
    /**
     * circular easing in/out - acceleration until halfway, then deceleration
     */
    static float EaseInOutCirc(float start, float distance, float
                         elapsedTime, float duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
        if (elapsedTime < 1) return -distance / 2 * (Mathf.Sqrt(1 - elapsedTime * elapsedTime) - 1) + start;
        elapsedTime -= 2;
        return distance / 2 * (Mathf.Sqrt(1 - elapsedTime * elapsedTime) + 1) + start;
    }
}



출처 : http://wiki.unity3d.com/index.php/Interpolate

반응형
Posted by blueasa
, |