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

카테고리

분류 전체보기 (2737)
Unity3D (817)
Script (91)
Extensions (14)
Effect (3)
NGUI (77)
UGUI (8)
Physics (2)
Shader (36)
Math (1)
Design Pattern (2)
Xml (1)
Tips (200)
Link (22)
World (1)
AssetBundle (25)
Mecanim (2)
Plugins (70)
Trouble Shooting (68)
Encrypt (7)
LightMap (4)
Shadow (4)
Editor (8)
Crash Report (3)
Utility (9)
UnityVS (2)
Facebook SDK (2)
iTween (3)
Font (11)
Ad (14)
Photon (2)
IAP (1)
Google (8)
Android (45)
iOS (41)
Programming (474)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (228)
협업 (58)
3DS Max (3)
Game (12)
Utility (136)
Etc (96)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (53)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday
04-20 00:00

InvokeRepeating

Unity3D/Script / 2012. 12. 7. 16:09
반복 실행하기에 유용한 함수 같아서 체크..

InvokeRepeating (함수명, 시작 시간, 함수호출 후 반복 간격); 


MonoBehaviour.InvokeRepeating

function InvokeRepeating (methodName : String, time : float, repeatRate : float) : void

Description

Invokes the method methodName in time seconds.

After the first invocation repeats calling that function every repeatRate seconds.

JavaScript
// Starting in 2 seconds.
// a projectile will be launched every 0.3 seconds

var projectile : Rigidbody;

InvokeRepeating("LaunchProjectile", 2, 0.3);

function LaunchProjectile () {
var instance : Rigidbody = Instantiate(projectile);
instance.velocity = Random.insideUnitSphere * 5;
}

관련 함수 : http://docs.unity3d.com/Documentation/ScriptReference/MonoBehaviour.CancelInvoke.html

참조 : http://devkorea.co.kr/bbs/board.php?bo_table=m03_qna&wr_id=23031&sca=UNITY&currentId=44



출처 : http://docs.unity3d.com/Documentation/ScriptReference/MonoBehaviour.InvokeRepeating.html

반응형
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
, |

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

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

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

반응형
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
, |



 WaitForSeconds라는 메소드가 있는데 C#에서 쓰러면 조금 까다롭게 형식에 맞춰서 작성해줘야 한다.

위 예제와 같이 Awake라는 메소드에서 시간을 두번 출력할때 첫번째 시간을 출력 한 뒤 5초뒤에 두번째 시간을 출력하고자 하는경우 또는 일정시간마다 반복 재귀호출 되는 메소드를 작성하고 싶을때에
'IEnumerator' 라는 인터페이스를 사용하도록 해당 메소드 앞에 적어줘야 한다.

IEnumerator delayTime()
{
yield return new WaitForSeconds(1);
Debug.Log("time = " + Time.time );
}

 위와 같이 delayTime이라는 메소드를 적어주면 메소드가 호출되면 1를 기다렸다가 1초뒤에 Debug 문장이 실행된다.

IEnumerator 인터페이스를 사용하는 메소드를 실행하기 위해서는 
특정 호출 메소드를 이용해야 하는데
StartCoroutine(delayTime);

다른 메서드들 처럼 그냥 메서드명() 으로 호출하면 실행되지 않고 위와 같이 StartCoroutine(메서드명) 으로 호출해야 한다.


일정시간 간격으로 계속 반복되어 실행되는 메서드를 만들러면
void Start () {
        StartCoroutine(countTime, 1);
 }
  
    IEnumerator countTime(float delayTime)
    {
        Debug.Log("Time = " + Time.time);
        yield return new WaitForSeconds(delayTime);
        StartCoroutine( countTime, 1 );
    }

위와 같이 적어주면 countTime이 waitForSeconds 명령에 의해 일정시간 만큼 딜레이를 한 뒤 자기자신을 재 호출하게되어 
1초 간격으로 계속 반복 호출하도록 할 수 있다.


출처 : http://clack.tistory.com/50

반응형

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

폰트의 픽셀정보로 문자열을 Mesh들로 생성하여 보여주기  (0) 2012.11.24
Interpolate  (0) 2012.11.22
AnimationEvent 추가 방법  (0) 2012.11.21
WaitForSeconds()  (0) 2012.11.21
Attributes 설명 모음  (0) 2012.11.18
Posted by blueasa
, |

  1. var mySkin : GUISkin;
  2. var animatedGameObject : GameObject;
  3. var horOffset = Screen.width * 0.18;
  4. private var animationEvent : AnimationEvent;
  5.  
  6. //Solved: move this function to a script attached to the animatedGameObject
  7. function AnimationEnded(animEvent : AnimationEvent){
  8.  
  9.     animatedGameObject.animation.CrossFade ("idle");
  10.    
  11. }
  12.  
  13. function Start(){
  14.  
  15.     animationEvent = new AnimationEvent();
  16.     animationEvent.time = animatedGameObject.animation["attacco"].clip.length * 0.9;
  17.     //animationEvent.messageOptions = SendMessageOptions.DontRequireReceiver;
  18.     animationEvent.functionName = "AnimationEnded";
  19.     animatedGameObject.animation["animation1"].clip.AddEvent(animationEvent);
  20.     animatedGameObject.animation["animation2"].clip.AddEvent(animationEvent);
  21.    
  22. }
  23.  
  24. function OnGUI () {
  25.     GUI.skin = mySkin;
  26.  
  27.     if(GUI.Button (Rect (Screen.width * 0.0 + horOffset, Screen.height * 0.75,Screen.width * 0.18, Screen.height * 0.25),"")){
  28.    
  29.         animatedGameObject.animation.CrossFade ("animation1");
  30.        
  31.     }
  32.  
  33.     if(GUI.Button (Rect (Screen.width * 0.20 + horOffset, Screen.height * 0.75,Screen.width * 0.18, Screen.height * 0.25),"")){
  34.    
  35.         animatedGameObject.animation.CrossFade ("animation2");
  36.        
  37.     }
  38. }


출처 : http://forum.unity3d.com/threads/19597-AnimationEvent-help-Solved

반응형

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

Interpolate  (0) 2012.11.22
특정시간 뒤에 함수 호출하도록 설정하기 (WaitForSeconds)  (0) 2012.11.21
WaitForSeconds()  (0) 2012.11.21
Attributes 설명 모음  (0) 2012.11.18
애니메이션 스크립팅(Animation Scripting)  (2) 2012.11.16
Posted by blueasa
, |

WaitForSeconds()

Unity3D/Script / 2012. 11. 21. 14:08

/* 유니티를 하면서 여기저기 해외 동영상 강좌도 보고 따라하고 있습니다만 그래도 자바스크립트보단 C#이 간지 있어 보이는거 같아서 C#으로 스크립트를 만들어 보고 있긴한데 어째 자바 스크립트 보단 많이 불편한거 같은 느낌이 드는건 나만의 착각일까요... 그 일례로 WaitForSeconds()함수를 사용하면서 삽질한걸 한번 끄적여 보겠습니다.*/


스크립트 레퍼런스에 나온 설명입니다.

static function WaitForSeconds (seconds : float) : WaitForSeconds

Description

Creates a yield instruction to wait for a given number of seconds

C#

using UnityEngine;

using System.Collections;


public class example : MonoBehaviour 

{

     public IEnumerator Awake() 

    {

          print(Time.time);

yield return new WaitForSeconds(5);
print(Time.time);

    }

}


근데 예제에 저런식으로 썼다가 개코피 터집니다 -ㅅ-;;; 한시간 정도 삽질했네요

구문은 맞는데 일반 함수를 그냥 사용할려고 하면 조금 변형을 가해줘야 됩니다.


public class myCreator : MonoBehaviour 

{

public GameObject box;

public bool readynow = false;


// Use this for initialization

void Start () 

{

}

// Update is called once per frame

void Update () 

{

if( readynow == true )

{

StartCoroutine( MakeBox() );

}

}

IEnumerator MakeBox()

{

readynow = false;

Instantiate( box, transform.position, transform.rotation );

yield return new WaitForSeconds(0.01f);

readynow = true;

}

}


보시면 아시겠지만 StartCoroutine()함수를 사용해서 해주어야 에러가 나질 않아요~

저거 찾는다고 아놔 -ㅅ-;

더불어서 StartCoroutine()함수 스크립트 메뉴얼도 보시겠습니다.

function StartCoroutine (routine : IEnumerator) : Coroutine

Description

Starts a coroutine.

The execution of a coroutine can be paused at any point using the yield statement. The yield return value specifies when the coroutine is resumed. Coroutines are excellent when modelling behaviour over several frames. Coroutines have virtually no performance overhead. StartCoroutine function always returns immediately, however you can yield the result. This will wait until the coroutine has finished execution.

When using JavaScript it is not necessary to use StartCoroutine, the compiler will do this for you. When writing C# code you must call StartCoroutine.

C#
using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
void Start() {
print("Starting " + Time.time);
StartCoroutine(WaitAndPrint(2.0F));
print("Before WaitAndPrint Finishes " + Time.time);
}
IEnumerator WaitAndPrint(float waitTime) {
yield return new WaitForSeconds(waitTime);
print("WaitAndPrint " + Time.time);
}
}

Another Example:
C#
using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
IEnumerator Start() {
print("Starting " + Time.time);
yield return StartCoroutine(WaitAndPrint(2.0F));
print("Done " + Time.time);
}
IEnumerator WaitAndPrint(float waitTime) {
yield return new WaitForSeconds(waitTime);
print("WaitAndPrint " + Time.time);
}
}

아... 줄 정리 해줄려니 귀찮아서 못해먹겠네요 이렇게 해주시면 WaitForSeconds()함수를 에러 없이 사용 하실수 있습니다.
마지막으로 Start함수나 Update함수에 그냥 사용을 가하실려면 이런식으로 해주시면 됩니다.

IEnumerator Start () 
{
int i = 0;
Vector3 pos = transform.position;
for( i = 0; i <= 3; ++i )
{
Instantiate( myPrefab, new Vector3( pos.x + i * distanceMultiplier, pos.y, pos.z ), transform.rotation );
yield return new WaitForSeconds(0.5f);
Debug.Log( "mode ball" + i );
}
}

Update쪽은 이런식으로 처리 되는지 안되는지 확인을 못해봤으니 그건 직접해보시길~~




반응형
Posted by blueasa
, |

[Unity3D] Attributes 설명 모음

알고 있으면 생산, 작업 효율성을 매우 높일 수 있는 attribute들을 unity에서 제공한다.

1) AddComponentMenu 
기본적으로 스크립트는 유니티의 Component->Scripts 메뉴에 자동추가된다.
자동추가말고 아무데나 맘대로 넣고 싶으면 AddComponentMenu를 사용한다.

[AddComponentMenu("Transform/Follow Transform")]
public class FollowTransform : MonoBehaviour
{
}

2) ContextMenu 
스크립트를 우클릭시 뜨는 context menu에 커맨드를 추가할 수 있다.

public class ContextTesting : MonoBehaviour {
/// Add a context menu named "Do Something" in the inspector
/// of the attached script.
[ContextMenu ("Do Something")]
void DoSomething () {
Debug.Log ("Perform operation");
}
}
이렇게 하면 컨텍스트 메뉴에 Do Something이 나타나고, 선택하면
ContextTesting.DoSomething() 메소드가 호출된다.

3) ExecuteInEditMode 
기본적으로 play mode일 때만 스크립트가 실행되나,
이 attribute를 사용하면 edit mode일 때도 스크립트가 실행되게 한다.
(Update, FixedUpdate, and OnGUI functions)
예제는 이렇다.

using UnityEngine;
using System.Collections;
[ExecuteInEditMode]public class example : MonoBehaviour {
public Transform target;
void Update() {
if (target)
transform.LookAt(target);
}
}

4) HideInInspector 
inspector에서 안보이게 한다.

using UnityEngine;
using System.Collections;
public class example : MonoBehaviour {
[HideInInspector]public int p = 5;
}
더이상 p를 inspector에서 볼 수 없다.
하지만 이전에 이미 inspector를 통해 세팅한 값이 있다면 그 값은
그대로 유지된다.

5) NonSerialized 
앞서 HideInInspector는 값을 유지하지만, 이건 그냥 리셋하여 디폴트값
으로 바꾼다.

class Test 
{
// p will not be shown in the inspector or serialized
[System.NonSerialized]public int p = 5;
}

6) RPC 네트워크 관련된 거라서 당장 필요없으므로 대충 스킵.

7) RequireComponent 
함께 필요한 다른 컴포넌트가 자동으로 추가된다.

[RequireComponent (typeof (Rigidbody))]
public class PlayerScript : MonoBehaviour {
void FixedUpdate() {
rigidbody.AddForce(Vector3.up);
}
}
이렇게 하면 작성하면, PlayerScript추가할 때 Rigidbody도 
같이 추가된다.

8) Serializable
일단 코드를 보면 대충 이런 상황이다.
class Sample : MonoBehaviour {
   public Test aa;
}
class Test
{
  public int p = 5;
  public Color c = Color.white;
}
보통 inspector에서 Sample::a.p, Sample::a.c 요놈들은
안보여서 편집할 수가 없는데,
[System.Serializable]
class Test
{
  public int p = 5;
  public Color c = Color.white;
}
이렇게 해주면 inspector에서 편집가능하다.

9) SerializeField
private필드를 강제로 serialize한다.
그러므로 inspector에서도 편집이 가능해진다.
예제코드는 아래와 같다.

using UnityEngine;
public class SomePerson : MonoBehaviour {
//This field gets serialized because it is public.
public string name = "John";
//This field does not get serialized because it is private.
private int age = 40;
//This field gets serialized even though it is private
//because it has the SerializeField attribute applied.
[SerializeField]
private bool hasHealthPotion = true;
void Update () {
}
}





공식홈페이지 링크


http://unity3d.com/support/documentation/ScriptReference/20_class_hierarchy.Attributes.html


AddComponentMenu : 유니티 메뉴 추가.

// C# example:
[AddComponentMenu("Transform/Follow Transform")]
public class FollowTransform : MonoBehaviour
{
}


ContextMenu : 우클릭 메뉴 추가.

// C# example:
public class ContextTesting : MonoBehaviour {
    /// Add a context menu named "Do Something" in the inspector
    /// of the attached script.
    [ContextMenu ("Do Something")]
    void DoSomething () {
        Debug.Log ("Perform operation");
    }
}


ExecuteInEditMode : 에디트 모드에서 스크립트 실행.

using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
public class example : MonoBehaviour {
    public Transform target;
    void Update() {
        if (target)
            transform.LookAt(target);
        
    }
}


HideInInspector : 인스펙터에서 속성 감추기, 이전 세팅값은 유지.

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
    [HideInInspector]
    public int p = 5;
}


NonSerialized : 인스펙터에서 속성 감추기, 이전 세팅값은 무시.

// C# Example
class Test {
    // p will not be shown in the inspector or serialized
    [System.NonSerialized]
    public int p = 5;
}


RPC : 원격지 호출 함수로 지정, 보내는 쪽과 받는 쪽 모두 다 존재해야 함.

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
    public Transform cubePrefab;
    void OnGUI() {
        if (GUILayout.Button("SpawnBox")) {
            NetworkViewID viewID = Network.AllocateViewID();
            networkView.RPC("SpawnBox", RPCMode.AllBuffered, viewID, transform.position);
        }
    }
    [RPC]
    void SpawnBox(NetworkViewID viewID, Vector3 location) {
        Transform clone;
        clone = Instantiate(cubePrefab, location, Quaternion.identity) as Transform as Transform;
        NetworkView nView;
        nView = clone.GetComponent<NetworkView>();
        nView.viewID = viewID;
    }
}


RequireComponent : 컴포넌트 자동 추가.

[RequireComponent (typeof (Rigidbody))]
public class PlayerScript : MonoBehaviour {
    void FixedUpdate()  {
        rigidbody.AddForce(Vector3.up);
    }
}


Serializable : 인스펙터에 인스턴스의 하위 속성 노출.

// C# Example
[System.Serializable]
class Test
{
    public int p = 5;
    public Color c = Color.white;
}

class Sample : MonoBehaviour 
{
    public Test serializableObj; // 인스펙터에 p, c가 노출된다.
}


SerializeField : 인스펙터에 비공개 멤버 노출.

//C# example
using UnityEngine;

public class SomePerson : MonoBehaviour {
    //This field gets serialized because it is public.
    public string name = "John";

    //This field does not get serialized because it is private.
    private int age = 40;

    //This field gets serialized even though it is private
    //because it has the SerializeField attribute applied.
    [SerializeField]
    private bool hasHealthPotion = true;

    void Update () {
    }
}



출처 : http://smilejsu.tistory.com/432


반응형

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

특정시간 뒤에 함수 호출하도록 설정하기 (WaitForSeconds)  (0) 2012.11.21
AnimationEvent 추가 방법  (0) 2012.11.21
WaitForSeconds()  (0) 2012.11.21
애니메이션 스크립팅(Animation Scripting)  (2) 2012.11.16
FadeInOut  (0) 2012.10.31
Posted by blueasa
, |

애니메이션 스크립팅 Animation Scripting

유니티의 애니메이션 시스템은 멋지게 애니메이션이 적용된 스키닝이 된 캐릭터를 만드는 것을 가능하게 해줍니다. 애니메이션 시스템은 애니메이션 블렌딩 blending, 믹싱 mixing, 가산 additive 애니메이션, 걷기사이클 시간동기화 walk cycle time synchronization, 애니메이션 레이어, 애니메이션 재생에 관한 모든 면에서의 제어 (시간, 속도, 블렌드 웨이트 blend-weights), 버텍스 당 1, 2, 혹은 4개 본 bone 들의 메쉬 스키닝뿐만 아니라 물리 기반의 랙돌 ragdoll 과 절차적 애니메이션 procedural animation 도 지원합니다. 가장 만족스런 결과를 얻기 위해서는Modeling Optimized Characters 페이지의 유니티에서 최적의 성능을 내는 리깅된 캐릭터 생성을 위한 가장 좋은 방법들과 기법들에 대해 읽어 보시는 것을 추천해 드립니다.

애니메이션 캐릭터를 만드는 것은 두 가지와 관련이 있습니다: 세상에서 그들이 움직이게 만들고 그에 따라 캐릭터가 애니메이션을 하게 만드는 것 입니다. 캐릭터를 움직이는 것에 대해 더 알고 싶으시다면 다음 Character Controller page를 참조하세요. 이 페이지는 애니메이션에 촛점을 맞추고 있습니다. 실제 캐릭터들의 애니메이션 적용은 유니티의 스크립팅 인터페이스를 통해 이루어 집니다.

여기에서 미리 셋업이 된 애니메이션 적용 캐릭터가 있는 example demos를 다운로드 받으세요. 이 페이지에서 기본을 익히면 animation script interface도 보시기 바랍니다.

원하신다면 이 페이지에서 다루는 아래의 주제들을 탐구해 보세요:

애니메이션 블렌딩 Animation Blending

오늘날의 게임에서 애니메이션 블렌딩 blending 은 캐릭터의 부드러운 애니메이션을 위해서 필수적인 요소입니다. 애니메이션을 만드는 사람은 각각의 애니메이션을 만듭니다. 예를 들어, 걷고, 뛰고, 쉴 때 idle 동작, 또는 사격하는 애니메이션이 있습니다. 게임 중에서는 어떤 때라도 가만히 있는 idle 애니메이션에서 걷는 애니메이션 또는 반대로 바꿀 수가 있어야 합니다. 물론 사용자는 움직임이 갑작스레 튀지 않고 부드럽게 전환되는 애니메이션을 원할 것입니다.

이때 필요한 것이 바로 애니메이션 블렌딩입니다. 유니티에서는 하나의 같은 캐릭터에 어떤 수의 애니메이션도 넣을 수가 있습니다. 모든 애니메이션들은 최종 애니메이션을 만들기 위해 서로 섞여지거나 더해집니다.

사용자가 할 첫 스텝은 캐릭터를 가만히 쉬는 애니메이션에서 걷는 애니메이션으로 부드럽게 전환하는 것입니다. 스크립트 작성시 작업을 쉽게 하기위해 애니메이션의 랩 모드 Wrap Mode를 `반복 `Loop으로 설정합니다. 그리고 사용자가 만드는 스크립트가 애니메이션이 재생되는 유일한 것이 되게 자동으로 재생되게 Play Automatically`` 를 꺼놓습니다.

캐릭터를 동작시키기 위한 첫 스크립트는 꽤 간단한 편입니다. 사용자가 알아야 할 것은 단지 캐릭터가 얼마나 빨리 움직이는지 감지할 방법과 걷는 애니메이션과 쉬는 애니메이션 사이에 녹아들어 사라지게 합니다. 이 간단한 테스트를 위해서 미리 설정된 입력 축들 input axes 을 사용합니다.

function Update () {
   if (Input.GetAxis("Vertical") > 0.2)
       animation.CrossFade ("walk");
   else
      animation.CrossFade ("idle");
} 

이 스크립트를 실행하기 위해서는:

  1. Assets->Create Other->Javascript를 이용해 자바 스크립트 Javascript 를 만듭니다.
  2. 그 안에 코드를 복사 & 붙여넣기를 합니다
  3. 스크립트를 캐릭터로 드래그하세요 (그것은 애니메이션과 같은 게임 오브젝트여야 합니다)

사용자가 재생 Play 버튼을 누르고, 위방향키를 누르고 있으면 캐릭터가 걷기 시작하고 손가락을 떼면 쉬는 포즈로 돌아갈 것입니다.

애니메이션 레이어 Animation Layer

레이어는 사용자가 애니메이션을 그룹화하고 가중치 weighting 에 우선 순위를 매기는 것을 가능하게 해주는 굉장히 중요한 개념입니다.

유니티 애니메이션 시스템에서 사용자는 원하는 만큼 애니메이션 클립들을 서로 블렌드 할수 있습니다. 사용자는 수동으로 가중치를 주거나 간단히 자동으로 가중치를 주는 animation.CrossFade()를 이용할 수 있습니다.

블렌드 가중치는 적용되기 전에 항상 정규화됩니다 Blend weights are always normalized before being applied.

걷는 것과 뛰는 애니메이션이 있고 둘 모두 1 (100%) 의 가중치를 가진다고 가정해 보세요. 유니티가 최종 애니메이션을 생성할 때 가중치를 정규화 합니다. 즉 걷는 것과 뛰는 애니메이션이 50%씩의 가중치를 각각 부여하게 되는 것입니다.

하지만 대부분의 경우 사용자는 두 개의 애니메이션이 있을 때 어떤 애니메이션이 더 가중치를 적용받을지 우선 순위를 정하길 원합니다. 물론 이때 모든 가중치의 합이 수동으로 100%가 되도록 할 수도 있겠지만 레이어들을 사용하는 것이 훨씬 쉬운 방법이 됩니다.

레이어만들기 예제 Layering Example

한 예로써 사용자가 사격하고, 쉬고, 그리고 걷는 애니메이션이 있다고 가정합니다. 걷는 애니메이션과 쉬는 애니메이션은 플레이어의 속도에 따라 블렌드되어 섞이겠지만, 사격 버튼이 눌러졌을때는 사격하는 애니메이션만이 나와야 합니다. 그러므로 사격 애니메이션은 이들 중 더 높은 우선 순위를 가지게 됩니다.

이것을 위한 가장 쉬운 방법은 사격 중에도 걷고 쉬는 애니메이션을 재생하게 하는 것입니다. 그러기 위해서는 사격 애니메이션을 쉬거나 걷기 보다 높은 레이어로 위치시켜야 하고 이것은 사격 애니메이션이 블렌드 가중치 blend weights 를 가장 우선 순위로 받게 된다는 뜻입니다. 걷기와 쉬기 애니메이션은 사격 애니메이션이 100% 블렌드 가중치를 다 사용하지 않을 때에만 가중치를 받게 됩니다. 그래서 크로스페이딩 CrossFading 으로 사격 애니메이션을 걷기나 쉬기 애니메이션 안에 들여보낼 때 사격 애니메이션의 가중치는 0에서 시작해 짧은 순간에 100%로 가중치가 변할 것입니다. 처음에 걷기와 정지레이어는 블렌드 가중치를 받지만 사격 애니메이션이 완전히 들어오면 (fade in) 가중치를 전혀 받을 수 없게 될 것입니다. 이것은 정확히 우리가 원하던 바입니다!

function Start () {
   // 모든 애니메이션을 룹으로 설정
   animation.wrapMode = WrapMode.Loop;
   // 사격은 제외
   animation["shoot"].wrapMode = WrapMode.Once;

   // 쉬기와 걷기를 아래 레이어로 놓습니다. (디폴트 레이어는 항상 0)
   // 이것은 두 가지를 할 것입니다.
   // - 사격과 쉬기/걷기는 다른 레이어에 있으므로,
   //   크로스페이드 CrossFade 를 호출할 때 그들은 서로의 재생에 영향을 끼치지 않을 것입니다..
   // - 사격은 더 높은 레이어에 있으므로,
   //  페이드-인 (fade-in) 할때 그 애니메이션은 쉬기/걷기 애니메이션을 대체할 것입니다.
   animation["shoot"].layer = 1;

   // 이미 재생되는 애니메이션을 정지시킵니다.Stop animations that are already playing
   //(사용자가 자동재생을 비활성화 시켰을 경우)
   animation.Stop();
}

function Update () {
   // 눌려진 키에 따라서,
   // 걷기나 쉬기 애니메이션을 재생합니다.
   if (Mathf.Abs(Input.GetAxis("Vertical")) > 0.1)
      animation.CrossFade("walk");
   else
      animation.CrossFade("idle");

   // Shoot
   if (Input.GetButtonDown ("Fire1"))
      animation.CrossFade("shoot");
} 

기본 설정으로 animation.Play()나 animation.CrossFade() 는 같은 레이어에 있는 애니메이션을 정지시키거나 사라지게 fade-out 합니다. 이것이 대부분의 경우 이것은 사용자가 원하는 바입니다. 위의 우리의 예제에서는 쉬기/걷기는 사격 애니매이션에 영향을 주지 않으며 그 반대의 경우도 마찬가지 입니다 (원한다면animation.CrossFade의 옵션 파라미터에서 이 것을 바꿀 수 있습니다).

애니메이션 믹싱 Animation Mixing

애니메이션 믹싱은 애니메이션을 몸의 어떤 일 부분에만 적용시켜 게임에서 생성해야 하는 애니메이션의 수를 줄여줍니다. 이것은 그런 애니메이션들이 다른 애니메이션들과 여러 조합으로 이루어져 사용될 수 있다는 뜻입니다.

사용자는 주어진 애니메이션상태 AnimatioState 에 AddMixingTransform()을 호출하여 애니메이션 믹싱 트랜스폼 animation mixing transform 을 다른 애니메이션에 더합니다.

믹싱 예 Mixing Example

믹싱의 한 예로는 손을 흔드는 애니메이션이 있습니다. 사용자는 캐릭터가 쉬거나 걸을 때 이 손 흔드는 애니메이션을 사용하길 원합니다. 애니메이션 믹싱이 없다면 사용자는 걸으며 손 흔드는 것 쉬면서 손흔드는 두개의 애니메이션을 만들어야 할 것입니다. 그러나 만약 사용자가 손 흔드는 애니메이션에 어깨 트랜스폼을 믹싱 트랜스폼으로써 추가하면, 손 흔드는 애니메이션은 어깨 조인트에서 손까지는 완전히 제어할 수 있게 될 것입니다. 나머지 몸은 그것에 의해 영향을 받지 않기 때문에 캐릭터는 쉬거나 걷는 애니메이션을 계속할 것입니다. 그러므로 몸의 나머지 부분이 쉬거나 걷는 동안에 손이 흔들리게 하려면 위와 같은 단 하나의 애니메이션 만이 필요하게 됩니다.

/// 트랜스폼 변수를 사용하여 믹싱 트랜스폼을 더합니다.
var shoulder : Transform;
animation["wave_hand"].AddMixingTransform(shoulder);

경로 path 를 이용한 또 다른 예.

function Start () {
   // 경로를 이용하여 믹싱 트랜스폼을 더합니다.
   var mixTransform : Transform = transform.Find("root/upper_body/left_shoulder");
   animation["wave_hand"].AddMixingTransform(mixTransform);
}

부가 애니메이션 Additive Animations

부가 애니메이션 Additive animation 과 애니메이션 믹싱은 게임을 위해 생성해야 하는 애니메이션 수를 줄이는 것을 줄이고, 얼굴표정 facial 애니메이션을 만드는데 중요한 역할을 합니다.

사용자가 걷거나 뛰면서 방향을 돌때 옆으로 기우는 캐릭터를 만든다고 가정해 봅시다. 이 경우 각각 애니메이션이 필요한 다음과 같은 네가지 조합이 필요하게 됩니다: 왼쪽으로 기울며 걷기 walk-lean-left, 오른쪽으로 기울며 걷기 walk-lean-right, 왼쪽으로 기울며 뛰기 run-lean-left, 오른쪽으로 기울며 뛰기 run-lean-right. 각 조합을 위해 각각 별개의 애니메이션을 만드는 것은 이와 같은 간단한 경우에도 훨씬 더 많은 추가 작업을 시키게 되고, 다른 액션들이 추가될 때마다 조합의 수는 기하급수적으로 늘어날 것입니다. 다행히도 가산 애니메이션 additive animation 과 믹싱은 단순 움직임들의 조합을 위해 각각 따로 애니메이션을 만들어야 하는 번잡함을 줄여 줍니다.

가산 애니메이션의 예 Additive Animation Example

가산 애니메이션은 한 애니메이션의 효과를 재생중인 다른 애니메이션들 위에 겹치게 overlay 합니다. 가산 애니메이션을 만들때 유니티는 애니메이션 클립의 첫번째 프레임과 현재 프레임의 차이를 계산할 것입니다. 그리고 이 차이를 다른 모든 재생 중인 애니메이션 위에 적용합니다.

다시 아까의 예로 돌아가서 이제 사용자는 왼쪽이나 오른쪽으로 기운 애니메이션을 만들면 유니티는 이것을 걷거나 쉬거나 뛰는 동작의 애니메이션 위에 상위 레이어로 놓을 수 있습니다.

이것을 만들기 위한 코드입니다:

private var leanLeft : AnimationState;
private var leanRight : AnimationState;

function Start () {
   leanLeft = animation["leanLeft"];
   leanRight = animation["leanRight"];

   //기우는 애니메이션 lean animation 을 별개의 레이어에 놓아서,
   //CrossFade 를 호출하는 다른 것들이 그것에 영향을 주지 않도록 합니다.
   leanLeft.layer = 10;
   leanRight.layer = 10;

   //기우는 애니메이션을 가산 additive 으로 설정합니다.
   leanLeft.blendMode = AnimationBlendMode.Additive;
   leanRight.blendMode = AnimationBlendMode.Additive;

   //기우는 애니메이션을 ClampForever 로 설정합니다.
   //ClampForever가 설정되면 애니메이션은 클립의 끝에 도달해도
   //자동적으로 정지되지 않습니다.
   leanLeft.wrapMode = WrapMode.ClampForever;
   leanRight.wrapMode = WrapMode.ClampForever;

   //애니메이션을 활성화 Enable 하고 그것을 완전히 들어오게 fade in 합니다.
   //여기서 사용자는 animation.Play 를 사용하지 않습니다. 왜냐하면
   //그것은 업데이트 함수에서 시간을 수동적으로 조절할 수 있기 때문입니다.
   //대신에 사용자는 그냥 애니메이션을 활성화시키고, 그것을 최대 가중치 weight 로 설정합니다.
   leanRight.enabled = true;
   leanLeft.enabled = true;
   leanRight.weight = 1.0;
   leanLeft.weight = 1.0;

   //테스트를 위해서 걷기 애니메이션을 재생한 후 반복 Loop 을 시킵니다.
   animation["walk"].wrapMode = WrapMode.Loop;
   animation.Play("walk");
}

//모든 프레임을 정규화된 normalized 시간으로 설정합니다.
//사용자가 적용시키기 원하는 정도에 따라서 말입니다.
function Update () {
   var lean = Input.GetAxis("Horizontal");
   // normalizedTime 은 첫 프레임때는 0 이고 클립의 마지막 프레임에는 1 이 됩니다.
   leanLeft.normalizedTime = -lean;
   leanRight.normalizedTime = lean;
} 

팁: 가산 애니메이션을 사용할 때 사용자가 가산 애니메이션과 함께 사용된 모든 트랜스폼 위에 가산이 아닌 다른 일반 애니메이션들도 같이 재생하는 것은 굉장히 중요합니다. 그렇지 않으면 그 애니메이션들은 마지막 프레임의 결과 위에 추가되 얹혀질 것입니다. 이것은 확실히 사용자가 원하는 바가 아닐 것입니다.

순차적으로 캐릭터 애니메이션화 하기 Animating Characters Procedurally

사용자는 가끔 캐릭터의 본 bone 을 순차적으로 애니메이션 만들기를 원합니다. 예를 들어, 사용자는 3D공간에서 캐릭터의 머리가 목표점을 추적하는 스크립트에 의해 조정되어 어느 한 점을 바라보기를 원합니다. 다행히도 유니티에서 본 bone 들은 그 스킨된 메쉬를 움직이는 트랜스폼일 뿐이기에 유니티는 이것을 매우 쉽게 할 수 있습니다. 사용자는 스크립트를 써서 어떤 게임오브젝트의 트랜스폼을 다루듯 캐릭터의 본들도 제어할 수 있는 것입니다.

한가지 중요하게 알아야 할 것은 애니메이션 시스템은 Update() 함수 후에 그리고 LateUpdate() 함수 전에 트랜스폼들을 업데이트 한다는 것입니다. 그러므로 만약 사용자가LookAt() 함수를 사용하고 싶다면 사용자는 사용자가 정말로 애니메이션을 오버라이딩 override 하는 것을 확실히 하기 위해 그 함수를 LateUpdate() 안에서 해야만 합니다.

랙돌 Ragdoll 들도 같은 방법으로 생성됩니다. 사용자는 단지 강체 Rigidbodies, 캐릭터 조인트 Character Joints 그리고 캡슐 충돌체 Capsule Colliders 들을 다른 본들에 붙여주기만 하면 됩니다. 그럼 이것은 사용자의 스킨된 캐릭터를 물리적으로 애니메이션화 하게 됩니다.

애니메이션 플레이백과 샘플링 Animation Playback and Sampling

이 섹션은 유니티에서 애니메이션들이 엔진에 의해 재생될 때 어떻게 샘플링이 되는지 설명해 줍니다.

애니메이션 클립 AnimationClips 들은 보통 고정된 프레임 비율로 만들어 집니다. 예를 들어, 사용자는 3D 맥스나 마야에서 프레임 속도 60fps (frames per second) 의 애니메이션을 만들수 있습니다. 유니티에서 그 애니메이션을 불러올 때 이 프레임 속도는 임포터 importer 에 의해 읽히게 되어 불려온 애니메이션의 데이타도 60 fps로 샘플링 됩니다.

하지만 게임은 일반적으로 다양한 프레임 속도로 실행됩니다. 프레임 속도는 어떤 컴퓨터에서는 다른 컴퓨터에서보다 더 높을 수 있고, 특정 순간에 카메라가 보고 있는 뷰의 복잡도에 따라 1초부터 수 초까지 또 다양한 결과를 냅니다. 기본적으로 이것은 게임이 실행되고 있는 프레임의 정확한 속도에 관해 우리는 어떤 가정도 만들수 없다는 것을 의미합니다. 즉 애니메이션이 60 fps로 만들어 졌어도 이것은 56.72 fps나 83.14 fps 혹은 어떤 다른 fps 속도로도 재생될지 모르는 것입니다.

그래서 그 결과로, 유니티는 애니메이션을 원래 지정되어진 프레임 속도가 아닌 이런 다양한 속도로 샘플링을 하게 됩니다. 다행히도 3D 컴퓨터 그래픽 애니메이션은 개별적으로 분리된 프레임이 아닌 연속적인 커브 curve 로 이루어져 있습니다. 이런 커브들은 원래의 애니메이션의 프레임들의 시간들에 딱딱 들어맞는 것이 아니라 어떤 시간에나 샘플링 될 수 있게 되어 있습니다. 그래서 실제적으로는 만약 게임이 만들어진 것보다 더 높은 프레임 속도로 실행이 될 경우 애니메이션은 애니메이션이 제작된 소프트웨어에서보다 더 부드럽고 유연하게 보일 것입니다.

가장 실제적인 상황에서는 사용자는 유니티가 애니메이션을 다양한 프레임 속도 variable fps 로 샘플을 한다는 것은 무시해도 좋습니다. 하지만 만약 사용자가 트랜스폼이나 속성을 어떤 아주 특정한 설정으로 애니메이트하는 애니메이션들에 의지하는 게임플레이 로직을 가지고 있다면, 사용자는 재샘플링 resampling 이 보이지 않는 곳에서 일어난다는 것을 알고 있어야 합니다. 예를 들어, 만약 사용자가 30프레임에 걸쳐 객체가 0에서 180도로 회전하는 애니메이션을 가지고 있고 그리고 그것이 언제 중간까지 도달했는지 코드에서 알고 싶다면, 사용자는 현재 회전 각도가 90도인지 체크하는 조건문을 만들어서 확인하면 안됩니다. 유니티는 애니메이션을 게임속의 다양한 프레임 속도로 샘플링을 하므로, 회전이 90도가 조금 안될때 샘플링을 하고 나중에는 90도 바로 이후에 할지도 모릅니다. 만약 사용자가 애니메이션에서 어떤 특정 점에 다다랐을 때 알림 받기를 원한다면 AnimationEvent를 이용해야 합니다.

또한 다양한 프레임 속도의 샘플링의 결과로 WrapMode.Once 를 사용한 애니메이션이 재생될 때 정확히 마지막 프레임에서 샘플링되지 않을 수도 있다는 것에 주의하세요. 게임의 한 프레임에서는 애니메이션의 마지막 바로 전에 샘플되고, 다음 프레임에서는 시간이 애니메이션의 길이를 초과해 버려 비활성화되고 더 이상 샘플링이 되지 않을지도 모릅니다. 만약 마지막 프레임이 반드시 샘플링이 되게 해야한다면WrapMode.ClampForever를 사용해야 합니다. 이 경우 사용자가 애니메이션을 직접 멈출때까지 마지막 프레임 샘플링을 계속 할 것입니다.


출처 : http://unitykoreawiki.com/index.php?n=KrMain.AnimationScripting

반응형

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

특정시간 뒤에 함수 호출하도록 설정하기 (WaitForSeconds)  (0) 2012.11.21
AnimationEvent 추가 방법  (0) 2012.11.21
WaitForSeconds()  (0) 2012.11.21
Attributes 설명 모음  (0) 2012.11.18
FadeInOut  (0) 2012.10.31
Posted by blueasa
, |