https://assetstore.unity.com/packages/vfx/particles/spells/100-magic-particle-effects-23515



유니티 이펙트 튜토리얼

https://www.youtube.com/watch?v=QN_rrM_OtPA

드로우 콜(Draw call)

오브젝트, 파티들 등은 CPU에 의해 연산된 정보를 GPU에서 가공하여 최종적으로 화면에 보이게된다. CPU에서 생산된 정보를 버퍼를 통해 GPU로 전달한다. 쉽게 말해 CPU가 GPU에게 이거 화면에 그려(Draw)달라고 요청(call)하는 것이다. 이것을 드로우 콜(Draw call) 이라한다. 


유니티 현재 버전(5.x)에서는 Batches로 표시된다.


병목현상

게임 중 화면에 표시할 오브젝트가 많아서 Draw call 도 많아졌다. CPU에서는 정보들을 빨리 연산하여 GPU에게 넘겨줘야하지만 오브젝트가 너무 많아 신속하게 처리가 안된다. 이러한 병목현상이 나타마면 갑자기 화면이 멈춘것처럼 보이거나. 끊기는 현상이 발생한다. CPU의 부담이 커져서 열도 많이나고 베터리 소모도 많아진다. 이렇게 지체되는 시간을 오버헤드(Overhead)라고한다. 


병을 거꾸로 했을 때 내용물이 병의 목 부분에서 잘 빠져나오지 못한다.


아틀라스(Atlas)

병목현상 없이 게임이 진행되기 위해, 다양한 방법이 있지만 그중에서 드로우 콜을 최소화 해야한다. 오브젝트의 수가 많더라도 같은 텍스처를 사용한다면 드로우콜은 한 번만 발생한다. 그래서 하나의 텍스처에 많은 이미지들을 모아둔다. 이것을 아틀라스라고 한다.

위 그림처럼 각각의 Cube 오브젝트가 각각의 텍스처를 사용한다고 했을 때 드로우 콜은 4가 발생한다.


하지만 4개의 텍스처를 하나의 아틀라스로 묶어 사용한다면 드로우 콜은 1이 된다. 아틀라스 크기도 2의 배수(Power of 2) 단위라 사용하는 것이 좋다. 32, 64, 128, 256, 512, 1024, 2048 ...


동적 배칭(Dynamic batching)

여러 오브젝트가 동일한 머터리얼을 사용한다면 자동으로 배칭을 해준다. 단, 버텍스 제한이 존재한다. 멀티 쉐이더를 사용하거나 실시간 그림자가 적용 된다면 배칭에서 제외된다.


정적 배칭(Static batching)

게임 오브젝트를 인스펙터에서 보면 Static 체크가 있다. 이것을 체크하면 해당 오브젝트를 Static baching으로 처리하여 CPU의 부담이 줄어든다. 하지만 메모리의 부담은 늘어난다. 경우에 따라서는 Static 체크를 해제하는 것이 더 유리할 때도 있다. 정적 배칭은 unity pro에서만 지원한다.


머터리얼과 쉐어드 머터리얼

게임 중 동적으로 머터리얼을 변경해야하는 상황이 발생할 수 있다. 이 경우 sharedMaterial 을 사용하여 변경하는게 더 좋다. 

using UnityEngine;
using System.Collections;

public class Test : MonoBehaviour
{
    public Material myMaterial;
    public Renderer myRenderer;

    void Start()
    {
        myRenderer = GetComponent<renderer>();
        myRenderer.enabled = true;
    }

    void ChangeMaterial()
    {
        myRenderer.material = myMaterial;
        myRenderer.sharedMaterial = myMaterial;
    }
}

위위 코드에서 myRenderer.material 과 myRenderer.sharedMaterial 둘 모두 머터리얼을 교체하는 코드이다. 결과는 같다. 하지만 머터리얼을 처리하는 과정은 서로 다르다. myRenderer.material 을 사용하는 것은 머터리얼을 복사하는 과정이 생겨 드로우콜이 하나 더 발생한다. 하지만 sharedMaterial 을 사용할 경우 배칭이 발생하여 공유할수 있는 머터리얼을 사용하여 추가 드로우콜이 발생하지 않는다. 무조건 드로우 콜이 추가로 발생하지 않는 것은 아니다. 공유 조건에 부합되지 않는다면 sharedMaterial 를 사용하여도 추가로 드로우콜이 발생할 수있다.


참고 : http://docs.unity3d.com/kr/current/Manual/DrawCallBatching.html



출처: http://teddy.tistory.com/25 [Teddy Games]

Object 회전시키기 - Touch Drag

Unity3D 2014/01/17 10:12


  


 

Object에 적용전에 Collider가 있어야 한다는걸 잊지마세요. (없다면 추가 ^^)


public class HomeRotate : MonoBehaviour {


public float rotationSpeed = 10.0f;

public float lerpSpeed = 1.0f;


private Vector3 speed = new Vector3();

private Vector3 avgSpeed = new Vector3();

private bool dragging = false;


void OnMouseDown() {

dragging = true;

}



void Update() {

if (Input.GetMouseButton(0) && dragging) {

speed = new Vector3(-Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"), 0);

avgSpeed = Vector3.Lerp (avgSpeed, speed, Time.deltaTime * 2);

}

else {

if (dragging) {

speed = avgSpeed;

dragging = false;

}


  float i = Time.deltaTime * lerpSpeed;

speed = Vector3.Lerp(speed, Vector3.zero, i);

}


transform.Rotate (Camera.main.transform.up * speed.x * rotationSpeed, Space.World);

transform.Rotate (Camera.main.transform.right * speed.y * rotationSpeed, Space.World);

}

1.맥스에서 유니티로


Editable poly 는 익스포트 할 때 경고가 뜹니다. 기본적으로 Editable Mesh로 변환해주세요. 

애니메이션은 IK인 상태를 FK로 바꾸셔야 합니다. 

일단 FBX로 익스포트 하시면  옵션이 뜨는데 잘 보시면 뭘 체크해야 하는지 아실겁니다.  


맵핑은 맥스의 맵소스가 자동으로 지정되지는 않습니다.  유니티 상에서 머티리얼을 열어서 텍스쳐를 지정해주셔야 합니다.


저도 맥스에서 매핑한 텍스쳐가 유니티로 넘어오지 않아서 고민을 많이 했었는데.. 

기본적으로 재질 설정은 넘어오질 않더군요 

텍스쳐만이라도 넘어오게 하는 방법은 

맥스에서 하나의 재질로 여러개의 오브젝트를 매핑하지 않는 방법입니다. 

좀 노가다이긴 한데 재질 이름이 서로 다 달라야 유니티에서 제대로 인식 하더라고요 

그리고 다시 불러오거나 할 때 유니티에 만들어져 있던 재질들을 모두 삭제하고 다시 불러오셔야 합니다. 

만약에 같은 이름의 재질이 있다면 기존의 재질을 사용하고 새로 만들지 않거든요 


헷갈리지 않게 하려면 재질 이름을 모두 오브젝트 이름과 똑같이 해서 작업하시던가 

재질 적용할 오브젝트를 모두 다 분리한 후 매핑하는게 좋습니다. 

전 후자를 사용





00.유니티가 당신에게 알려주지 않는 진실


http://www.slideshare.net/MrDustinLee/ss-27739454





2.라이트맵 오브젝트 하나를 두장으로 뽑았을 때 중복되는 텍스처 때문에 유니티에서 적용 불가


3D Max 에서 오브젝트를 만들고 

오브젝트를 2개로 분활하여 라이트맵을 2장뽑았습니다 

그리고 유니티로 와서 FBX로 뽑고 불러들인다음 

라이트맵을 설정했는데 라이트맵이 공유가되서 두개를설정할수없어요 ㅠ 

box1, box2 가있다고하면 

box1,2에는 중복되는 텍스처 몇 개 있습니다. 

1번 텍스처가 같은텍스처라고하면 

box1번에 1번 텍스처에 1번 라이트맵을 넣고 

box2번에 1번 텍스처에 2번 라이트맵을 넣으면 

box1번이 라이트맵 2번으로 적용됩니다 

그래서 box1번 라이트맵을 다시 1로 지정하면 

box2번이 라이트맵 2번으로 바뀌고요 


라이트맵에 오브젝트가 아닌 하나의 텍스처에 연결되어있는거같아요 하나바꾸면 

다른 그 텍스처 쓴 오브젝트들은 전부 지정한 라이트맵으로 다바껴요 


맥스에서 혹시나 머트리얼 이름이 중복되서 그런가 해서 

텍스처 설정할때 머트리얼 아이디랑 전부 이름들을 전부 다르게 설정하고 다시뽑아도 저런형상이고요 

FBX최신껄로 업데이트하고 다시뽑아도 변화없고요 ㅠㅠ 

저거 해결못해서 같은 텍스처 복사해서 이름만 바꾸고 새로 넣어주고있습니다 이건 작은양은 상관없겠지만 데이터가 좀 많아질수록 복사하는 수가 몇배나 되서 쓸데없는 작업도늘어나고 용량만 엄청커지고 


123휴  2012.02.15 15:55   답변 신고

라이트맵을 갈아끼셨을 때 두개다 적용된다면 두 오브젝트가 하나의 Material을 사용하고 있는것 같은데요... Unity 3D 상에서 빈 Material을 만드셔서 각 오브젝트마다 다른 Material을 적용시켜 보세요.

지금을살아라  2012.02.15 16:54   답변 신고

그 방법을 써서 하고있습니다만 이것도 양이 많아지면 일일히 Material 을 복사해서 새로 생성해주고 오브젝트마다 그것을 다시 다 지정해줘야하는 작업이기에 오브젝트하나에 텍스처가 10개씩 들어가고 오브젝트가 50개정도만 되어두 500번의 수작업을 해야되니 ㅠㅠ 다른 분들은 알아서 되는거같던데 ㅠ

123휴  2012.02.15 17:12   답변 신고

저는 따로 그래퍼가 fbx를 빼기 전에 Texture를 입혀서 주는데 제가 알기로는 max에서 먹이는 Material이 그대로 오는걸로 알고 있습니다. 유니티에서 손수 작업이 힘드시면 max에서 작업때 미리 Material를 관리하셔서 먹이시면 유니티에서는 Import후 바로 사용 가능하실듯 하네요.

지금을살아라  2012.02.18 13:52   답변 신고

문제점을 찾았습니다 맥스에서 작업한 맵소스 있는 폴더랑 유니티폴더랑 이름이 같아야 하더라고요 다르면 저런문제가 ㅠㅠ 별거아닌걸로 엄청고생했네요 ㅠ 감사합니다



작업상의 문제점은  같은 머터리얼 (텍스쳐)를  공유하면서 라이트맵은 분리 시켜 놓은 건데 

단순한 해결점은  맥스에서  라이트맵 작업을 위한 메쉬 어태치를 같은 머터리얼(텍스쳐) 을 쓰는 것 끼리 그룹핑 해서 어테치  합니다  즉  2개의 라이트맵용 메쉬로 할려고 한다면  어테치 할때 메터리얼이 중복안되게 1번 메쉬나 2메쉬에 몰아서 어테치를 시키면 됩니다.  절대 라이트맵 메쉬를 여러개 사용할때 메터리얼을 각각의 메쉬에 공통으로 쓰게 하면 안된다가 포인트입니다.  이건 유니티 문제라기보다 맥스상의 작업 문제입니다.



감사합니다 

이것저것 알아보고 있는데 저두 제가 작업한 파일들이 문제가 있다고 생각하고있습니다. 

모델링만 새로 불러와서 머트리얼 아이디 중복안되게 변경해주고 새로 설정했는데도 그러고요 ㅠ 

제가 도무지 방법이 없으면 머트리얼끼리 어테치해서 라이트맵을 뽑을까 생각해봤습니다. 

그러다 다른사람 유니티 파일을 봤는데 약 텍스처 이름이 1이라면 

유니티에서 자동 생성되는 머트리얼 파일이 1.mat로 생성이되어 같은 텍스처가 저기로 다들어갑니다 

다른사람 유니티 파일을 보니 머트리얼 파일이 1-Material #32156.mat , 1-Material #32143.mat 

이런식으로 생성되어 같은 텍스처라도 뒤에 머트리얼 아이뒤가 추가로 붙어서 공유되는일이없는거같습니다

gigaman  2012.02.16 14:50   답변 신고

max 작업물을 볼수 없어서 자세히는 어떠한 사항인지 알 수는 없지만 추측키로는 메터리얼 아이디 변경으로 해결이 안될 수 있습니다.  특히나 하나의 오브젝트가 멀티 메터리얼 상태이면 아주 힘듭니다. 

일단 오브젝트 하나하나가 멀티 메터리얼 상태가 아니라는 가정하에서 

1.어테치 하기전의 여러개 가 놓여진 오브젝트 중에서 메터리얼 에디터에서 스포이드로 하나를 찍어서  메터리얼 에디터 메뉴중에 Utilities / Selet Objct by meteral  누르면 현재 선택된 메터얼을 사용하고 있는 메쉬들이 쫙 선택이 될겁니다. 

2. 선택된 메쉬들 끼리 어태치 하시고  1번 작업을 반복합니다.  

3. 더이상 체크할 메터리얼이 없으면  어태치 된 오브젝트끼리  그룹핑 해서  2개의 ??  라이트맵용 어태치 메쉬를 만드셔서 익스 포트 해보시기 바랍니다.


문제점을 찾았습니다 맥스에서 작업한 맵소스 있는 폴더랑 유니티폴더랑 이름이 같아야 하더라고요 다르면 저런문제가 ㅠㅠ 별거아닌걸로 엄청고생했네요 ㅠ 감사합니다



3.unity


유니티 관련 3DS Max 에서 작업시 유의사항


최신의 FBX 익스포터를 사용하자.

: 과거 버전에서 만든 파일을 임포트할 경우 결과가 달라질 수 있으므로 가능한 한 가장 최신의 FBX 익스포터를 사용한다.


FBX를 내보내기 전에 Resource Collector 를 사용해 텍스처를 Asset 폴더로 복사할 수 있다.


3차원 좌표계

유니티는 기본적으로 Y축이 위를 향하는 왼손 좌표계를 사용한다.

: FBX 익스포터 옵션에서 Y UP 으로 설정되어 있는지 확인하도록 하자.


스케일(Scale)

유니티에서 1의 단위는 1미터를 의미한다.

: Scale Factor 를 통해 모델링을 불러올 때 스케일을 조정할 수 있지만, 가급적 모델링 작업 때 이 단위를 감안하자.


노멀(Normal) 구성

대부분의 유니티 셰이더는 기본적으로 뒷면은 그리지 않도록 설정되어 있다.

: 일반적으로 그래픽 소프트웨어는 양면을 다 그리는 반면 유니티 셰이더는 그렇지 않다. 이 때문에 면의 노멀 방향이 잘못되어 있을 경우 그래픽 소프트웨어에서 잘 보이는 물체가 유니티에서는 잘 안 보일 때가 있다.


텍스처(Texture)

유니티에서는 이미지가 RGBA 압축된 DXT 이미지인 .dds 형식으로 변환하여 사용된다.

: 유니티에서는 이미지를 .dds 형식으로 변화하여 사용됨으로, tif, psd 같은 대용량 파일도 마음대로 사용해도 된다.


2의 제곱수 사이즈의 텍스처를 사용하자

: 2의 제곱수 이미지를 사용하면 밉매핑(mip-mapping) 이미지가 사용될 때, 아티팩팅(artifacting) 이라는 깜빡임 현상으로 인한 부작용이 거의 없어진다. 또한 컴퓨터 내부적으로 메모리가 2의 제곱수 블록 형태로 사용됨으로 메모리 최적화와 효율성에서 이득이 있다. 가능하다면 이미지는 항상 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048 등의 크기로 만들어야 한다.


재질(Material)

재질(Material)이름과 텍스처 파일명과 같게 하자

: Unity3D 툴 재질에 텍스처가 자동으로 들어가게 하려면 이름이 같아야 한다.


유니티는 임포트 시점에 객체에 대해 기본 디퓨즈 텍스처만을 생성한다.

: 범프(bump)나 반짝임, 높이, 기타 특수 맵은 직접 추가해야 한다.


메시(Mesh)

맥스 객체는 모서리 문제를 막기 위해 에디터블 폴리 대신 에디터블 메시로 병합해야 한다.

: FBX는 회전 모서리를 지원하지 않으므로 내보내는 과정에서 모델이 변경될 수 있다.


애니메이션(Animation)

복잡한 애니메이션 계층구조는 유니티에 임포트할 때까지 정사영 방향으로 유지한다.

: 유니티는 비정사영 회전 매트릭스를 지원하지 않는다.


유니티는 현재 모프 타깃 같은 정점 애니메이션을 지원하지 않는다.

: 정점 단위로 객체에 영향을 주는 애니메이션은 항상 뼈대를 사용해 처리해야 한다.


각 비헤이비어(behaviour)나 타임 세그먼트의 시작 및 끝에 있는 변형과 객체에 대해 모두 키를 지정한다.


비헤이비어의 타임 세그먼트는 여러 객체가 같은 이름의 타임 세그먼트나 클립을 사용하지 않는 한 겹치지 않게 한다.




텍스쳐에 어떤 내부 표현이 사용되었는가. 이것은 크기와 퀄리티간의 절충(trade-off)이 필요합니다. 아래 예에서는 게임 내 텍스쳐의 최종 크기(256x256 픽셀)를 보여줍니다.


RGB Compressed PVRTC 4 bits : 압축된 RGB 텍스쳐. 이것은 디퓨즈(diffuse) 텍스쳐의 가장 흔한 형식입니다. 픽셀 당 4bits (256x256 텍스쳐에 32KB).


RGBA Compressed PVRTC 4 bits : 압축된 RGBA 텍스쳐. 이것은 디퓨즈(diffuse) & 스페큘러(specular) 제어 텍스쳐의 가장 주요 형식입니다. 픽셀당 1 바이트(1 byte/pixel) (256x256 텍스쳐에서 32KB).


RGB Compressed PVRTC 2 bits : 압축된 RGB텍스쳐. 디퓨즈(diffuse) 텍스쳐에 가장 적합한 낮은 퀄리티의 포맷. 픽셀당 2 비트 (256x256 텍스쳐에서 16KB).


RGBA Compressed PVRTC 2 bits : 압축된 RGBA 텍스쳐. 디퓨즈(diffuse) & 스페큘러(specular) 제어 텍스쳐에 가장 적합한 낮은 퀄리티의 포맷. 픽셀당 2 비트 (256x256 텍스쳐에서 16KB)


RGB Compressed DXT1 : 압축된 RGB 텍스쳐. 이 형식은 iOS에서 지원되지 않지만 데스크탑 프로젝트의 호환성을 위해 가지고 있습니다.


RGBA Compressed DXT5 : 압축된RGBA 텍스쳐. 이 형식은 iOS에서 지원되지 않지만 데스크탑 프로젝트의 호환성을 위해 가지고 있습니다.


RGB 16 bit : 알파(alpha) 없는 65,000 가지 색상. RVRTC 형식보다 메모리를 더 사용하지만 UI 또는 그레이디언트(gradient)없는 날카로운(crisp) 텍스쳐에 더욱 적합합니다. 256x256 텍스쳐에서 128KB.


RGB 24 bit : 알파 없는 트루컬러. 256x256 텍스쳐에서 192KB.


Alpha 8 bit : 높은 퀄리티의 알파 채널. 256x256 텍스쳐에서 64KB.


RGBA 16 bit : 낮은 퀄리티의 트루컬러. 16 레벨의 빨강(R), 초록(G), 파랑(B) 그리고 알파(alpha). RVRTC형식보다 메모리를 더 사용하지만 사용자가 정확한 알파 채널을 원할때 편리합니다. 256x256 텍스쳐에서 128KB.


RGBA 32 bit : 알파 있는 트루컬러 ? 이것은 가장 높은 퀄리티를 가집니다. 256x256 텍스쳐에서 256KB를 가지며 이것은 아주 비쌉니다. 대부분 PVRTC는 훨씬 작은 크기에서도 충분한 퀄리티를 제공합니다.


Android

텍스쳐에 어떤 내부 표현이 사용되었는가. 이것은 크기와 퀄리티간의 절충(trade-off)이 필요합니다. 아래 예에서는 게임 내 텍스쳐의 최종 크기(256x256 픽셀)를 보여줍니다.


RGB Compressed DXT1 : 압축된 RGB 텍스쳐. 엔비디아 (Nvidia) Tegra에 의해 지원됩니다. 픽셀당 4 bits (256x256 텍스쳐에서 32KB).


RGBA Compressed DXT5 : 압축된 RGBA 텍스쳐. 엔비디아 (Nvidia) Tegra에 의해 지원됩니다. 픽셀당 6 bits (256x256 텍스쳐에서 64KB).


RGB Compressed ETC 4 bits : 압축된 RGB 텍스쳐. 이것은 디퓨즈(diffuse) 텍스쳐의 가장 흔한 포맷입니다. 픽셀당 4bits (256x256 텍스쳐에서 32KB).


RGB Compressed PVRTC 2 bits : 압축된 RGB 텍스쳐. 이매지네이션 (Imagination) PowerVR GPUs에 의해 지원됩니다. 픽셀당 2bits (256x256 텍스쳐에서 16KB)


RGBA Compressed PVRTC 2 bits : 압축된RGBA 텍스쳐. 이매지네이션 (Imagination) PowerVR GPUs에 의해 지원됩니다. 픽셀당 2bits (256x256 텍스쳐에서 16KB)


RGB Compressed PVRTC 4 bits : 압축된 RGB 텍스쳐. 이매지네이션 (Imagination) PowerVR GPUs에 의해 지원됩니다. 픽셀당 4bits (256x256 텍스쳐에서 32KB)


RGBA Compressed PVRTC 4 bits : 압축된RGBA 텍스쳐. 이매지네이션 (Imagination) PowerVR GPUs에 의해 지원됩니다. 픽셀당 4bits (256x256 텍스쳐에서 32KB)


RGB Compressed ATC 4 bits : 압축된 RGB 텍스쳐. 콸콤(Qualcomm) Snapdragon에 의해 지원됩니다. 픽셀당 4bits (256x256 텍스쳐에서 32KB).


RGBA Compressed ATC 8 bits : 압축된RGBA 텍스쳐. 콸콤(Qualcomm) Snapdragon에 의해 지원됩니다. 픽셀당 6bits (256x256 텍스쳐에서 64KB).


RGB 16 bit : 알파 없는 65,000 가지 색상. RVRTC형식보다 메모리를 더 사용하지만 UI또는 gradient없는 주름진 텍스쳐에 더욱 적합합니다. 256x256 텍스쳐에서는128KB.


RGB 24 bit : 알파 없는 트루컬러. 256x256 텍스쳐에서 192KB.


Alpha 8 bit : 높은 퀄리티의 알파 채널. 256x256 텍스쳐에서 64KB.


RGBA 16 bit : 낮은 퀄리티의 트루컬러. 알파 채널이 있는 텍스쳐에서의 기본 압축. 256x256 텍스쳐에서 128KB.


RGBA 32 bit : 알파 있는 트루컬러 - 알파 있는 텍스쳐를 위한 가장 높은 퀄리티의 압축. 256x256 텍스쳐에서 256KB.


사용자가 Tegra 같은 어떤 특정 하드웨어를 목표로 하지 않는다면 저희는 ETC1 압축 사용을 권장합니다. 필요할 경우 외부(external) 알파 채널을 저장할 수 있으면서도 낮은 텍스쳐 종류의 이득을 받을 수 있습니다. 만약 사용자가 반드시 텍스쳐에 알파 채널을 저장하길 원하면 모든 하드웨어 공급 업체에서 지원하는 압축인 RGBA16 bit을 사용하세요.


사용자 앱이 지원되지 않는 텍스쳐 압축(compression)을 사용하면 그 텍스쳐는 RGBA32로 무압축(uncompressed)되며 압축된 것들과 함께 메모리에 저장이 됩니다. 그래서 이 경우 텍스쳐의 압축을 푸는데 시간을 잃게되며 두번의 저장으로 인해 메모리 손실을 봅니다. 이것은 또한 렌더링 성능에도 아주 부정적인 영향을 줄 수 있습니다.






4.압축이미지

png 포맷 텍스쳐 압축 관련


실텍스쳐 용량 즉 비트수를 줄이면,,패키지 용량이 줄어듭니다...

그리고 유니티에서 텍스쳐를 압축하면,, 로딩시 메모리에 올라갈 메모리가 줄어듭니다.






5.안드로이드에서 최적화 방법


Lighting Performance


Per-pixel dynamic lighting will add significant cost to every affected pixel and can lead to rendering object in multiple passes. Avoid having more than one Pixel Light affecting any single object, prefer it to be a directional light. Note that Pixel Light is a light which has a Render Mode setting set to Important.

Per-vertex dynamic lighting can add significant cost to vertex transformations. Avoid multiple lights affecting single objects. Bake lighting for static objects.

퍼 픽셀 라이트는 픽셀마다 중대한 영향을 끼치고 여러 패스로 그리게 될 수도 있으니까 하나만 쓰라는 얘기. 그것도 디렉셔널 라이트로. 셋팅은 important 셋팅으로 (제대로 번역하기 귀찮...)

버텍스 라이트는 트렌스폼 코스트에 영향 끼친다... 당연하겠지. 어쨌건 결론적으로 라이트는 하나만 쓰라는 말씀.


Optimize Model Geometry


When optimizing the geometry of a model, there are two basic rules:


Don't use excessive amount of faces if you don't have to

필요없는 면 쓰지 마

Keep the number of UV mapping seams and hard edges as low as possible

UV 단순하게 짤러. 그리고 스무스 옵션으로 부드럽게 해. (주:노말과 UV 줄이라는 말임)

Note that the actual number of vertices that graphics hardware has to process is usually not the same as what is displayed in a 3D application. Modeling applications usually display the geometric vertex count, i.e. number of points that make up a model.

그래픽 툴에서 보이는 버텍스 숫자는 그래픽 하드웨어에서 인식하는 숫자랑 다르다는것 주의. 모델링 프로그램은 보이는 버텍스만 카운트 하걸랑.


For a graphics card however, some vertices have to be split into separate ones. If a vertex has multiple normals (it's on a "hard edge"), or has multiple UV coordinates, or has multiple vertex colors, it has to be split. So the vertex count you see in Unity is almost always different from the one displayed in 3D application.

그래픽 카드에서는 버텍스를 똑같은 놈으로 잘라 (복사) 해 버리거든요. 버텍스 노말이 많으면 (꺾인면이 있으면) 또는 UV좌표가 많으면, 혹은 버텍스 칼라가 많으면 버텍스가 복사 되어요. 그래서 버텍스 카운트가 늘어나요. 그래서 그래픽 프로그램과는 데이터가 달라져요 (요건 글로 한번 써야겠다. 좋은 말인데?)


Texture Compression


All Android devices with support for OpenGL ES 2.0 also support the ETC1 compression format; it's therefore encouraged to whenever possible use ETC1 as the prefered texture format. Using compressed textures is important not only to decrease the size of your textures (resulting in faster load times and smaller memory footprint), but can also increase your rendering performance dramatically! Compressed textures require only a fraction of memory bandwidth compared to full blown 32bit RGBA textures.


If targeting a specific graphics architecture, such as the Nvidia Tegra or Qualcomm Snapdragon, it may be worth considering using the proprietary compression formats available on those architectures. The Android Market also allows filtering based on supported texture compression format, meaning a distribution archive (.apk) with for example DXT compressed textures can be prevented for download on a device which doesn't support it.


Enable Mip Maps


As a rule of thumb, always have Generate Mip Maps enabled. In the same way Texture Compression can help limit the amount of texture data transfered when the GPU is rendering, a mip mapped texture will enable the GPU to use a lower-resolution texture for smaller triangles. The only exception to this rule is when a texel (texture pixel) is known to map 1:1 to the rendered screen pixel, as with UI elements or in a pure 2D game.


Tips for writing well performing shaders


Although all Android OpenGL ES 2.0 GPUs fully support pixel and vertex shaders, do not expect to grab a desktop shader with complex per-pixel functionality and run it on Android device at 30 frames per second. Most often shaders will have to be hand optimized, calculations and texture reads kept to a minimum in order to achieve good frame rates.


Complex arithmetic operations


Arithmetic operations such as pow, exp, log, cos, sin, tan etc heavily tax GPU. Rule of thumb is to have not more than one such operation per fragment. Consider that sometimes lookup textures could be a better alternative.


Do NOT try to roll your own normalize, dot, inversesqrt operations however. Always use built-in ones -- this was driver will generate much better code for you.


Keep in mind that discard operation will make your fragments slower.


Floating point operations


Always specify precision of the floating point variables while writing custom shaders. It is crucial to pick smallest possible format in order to achieve best performance.


If shader is written in GLSL ES, then precision is specified as following:


highp - full 32 bits floating point format, well suitable for vertex transformations, slowest

mediump - reduced 16 bits floating point format, well suitable for texture UV coordinates, roughly x2 faster than highp

lowp - 10 bits fixed point format, well suitable for colors, lighting calculation and other high performant operations, roughly x4 faster than highp

If shader is written in CG or it is a surface shader, then precision is specified as following:


float - analogous to highp in GLSL ES, slowest

half - analogous to mediump in GLSL ES, roughly x2 faster than float

fixed - analogous to lowp in GLSL ES, roughly x4 faster than float

For more details about general shader performance, please read the Shader Performance page. Quoted performance figures are based on the PowerVR graphics architecture, available in devices such as the Samsung Nexus S. Other hardware architectures may experience less (or more) benefit from using reduced register precision.


Bake Lighting into Lightmaps


Bake your scene static lighting into textures using Unity built-in Lightmapper. The process of generating a lightmapped environment takes only a little longer than just placing a light in the scene in Unity, but:


It is going to run a lot faster (2-3 times for eg. 2 pixel lights)

And look a lot better since you can bake global illumination and the lightmapper can smooth the results

Share Materials


If a number of objects being rendered by the same camera uses the same material, then Unity Android will be able to employ a large variety of internal optimizations such as:


Avoiding setting various render states to OpenGL ES.

Avoiding calculation of different parameters required to setup vertex and pixel processing

Batching small moving objects to reduce draw calls

Batching both big and small objects with enabled "static" property to reduce draw calls

All these optimizations will save you precious CPU cycles. Therefore, putting extra work to combine textures into single atlas and making number of objects to use the same material will always pay off. Do it!


Simple Checklist to make Your Game Faster


If you're using built-in shaders, peek ones from Mobile category. Keep in mind that Mobile/VertexLit is currently the fastest shader.

Keep the number of different materials per scene low - share as many materials between different objects as possible.

Set Static property on a non-moving objects to allow internal optimizations.

Use ETC1 format for textures when possible, otherwise choose 16bit textures over 32bit for uncompressed texture data.

Use mipmaps.

Use combiners or pixel shaders to mix several textures per fragment instead of multi-pass approach.

If writing custom shaders, always use smallest possible floating point format: fixed / lowp -- perfect for color, lighting information and normals,

half / mediump -- for texture UV coordinates,

float / highp -- avoid in pixel shaders, fine to use in vertex shader for vertex position calculations.

Minimize use of complex mathematical operations such as pow, sin, cos etc in pixel shaders.

Do not use Pixel Lights when it is not necessary -- choose to have only a single (preferably directional) pixel light affecting your geometry.

Do not use dynamic lights when it is not necessary -- choose to bake lighting instead.

Choose to use less textures per fragment.

Avoid alpha-testing, choose alpha-blending instead.

Do not use fog when it is not necessary.

Learn benefits of Occlusion culling and use it to reduce amount of visible geometry and draw-calls in case of complex static scenes with lots of occlusion. Plan your levels to benefit from Occlusion culling.

Use skyboxes to "fake" distant geometry.

See Also


iPhone Optimizing Graphics Performance (for when the graphics architecture is known to be Imagination Tech's PowerVR.)






6.메모리 최적화


● 시스템 메모리

1. 메모리 프로파일러(Instruments, DDMS)를 늘 곁에 두고 지낸다.

2. 모노 런타임에 기인한 메모리 릭이 발생할 수도 있다는 사실을 기억한다.

3. 모노 런타임 분석에도 도전해 본다.


● 비디오 메모리

1. 어떠한 경우에서라도 NPOT(2의 n승이 아닌) 텍스처를 피한다.






7.iOS 사용시 권장하는 텍스처 포맷 : PVRTC


Android 사용시 권장하는 텍스처 포맷 (GPU에 따라 다름)

- Tegra: DXT

- Adreno: ATC

- 공통: ETC1 (OpenGL ES 2.0)

2. OpenGL ES Profiler와 친해진다.

3. 가능하다면 텍스처 압축을 사용한다.

4. 지금 선택한 텍스처의 color bit이 적절한지 다시 생각해 본다.






8.에셋스토어? 너무 좋은 자료가 많다.. 이거 다 쓰고 싶다.


A. 에셋 스토어 자료 너무 좋은 것이 많죠. ngui, fxmaker, 쉐이더 자료들, 뭐 좋습니다. 하지만 초보자라면 ngui제외하고는 처음 부터 권해드리고 싶지 않습니다. 사용하다 보면 에셋인지 쓰레기인지 이게 굳이 필요한가? 이런생각이 듭니다. 그리고 이거 분석하는게 시간이 더 많이 걸립니다. 뭐 시간이 많다면 분석해서 쓰는것은 권장하나... 막쓰는건 게임의 퍼포먼스를 저해하는 결과로 이어지니 주의하세요.

그래도 꼭 써야 겠다하면 꼭 분석해서 사용하세요. ngui만 해도 분석하다보면 ngui를 이용하여 새로운 UI tool을 구성 할 수 있습니다. ngui에서도 hud바는 따로 팔고 있듯이요.....


참고로 제가 써본걸로는 ngui, ezgui, toon shader?(퍼포먼스 안나와서 그냥 만들었음), fxmaker, usequencer,등등 입니다. 더 말 하고 싶은것은 혹시 시간되면 에셋 스토어에...메탈기어 솔리드 라이징에 나오는 오브젝트 컷도 있답니다...ㅋㅋ


Q. update() 함수는 좋을까?

A. 뭐 게임 코디 분들은 다 알고 계시리라 생각하지만 update()함수는 사용하지 않을 경우에 코드에서 아예 제외 시키는게 낫다고 생각합니다. 유니티 안을 들여다 본건 아니지만 사용하지 않는게 커뮤니티에도 글이 많이 올라와 있더군요. 자세한건 스크립트 참조.

저는 update를 사용하지 않고, coroutine을 사용하여 캐릭터를 움직였습니다. 30~40마리 몬스터...^^~위키 보니깐 코루틴은 우리의 친구라고 되어있더군요..ㅋㅋ


Q. 유니티는 main() 없어요>ㅜㅜ.

A. 컴포넌트 방식이라 기존 프로그래밍 하던 사람들이 조금은 헷갈릴 수 있다고 생각합니다. 그래서 저는 main처럼 만들려고 순차적인 접근으로 방법으로 유니티를 컨트롤 했습니다.(?)


예를 들어 빈 오브젝트에 main이 될만한 코드를 삽입하고 여기에서 모든 오브젝트를 컨트롤 합니다. 오브젝트를 생성하고 초기화하고 일종의 manager역할을 하는 오브젝트를 제작하여 사용하였습니다. 그랬더니... 순차적인 접근이 가능하여 조금은 더 내맘대로? 가지고 놀 수 있었습니다.


Q. 오브젝트 10마리를 뿌렸다...그러나 drawcall은 10이 아니네..

A. 저 같은 경우는 10마리 10 몬스터를 출력할때 ... 해당 스테이지에 나오는 몬스터를 종류별로 묶고 텍스쳐 1장에 10마리 몬스터에 대한 텍스쳐를 몰아 넣었습니다. 그리고 메터리얼의 좌표를 변환하여 불러서 사용했습니다. 음 그랬더니 drawcall이 눈에 띄게 줄어든 것을 볼 수 있었습니다. 한 화면에 건물과 나무들 30~40개 몬스터 10~30마리를 띄우고 50frame 유지했습니다. 갤럭시 S2 를 기준으로.....


Q. 정적 오브젝트는 어떻게?

A. 정적 오브젝트는 무조건 static을 표시해줘야 합니다. 이건 유니티에서 권장하는 것이니 이렇게 안 한 것과 한 것을 체크해 보면 프레임 차이가 어마어마 한 것을 볼 수 있을 것입니다.


Q. 모바일에서 지형을?

A. 모바일에서 지형을 출력하고 싶은가요? 드X~스(신규작) , 삼X~다, 아X~어(신규)~ ㅇ도 거의다 평지 맵에서 캐릭터가 왔다갔다 합니다. 가끔 지형을 출력하고 싶은 분들이 있을거라 생각합니다. 아마도 이분들이 몰라서 못한 것은 아닌것 같구요. 컨셉이필요없어서 안한거라 생각합니다...^^~ 지형을 띄우려면 모바일에서 유니티에 지형을 사용하지는 말라고 유니티에서 권장합니다. 이럴거면 왜 만든건지?``ㅋㅋ 그래도 지형을 출력하고 싶으시면 3ds max에서 정적 오브젝트를 제작하시고 스플래팅맵을 만드시는것을 추천합니다. 저는 정적 오브젝트로 출력하였는데 그렇게 느리지도 않고 몹20~, 건물과 오브젝트 20~30 출력했을 때 60fps가 최대일때 54fps를 유지했습니다. (이거는 뭐 다들 잘 알 것 같으니깐..여기까지..)

Q. 유니티 쉐이더?

A. 음..이건 제 분야가 아니지만...적어 본다면 왠만하면 그래픽디자이너 분들을 설득 시켜서 mobile shader를 사용하세요. 아니면 직접 제작하는 것을 추천합니다. 생각보다 그리 성는이 나쁘지는 않답니다. ngui쉐이더도 은근히 많이 쓴듯 하네요.ㅋ


Q. 소켓 서버?

A. 유니티의 장점은 c#의 소켓 프로그래밍을해도 ios에서 잘 돌아 갑니다.~~~혹시 궁금한 분들이 있을까봐.. 올려 드려요.

뭐 내부는 유니티에서 알아서 하겠지만 제가 맥을 잘 모르지만 어쩄든 서로 다른 운영체제에서도 C#하나만 가지고 잘 돌아가니 따로 만들 필요가 없어서 좋았습니다.


Q. 충돌체크

A. 저 같은 경우는 특별한 충돌체크 이외에는 피직스를 쓰지 않고 만들어서 사용하였습니다. 왠지 피직스를 쓰면 부담감이 많이 갈거라 생각해서 그렇게 복잡한 충돌이 아니라 캡슐, 실린더, 플랜, 구 이런 충돌만 있으면 되었기에 직접 만들어서 사용하였습니다.


Q. 수학 함수.

A. 유니티 커뮤니티(데브 거기 말하는거 아님..미국 유니티.<--.) 가면 퍼포먼스가 잘 안 나오는 수학함수가 있다고 합니다. 그 예를 들자면 distance보다는 magnitude를 쓰라는 경우도 있었고...잘 찾아 보시면 여러가지 있는데 지금은 생각이 안나네요...








9.materials 초기화 및 삭제 하기


1. 메터리얼 에디터 슬롯의 샘플 초기화는 Reset material editor slots 를 사용한다.

  (이 기능은 슬롯에 보이는 샘플들을 삭제할 뿐 이미 오브젝트에 적용된 재질은 삭제가 안됩니다.)


Condense Material Editor Slots : 장면에 사용된 재질만 표시.

Restore Material Editor Slots : 버퍼에 저장된 재질을 복원

- 'Reset material editor slots' or 'Condense Material Editor Slots' 를 사용한 후 Reset (파일 저장시 질문 '아니오" 선택) 하고 이 기능을 사용하면 된다.


스크립트:


- 모든 슬롯을 스탠다드 재질로 초기화


 for i = 1 to 24 do (meditMaterials[i] = Standard ())


문구를 고쳐서 모든 샘플슬롯을 원하는  VrayMtl (Vray),  mrArchMaterial (Mental ray) 재질로 변경할 수 있다.  




- 현재의 슬롯 상태를 Medit.mat 파일로 저장하기 (c: 디렉토리안에 임시 저장)

이렇게 저장된 Medit.mat 파일을 사용자폴더 안에 옴겨 넣으면 맥스를 Reset 하거나 재실행할 때 자동적으로 불러온다.


(

tmpLib = materialLibrary()


for i = 1 to 24 do(

append tmpLib meditmaterials[i]

)


saveTempMaterialLibrary tmpLib "C:\Medit.mat"

)







4. 장면안에 있는 모든 오브젝트의 재질을 삭제하고 초기화를 하고자 할때  (스크립트 명령)  

$*.material = undefined (또는 Geometry.material = undefined ) 라고 명령어를 입력하면 된다.

UNITY
new project / 새작업에 가져올것
1. 캐릭터 컨트롤팩
2. 이미지 이펙트팩

작업창이 열리면 순서대로 큐브 생성0.0.0 위치값 지정 하위객체로 ao적용해볼 대상 오브젝트 넣는다
캐릭터 컨트롤 넣고 하위 속성에 메인카메라 선택후 Assets / Standard Assets / Image Effects (Pro Only) / SSAOEffect 텍스트 언어를 끌어다 넣는다 그러면 그외 이펙트 효과들도 해당 언어의 링크가 연결되어 적용된다

 

 

http://dvframes.com/rb/home/b/unity3d/1398

| 텍스쳐(Texture)

스마트폰의 그래픽칩에 따라 텍스쳐 크기를 정하는 것도 중요하고, 항상 정사각형의 텍스쳐 해상도를 가지는 것도 중요하다.

해상도
128x128
256x256
512x512
1024x1024
2048x2048


*지원되는 이미지 포멧 - PDS, TIFF, JPEG, TGA, PNG, GIF, BMP, IFF, PICT
추천하는 이미지 포멧은 PhotoShop의 PDS 파일이다.


매터리얼(Material)

오브젝트(모델)의 질감을 줄 때 사용한다.


임포트된 텍스쳐는 매터리얼의 텍스쳐 파라미터로 들어가게 되어 표현하게 된다.


오브젝트에 매터리얼이 들어가고 Mesh Renderer를 통해 렌더링 되어진다.


쉐이더(Shader)

매터리얼의 쉐이더를 통해 다양한 질감을 표현할 수 있다.

*주요쉐이더

종류 기능
Diffuse  모델의 표면에 라이트의 빛이 확산되도록 렌더링한다. 기본 쉐이더
Specular  라이트의 빛이 광택을 내도록 렌더링하는데 사용한다.
VertexLit  라이트의 빛의 반사를 계산하는 처리를 메쉬의 정점 단위로 계산하서 렌더링한다. Diffuse와 Specular 등의 픽셀 단위로 빛의 반사를 계산하는 것에 비해 처리 속도가 빠르다.
DumpedDiffuse/
DumpedSpecular
Diffuse와 Specular에 노멀맵이라는 텍스쳐를 사용해 표면에 요청이 있는 것처럼 렌더링합니다. 노멀맵은 빛의 반사 정보를 가진 텍스처를 말하며, 요철이 있는 모델을 제작하지 않아도 현실감 있는 주름 등을 표현할 수 있다.
Decal  베이스 텍스처에 데칼을 붙인 것 같이 렌더링한다.
Transparent  투명한 부분을 가진 텍스처를 렌더링한다.
Unlit/Texture Unlit 계열의 쉐이더는 빛 계산을 전혀하지 않고 텍스처의 색을 그대로 랜더랑한다. 라이트 처리를 하지 않기 때문에 처리 속도가 매우 빠르다.
Unlit/Transparent 유리창 등을 표현할 때는 알파 정보를 가진 반투명한 이미지를 사용하게 된다. 반투명한 텍스처를 렌더링할 때는 Transparent 계열이나 Unlit/Transparent 쉐이더를 사용한다.
Unlit/Transparent Cutout 철망이나 펀치 메탈처럼 반대편이 완전히 보이는 표현을 할 때는 Transparent/Cutout 계열이나 Unlit/TransparentCutout 쉐이더를 사용한다.


라이트(Light)

오브젝트에 사실감 있게 표현하는데 중요한 역할을 한다.

*라이트 종류
종류 기능
Ambient Light  물체가 균일한 빛을 가질 수 있게 설정할 수 있다. 현실적인 빛이 아닌 수학적 계산을 빠르게 편하게 하기 위해 도입된 라이트이다.
Point Light 특정 지점에서 지정한 거리만큼 균일하게 퍼지는 빛을 표현한다. 예) 가로등
Directional Light 태양의 빛으로 특정 방향으로 진행되는 빛을 표현한다.
Spot Light  정해진 위치에 원뿔 모양으로 집중적으로 비추는 빛을 표현한다. 예) 자동차 헤드라이트, 무대의 스포트라이트
Area Light 사각형 영역 내에서 특정 방향으로 비추는 빛을 표현한다. 예) 형광등

<참고 서적>
유니티 4 게임 개발의 정석(에이콘)
따라하면서 배우는 유니티3D 입문(위키북스)

<참고 사이트>

Unity Web Player | betaTest

작업 하이라키 상목에 추가 Meshes Collider
계단 걷기 더미 부피 줄이기
머터리얼 셀프일루미

1. 프로파일러를 이용해서 병목현상 체크하기.
- Window > Profiler 메뉴를 이용한다.

2. 컬링 기법 이용하기.
- 프러스텀 컬링 (Frustum Culling) : 레이어별로 컬링 거리를 따로 지정 가능하다.
- 오클루전 컬링 (Occlusion Culling) : Window > Occlusion Culling 메뉴를 이용한다.

3. 드로우콜 체크하기.
- 드로우콜은 게임 오브젝트에 설정된 재질의 셰이더 패스당 하나씩 일어난다.
- 렌더러에 사용한 재질의 수만큼 드로우콜이 발생한다.
- 드로우콜의 발생을 최소화하기 위해서는 성질이 동일한 물체들은 하나의 메쉬와 재질을 사용하도록 통합하는 것이다.
(이를 위해 최상위 오브젝트에 사용할 수 있는 CombineChildren 컴포넌트가 Scripts 패키지에서 제공된다.)
- CombineChildren 컴포넌트를 사용할 경우, 하위 오브젝트가 모두 하나가 되어서 빛의 계산을 모두 수행하는 등 불필요한 계산이 발생하는 단점도 있다.
- 같은 셰이더를 사용하더라도 다른 텍스처를 사용하면 드로우콜이 증가한다.
- 위와 같은 경우, 텍스처를 모두 합친 큰 텍스처(텍스처 아틀라스)를 만들어 서로 공유하면 드로우콜을 줄일 수 있다.

4. 배칭기능 사용하기.
- Edit > Project Settings > Player 에서 설정.
- 정적 배칭을 사용할 경우, static으로 설정된 게임 오브젝트에서 동일한 재질을 사용하는 물체가 있는 경우 자동으로 통합한다.
- 정적 배칭을 사용할 경우, CombineChildren처럼 통합되는 오브젝트를 모두 하나의 커다란 메쉬로 만들어서 따로 저장하게 된다. (메모리 사용 증가)
- 동적 배칭은 움직이는 물체를 대상으로 동일한 재질을 사용하는 경우, 자동으로 메쉬를 통합하여 드로우콜을 줄여주는 기능이다.
- 동적 배칭은 계산양이 많으므로, 정점이 900개 미만인 오브젝트만을 대상으로 수행된다.

5. 권장 텍스처 사용하기.
- 아이폰 (PowerVR) : PVRTC
- 안드로이드 (Tegra) : DXT
- 안드로이드 (Adreno) : ATC
- 안드로이드 (공통) : ETC1

6. 오버드로우
- 겹치는 부분의 픽셀을 다시 그리는 것을 오버드로우라고 한다.
- 오버드로우를 줄이는 가장 좋은 방법은 큰 영역을 차지하는 물체를 먼저 그리도록 하는 것이다.

7. 물리엔진
- 유니티에서는 물리 엔진 작업을 렌더링 작업과 별개로 수행한다.
- 물리 엔진 작업은 FixedUpdate() 함수에서 수행되며, 0.02초로 매우 짧아서 FixedUpdate() 함수가 여러 번 수행된 후 Update() 함수가 호출된다.
- 따라서 FixedUpdate() 함수의 코드에는 필요한 기능만 넣도록 한다.
- 게임 진행에 문제가 없다면 Edit > Project Settings > Time 메뉴에서 FixedUpdate() 함수의 실행 주기를 늘리는 것도 좋다.

8. 충돌체의 이동
- 리지드 바디가 없는 고정 충돌체를 움직이면 CPU에 부하가 발생된다.
- 이 경우, 리지드 바디를 추가하고 IsKinematics 옵션을 준 후 움직이는 것이 좋다.

9. Maximum Allowed timestep 조절
- 여타 요인으로 시스템에 부하가 걸려 지정된 시간보다 오래 멈출 경우, 물리 계산을 건너뛰도록 설정하는 기능.
- Edit > Project Settings > Time 메뉴에서 설정.

10. Solver Iteration Count 조절
- 물리 관련 계산을 얼마나 정교하게 할 것인지 지정. ( 높을수록 정교해진다. )
- Edit > Project Settings > Physics 메뉴에서 설정.

11. Sleep 조절
- 리지드 바디의 속력이 지정된 수치보다 작을 경우, 자동으로 휴면 상태에 들어간다.
- Edit > Project Settings > Physics 메뉴에서 설정.
- Physics.Sleep() 함수를 이용해서 강제 휴면 상태를 만들 수도 있다. 
(Awake()함수에서 사용하면 레벨이 로딩되기 전까지 물리 엔진 사용을 자제시킬 수 있다.)

12. 유니티 라이브러리 사용 시 주의사항
- 유니티의 핵심기능은 모두 c++로 작성되어 있다.
- 예를 들어 transform.position 에서 transform은 c#의 속성으로 정의되어 있고 position은 c++영역에 작성되어 있다.
- 때문에 transform.position 구문을 자주 사용하는 것보다 미리 변수에 저장해두고 사용하는 방식이 좋다.
- FindObject 계열 함수들은 매우 느리다. ( 미리 찾아서 저장해두는게 좋다. )
- Instantiate 와 Destroy 함수를 이용한 프리팹의 생성과 소멸은 비용이 크다. ( 활성화와 비활성화를 이용하는 것이 좋다. )
- 가급적이면 Update 함수보다 CoRoutine 함수를 사용하도록 한다.
- 박싱과 언박싱은 부하가 큰 작업이다.
- 나눗셈보다는 곱셈이 몇십배 빠르다.
- magnitude 보다 sqrMagnitude를 사용해서 제곱근 계산을 줄이도록 한다.
- 삼각함수의 값은 상수로 저장해두고 사용하는 게 좋다.
- 고정 문자열은 readonly 혹은 const 키워드를 사용하여 가비지 컬렉션으로 부터 벗어나도록 한다.

13. 배열 관리
- Array : 아이템들의 크기가 일정하고, 순서가 변할 일이 없다면 일반 배열을 사용하는 것이 가장 빠르게 동작한다.
- ArrayList : 아이템들의 크기가 자주 변하고 순서도 자주 바뀌는데다, 모든 아이템이 레퍼런스형일 경우 사용한다.
- List<T> : ArrayList인데 저장하는 데이터가 밸류 타입이면 제네릭 List를 사용해야 박싱이 일어나지 않는다.
- Hashtable : 키와 값으로 구성된 사전류의 데이터를 관리할 때 해시 테이블을 사용하면 편리하다.
- Dictionary<K, V> : 해시 테이블과 동일한 기능을 수행하나, 데이터의 형식이 밸류 타입이면 제네릭 Dictionary를 사용해야 박싱이 일어나지 않는다.

 

게임 데이터를 게임이 종료된 후에도 사용할 수 있도록 저장하고 싶은 경우
기본 타입(type)의 데이터 말고 좀 더 복잡한 데이터를 저장하고 싶은 경우
위의 경우에 해당되신다면 이번 튜토리얼이 유용할 수 있습니다.

개요
유니티에서 데이터를 저장하는 게 생각만큼 쉽지 않는 건 사실입니다. 전체 씬, 플레이어 위치 정보 등을 저장하려는 경우에그 작업량이 만만치 않습니다. 이번 튜토리얼 그리고 후에 있을 튜토리얼을 통해 유니티에서 데이터를 저장하는 좀 더 쉬운 방법을 보여드리겠습니다. 이번 튜토리얼에서는 데이터를 저장하는 몇 가지 다른 방법들과 이렇게 저장된 데이터들을 RPC 연결 / 서버에 전달해서, 게임에 사용하는 방법을 보여드리겠습니다.

가장 기본적인 방법

기본적인 방법부터 시작해 보겠습니다. 단순한 데이터형(type)에 대해서는 여러분께서 잘 알고 계실 PlayerPrefs으로 저장하는 방법을 확인 하는 차원에서 한번 알아보도록 하겠습니다. PlayerPrefs는 기본형의 데이터를 문자열키 (string key) 값과 함께 저장할 수 있도록 해줍니다. 단순한 데이터를 저장하고 불러와 사용하기에 좋은 방법입니다. 

Image

게임 내의 값들

씬 전환 시에 데이터를 저장하고 이를 공유하고 싶은 경우에 좋은 방법 중 하나는 정적 클래스 (static class)를 만들어 이 클래스에 데이터를 저장하는 방법입니다.

Image

그리고 이 값을 읽고 싶을 때는 아래와 같이 사용하면 됩니다.

Image


이와 같은 클래스를 사용하는 방법의 단점은 인스펙터(Inspector)에서 값을 조절할 수 없다는 점 입니다. (싱글톤으로 매니져 클래스를 구성하면 이 점은 보완할 수 있습니다..)
- 인스펙터와 코드 모두에서 값을 조절하고 싶은 경우에는 DontDestroyOnLoadobject 함수를 이용하는 방법을 고려할 수 있습니다. (아래 코드 참고)

Image

그리고 아래와 같은 방법으로 값에 접근할 수 있습니다.

Image

좀 더 복잡한 데이터 저장하기

위의 예제에서 PlayerPrefs를 사용해서 high score를 저장하는 방법을 살펴봤습니다. 하지만 위에서 살펴본 방법으로는 많은 데이터를 저장하는 데에는 한계가 있습니다. 따라서 아래와 같이 high score를 저장할 수 있는 테이블을 정의해서 저장하는 방법을 고려해볼 때가 왔습니다.

Image

위의 예제를 살펴보면, List를 이용해서 ScoreEntry 클래스 정보를 담아 테이블처럼 사용합니다. 하지만 이 정보를 어떻게 저장해야 할까요? – 바로 BinaryFormatter를 사용하면 됩니다! BinaryFormatter를 사용해서 “파라미터를 갖지 않는 생성자”를 갖는 클래스라면 어떤 클래스도 바이트 배열로 변환하고, 변환된 배열을 다시 문자열 값으로 변환할 수 있습니다. (문자열 값으로 변환하면, PlayerPrefs에 저장할 수 있겠죠?) 아래 보이는 네임 스페이스들을 추가해줘야 한다는 점을 잊지 마시구요.

Image

유니티 오브젝트 저장하기

유니티 오브젝트들을 저장하는 방법은 생각보다 까다로울 수 있습니다. 그래서 대부분 유니티 오브젝트가 갖는 값을 유추해 볼 수 있는 클래스를 새로 생성하고 이 클래스의 값을 저장합니다. 예를 들면, RPC 호출을 통해 여러 개의 AnimationStates를 전달하고 싶은 경우에, AnimationStates를 대신할 수 있는 클래스를 생성해서 이 값을 전달하게 됩니다. 다른 유니티 오브젝트의 값을 전달하려는 경우에도 상황은 마찬가지겠지요.


RPC를 통해 전달하기

아래 코드를 보면, 어떤 클래스라도 문자열로 변환할 수 있도록 하는 방법을 보여줍니다. 이를 이용하면 RPC를 통해 모든 파라미터 값을 보낼 수 있겠죠?


문서화 되지는 않았지만, RPC 역시 byte[]을 보낼 수 있습니다. 이 값은 BinaryFormatter를 이용해서 우리가 원하는 값으로 바로 변환할 수 있도록 도와줍니다. 문자열로부터 변환하는 시간을 줄여주기 때문에 더 좋다고 할 수 있습니다.

이제 highscores 값을 다른 플레이어에 전달할 수 있도록 하는 능력이 갑자기 생겼네요.

Image

웹으로 전달하기

WWWForm 을 이용해서 웹 서버에 데이터를 전달하는 방법은 아주 쉽습니다. 하지만 위에서 보았듯이 Convert.ToBase64String()를 이용해서 바이너리 데이터를 문자열로 변환하는 방법이 제일 쉽지 않을까 생각되네요. (물론 여러분이 사용하시는 서버에 따라 달라질 수 있습니다)

파일로 저장하기

파일로 저장하는 방법도 물론 쉽습니다. 유니티가 제공하는 Application.persistentDataPath를 이용해서 파일을 저장할 위치를 정하고, MemoryStream 대신 FileStream 을 사용하면 됩니다.

Image

결론

이번 튜토리얼을 통해서, 데이터를 저장하고 게임 중에 이 값들을 이용하는 몇몇 새로운 방법들을 익히셨으리라 생각합니다.

 

+ Recent posts