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

카테고리

분류 전체보기 (2834)
Unity3D (883)
Script (93)
Extensions (16)
Effect (3)
NGUI (81)
UGUI (9)
Physics (2)
Shader (39)
Math (1)
Design Pattern (2)
Xml (1)
Tips (203)
Link (26)
World (1)
AssetBundle (25)
Mecanim (2)
Plugins (85)
Trouble Shooting (71)
Encrypt (7)
LightMap (4)
Shadow (4)
Editor (12)
Crash Report (3)
Utility (9)
UnityVS (2)
Facebook SDK (2)
iTween (3)
Font (18)
Ad (14)
Photon (2)
IAP (1)
Google (11)
URP (4)
Android (51)
iOS (46)
Programming (479)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (187)
협업 (64)
3DS Max (3)
Game (12)
Utility (140)
Etc (99)
Link (32)
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

'Unity3D/Script'에 해당되는 글 93건

  1. 2012.11.18 Attributes 설명 모음
  2. 2012.11.16 애니메이션 스크립팅(Animation Scripting) 2
  3. 2012.10.31 FadeInOut

[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
, |

FadeInOut

Unity3D/Script / 2012. 10. 31. 17:19

FadeInOut


Contents

 [hide

JavaScript

Introduction

Author: PsychicParrot

Little script to fade an image (stretched to fit the screen, so use a 1x1 black pixel for a simple black fade in/out).

Simply apply it to your camera (or an empty GameObject), set the texture to use, set the fadeSpeed and call fadeIn() or fadeOut()

Easiest way is probably to apply this script to your main camera in the scene, then wherever you want to fade use something like:

Camera.main.SendMessage("fadeOut");

or

Camera.main.SendMessage("fadeIn");

Enjoy!

Source (FadeInOut.js)

// FadeInOut
//
//--------------------------------------------------------------------
//                        Public parameters
//--------------------------------------------------------------------
 
public var fadeOutTexture : Texture2D;
public var fadeSpeed = 0.3;
 
var drawDepth = -1000;
 
//--------------------------------------------------------------------
//                       Private variables
//--------------------------------------------------------------------
 
private var alpha = 1.0; 
 
private var fadeDir = -1;
 
//--------------------------------------------------------------------
//                       Runtime functions
//--------------------------------------------------------------------
 
//--------------------------------------------------------------------
 
function OnGUI(){
 
	alpha += fadeDir * fadeSpeed * Time.deltaTime;	
	alpha = Mathf.Clamp01(alpha);	
 
	GUI.color.a = alpha;
 
	GUI.depth = drawDepth;
 
	GUI.DrawTexture(Rect(0, 0, Screen.width, Screen.height), fadeOutTexture);
}
 
//--------------------------------------------------------------------
 
function fadeIn(){
	fadeDir = -1;	
}
 
//--------------------------------------------------------------------
 
function fadeOut(){
	fadeDir = 1;	
}
 
function Start(){
	alpha=1;
	fadeIn();
}

Boo

Introduction

Author: Adrian

Extended version written in Boo (put it into "Standard Assets/Scripts" to use it from within JavaScript files).

Main change is that rather than defining a fade speed you can set the duration of the fade in seconds.

Also provides methods to set the fade duration when the method is called and static methods to call the fade script on the main camera (by calling CameraFade.FadeInMain()).

Source (CameraFade.boo)

import UnityEngine
 
class CameraFade (MonoBehaviour): 
 
	# ---------------------------------------- #
	# PUBLIC FIELDS
 
	# Alpha start value
	public startAlpha as single = 1
 
	# Texture used for fading
	public fadeTexture as Texture2D
 
	# Default time a fade takes in seconds
	public fadeDuration as single = 2
 
	# Depth of the gui element
	public guiDepth as int = -1
 
	# Fade into scene at start
	public fadeIntoScene as bool = true
 
	# ---------------------------------------- #
	# PRIVATE FIELDS
 
	# Current alpha of the texture
	currentAlpha as single = 1
 
	# Current duration of the fade
	currentDuration as single
 
	# Direction of the fade
	fadeDirection as int = -1
 
	# Fade alpha to
	targetAlpha as single = 0
 
	# Alpha difference
	alphaDifference as single = 0
 
	# Style for background tiling
	private backgroundStyle as GUIStyle = GUIStyle()
	private dummyTex as Texture2D
 
	# ---------------------------------------- #
	# START FADE METHODS
 
	def FadeIn(duration as single, to as single):
		# Set fade duration
		currentDuration = duration
		# Set target alpha
		targetAlpha = to
		# Difference
		alphaDifference = Mathf.Clamp01(currentAlpha - targetAlpha)
		# Set direction to Fade in
		fadeDirection = -1
 
	def FadeIn():
		FadeIn(fadeDuration, 0)
 
	def FadeIn(duration as single):
		FadeIn(duration, 0)
 
	def FadeOut(duration as single, to as single):
		# Set fade duration
		currentDuration = duration
		# Set target alpha
		targetAlpha = to
		# Difference
		alphaDifference = Mathf.Clamp01(targetAlpha - currentAlpha)
		# Set direction to fade out
		fadeDirection = 1
 
	def FadeOut():
		FadeOut(fadeDuration, 1)
 
	def FadeOut(duration as single):
		FadeOut(duration, 1)
 
	# ---------------------------------------- #
	# STATIC FADING FOR MAIN CAMERA
 
	static def FadeInMain(duration as single, to as single):
		GetInstance().FadeIn(duration, to)
 
	static def FadeInMain():
		GetInstance().FadeIn()
 
	static def FadeInMain(duration as single):
		GetInstance().FadeIn(duration)
 
	static def FadeOutMain(duration as single, to as single):
		GetInstance().FadeOut(duration, to)
 
	static def FadeOutMain():
		GetInstance().FadeOut()
 
	static def FadeOutMain(duration as single):
		GetInstance().FadeOut(duration)
 
	# Get script fom Camera
	static def GetInstance() as CameraFade:
		# Get Script
		fader as CameraFade = Camera.main.GetComponent(CameraFade)
		# Check if script exists
		if (fader == null):
			raise System.Exception("No CameraFade attached to the main camera.")
		return fader
 
	# ---------------------------------------- #
	# SCENE FADEIN
 
	def Start():
		dummyTex = Texture2D(1,1)
		dummyTex.SetPixel(0,0,Color.clear)
		backgroundStyle.normal.background = fadeTexture
		currentAlpha = startAlpha
		if fadeIntoScene:
			FadeIn()
 
	# ---------------------------------------- #
	# FADING METHOD
 
	def OnGUI():
 
		# Fade alpha if active
		if ((fadeDirection == -1 and currentAlpha > targetAlpha)
				or
			(fadeDirection == 1 and currentAlpha < targetAlpha)):
			# Advance fade by fraction of full fade time
			currentAlpha += (fadeDirection * alphaDifference) * (Time.deltaTime / currentDuration)
			# Clamp to 0-1
			currentAlpha = Mathf.Clamp01(currentAlpha)
 
		# Draw only if not transculent
		if (currentAlpha > 0):
			# Draw texture at depth
			GUI.color.a = currentAlpha;
			GUI.depth = guiDepth;
			GUI.Label(Rect(-10, -10, Screen.width + 10, Screen.height + 10), dummyTex, backgroundStyle)


Another Fade Script in C#

Introduction

Author: Kentyman

Hello everybody! I was looking for an easy way to fade the screen and found this page. The scripts here didn't do quite what I wanted, so I rewrote the C# version. This one will fade from any color to any color. Usage: use "SetScreenOverlayColor" to set the initial color, then use "StartFade" to set the target color and the fade duration (in seconds) and start the fade.

Source (CameraFade.cs)

 
// simple fading script
// A texture is stretched over the entire screen. The color of the pixel is set each frame until it reaches its target color.
 
 
using UnityEngine;
 
 
public class CameraFade : MonoBehaviour
{   
	private GUIStyle m_BackgroundStyle = new GUIStyle();		// Style for background tiling
	private Texture2D m_FadeTexture;				// 1x1 pixel texture used for fading
	private Color m_CurrentScreenOverlayColor = new Color(0,0,0,0);	// default starting color: black and fully transparrent
	private Color m_TargetScreenOverlayColor = new Color(0,0,0,0);	// default target color: black and fully transparrent
	private Color m_DeltaColor = new Color(0,0,0,0);		// the delta-color is basically the "speed / second" at which the current color should change
	private int m_FadeGUIDepth = -1000;				// make sure this texture is drawn on top of everything
 
 
	// initialize the texture, background-style and initial color:
	private void Awake()
	{		
		m_FadeTexture = new Texture2D(1, 1);        
        m_BackgroundStyle.normal.background = m_FadeTexture;
		SetScreenOverlayColor(m_CurrentScreenOverlayColor);
 
		// TEMP:
		// usage: use "SetScreenOverlayColor" to set the initial color, then use "StartFade" to set the desired color & fade duration and start the fade
		//SetScreenOverlayColor(new Color(0,0,0,1));
		//StartFade(new Color(1,0,0,1), 5);
	}
 
 
	// draw the texture and perform the fade:
	private void OnGUI()
    {   
		// if the current color of the screen is not equal to the desired color: keep fading!
		if (m_CurrentScreenOverlayColor != m_TargetScreenOverlayColor)
		{			
			// if the difference between the current alpha and the desired alpha is smaller than delta-alpha * deltaTime, then we're pretty much done fading:
			if (Mathf.Abs(m_CurrentScreenOverlayColor.a - m_TargetScreenOverlayColor.a) < Mathf.Abs(m_DeltaColor.a) * Time.deltaTime)
			{
				m_CurrentScreenOverlayColor = m_TargetScreenOverlayColor;
				SetScreenOverlayColor(m_CurrentScreenOverlayColor);
				m_DeltaColor = new Color(0,0,0,0);
			}
			else
			{
				// fade!
				SetScreenOverlayColor(m_CurrentScreenOverlayColor + m_DeltaColor * Time.deltaTime);
			}
		}
 
		// only draw the texture when the alpha value is greater than 0:
		if (m_CurrentScreenOverlayColor.a > 0)
		{			
            		GUI.depth = m_FadeGUIDepth;
            		GUI.Label(new Rect(-10, -10, Screen.width + 10, Screen.height + 10), m_FadeTexture, m_BackgroundStyle);
		}
    }
 
 
	// instantly set the current color of the screen-texture to "newScreenOverlayColor"
	// can be usefull if you want to start a scene fully black and then fade to opague
	public void SetScreenOverlayColor(Color newScreenOverlayColor)
	{
		m_CurrentScreenOverlayColor = newScreenOverlayColor;
		m_FadeTexture.SetPixel(0, 0, m_CurrentScreenOverlayColor);
		m_FadeTexture.Apply();
	}
 
 
	// initiate a fade from the current screen color (set using "SetScreenOverlayColor") towards "newScreenOverlayColor" taking "fadeDuration" seconds
	public void StartFade(Color newScreenOverlayColor, float fadeDuration)
	{
		if (fadeDuration <= 0.0f)		// can't have a fade last -2455.05 seconds!
		{
			SetScreenOverlayColor(newScreenOverlayColor);
		}
		else					// initiate the fade: set the target-color and the delta-color
		{
			m_TargetScreenOverlayColor = newScreenOverlayColor;
			m_DeltaColor = (m_TargetScreenOverlayColor - m_CurrentScreenOverlayColor) / fadeDuration;
		}
	}
}

C#

Introduction

Author: ratmat2000

Extended version written in C# (put it into "Standard Assets/Scripts" to use it from within JavaScript files).

This version is identical to the Boo version but written in C#.

Source (CameraFade.cs)

using UnityEngine;
 
public class CameraFade : MonoBehaviour
{    
    // ---------------------------------------- 
    // 	PUBLIC FIELDS
    // ----------------------------------------
 
    // Alpha start value
    public float startAlpha = 1;
 
    // Texture used for fading
    public Texture2D fadeTexture;
 
    // Default time a fade takes in seconds
    public float fadeDuration = 2;
 
    // Depth of the gui element
    public int guiDepth = -1000;
 
    // Fade into scene at start
    public bool fadeIntoScene = true;
 
    // ---------------------------------------- 
    // 	PRIVATE FIELDS
    // ----------------------------------------
 
    // Current alpha of the texture
    private float currentAlpha = 1;
 
    // Current duration of the fade
    private float currentDuration;
 
    // Direction of the fade
    private int fadeDirection = -1;
 
    // Fade alpha to
    private float targetAlpha = 0;
 
    // Alpha difference
    private float alphaDifference = 0;
 
    // Style for background tiling
    private GUIStyle backgroundStyle = new GUIStyle();
    private Texture2D dummyTex;
 
    // Color object for alpha setting
    Color alphaColor = new Color();
 
    // ---------------------------------------- 
    // 	FADE METHODS
    // ----------------------------------------
 
    public void FadeIn(float duration, float to)
    {
        // Set fade duration
        currentDuration = duration;
        // Set target alpha
        targetAlpha = to;
        // Difference
        alphaDifference = Mathf.Clamp01(currentAlpha - targetAlpha);
        // Set direction to Fade in
        fadeDirection = -1;
    }
 
    public void FadeIn()
    {
        FadeIn(fadeDuration, 0);
    }
 
    public void FadeIn(float duration)
    {
        FadeIn(duration, 0);
    }
 
    public void FadeOut(float duration, float to)
    {
        // Set fade duration
        currentDuration = duration;
        // Set target alpha
        targetAlpha = to;
        // Difference
        alphaDifference = Mathf.Clamp01(targetAlpha - currentAlpha);
        // Set direction to fade out
        fadeDirection = 1;
    }
 
    public void FadeOut()
    {
        FadeOut(fadeDuration, 1);
    }    
 
    public void FadeOut(float duration)
    {
        FadeOut(duration, 1);
    }
 
    // ---------------------------------------- 
    // 	STATIC FADING FOR MAIN CAMERA
    // ----------------------------------------
 
    public static void FadeInMain(float duration, float to)
    {
        GetInstance().FadeIn(duration, to);
    }
 
    public static void FadeInMain()
    {
        GetInstance().FadeIn();
    }
 
    public static void FadeInMain(float duration)
    {
        GetInstance().FadeIn(duration);
    }
 
    public static void FadeOutMain(float duration, float to)
    {
        GetInstance().FadeOut(duration, to);
    }
 
    public static void FadeOutMain()
    {
        GetInstance().FadeOut();
    }
 
    public static void FadeOutMain(float duration)
    {
        GetInstance().FadeOut(duration);
    }
 
    // Get script fom Camera
    public static FadeInOut GetInstance()
    {
    	// Get Script
        FadeInOut fader = (FadeInOut)Camera.main.GetComponent("FadeInOut");
        // Check if script exists
        if (fader == null) 
        {
            Debug.LogError("No FadeInOut attached to the main camera.");
        }    
        return fader;
	}
 
    // ---------------------------------------- 
    // 	SCENE FADEIN
    // ----------------------------------------
 
    public void Start()
    {
    	Debug.Log("Starting FadeInOut");
 
        dummyTex = new Texture2D(1,1);
        dummyTex.SetPixel(0,0,Color.clear);
        backgroundStyle.normal.background = fadeTexture;
        currentAlpha = startAlpha;
        if (fadeIntoScene)
        {
            FadeIn();
        }
    }
 
    // ---------------------------------------- 
    // 	FADING METHOD
    // ----------------------------------------
 
    public void OnGUI()
    {   
        // Fade alpha if active
        if ((fadeDirection == -1 && currentAlpha > targetAlpha) ||
            (fadeDirection == 1 && currentAlpha < targetAlpha))
        {
            // Advance fade by fraction of full fade time
            currentAlpha += (fadeDirection * alphaDifference) * (Time.deltaTime / currentDuration);
            // Clamp to 0-1
            currentAlpha = Mathf.Clamp01(currentAlpha);
        }
 
        // Draw only if not transculent
        if (currentAlpha > 0)
        {
            // Draw texture at depth
            alphaColor.a = currentAlpha;
            GUI.color = alphaColor;
            GUI.depth = guiDepth;
            GUI.Label(new Rect(-10, -10, Screen.width + 10, Screen.height + 10), dummyTex, backgroundStyle);
        }
    }
}


The following bugs have been identified in the code segment above

LINE 133: FadeInOut should read CameraFade

LINE 136: Replace FadeInOut occurances with CameraFade

Also when I was trying to use it, if I didn't FadeIn on start the value for currentAlpha would end up NaN. I had to do some rearranging, but when I was done there were conditions that would cause currentAlpha to equal the targetAlpha when I issued a FadeIn command. I corrected this by placing the following code in the FadeIn method and an equivalent one in the FadeOut.


    	//Check to see if currentAlpha is set to 1.  It will need to be 1 to fade properly
    	if (currentAlpha != 1){
          currentAlpha = 1;	
        }

I would replace this code with mine, but I've already changed my so much I am hesitant to do so, I'll leave that exercise to someone else.







반응형
Posted by blueasa
, |