Unity Sprite, Performance etc

About Unity Performance … 

Draw calls indicate how many texture draws your gpu has to display.
Alpha Overdraw :

 

Advertisements

Functional Programming in C# [ Ch. 4, 5, 6 ] __ Oliver Sturm

Chap. 4. Flexible Typing with Generics [9/22]

제네릭 가능 : class, method, interface, delegate
대표적인 것 : 컨테이너 클래스.  다목적 베이스 클래스.

Generic Functions [9/22]

static void SomeThing<T> (T param) { // 함수 이름 뒤에 <타잎> 표시.
}
// Usage ..
SomeThing<int>(33);
SomeThing<string>(" The Parameter ");

<타잎> 변수 생략 가능 : 컴파일러 추론.

Generic Classes

..

Constraining Types 제한.

static void OutputVal<T> ( T value ) where T : ListItem<string> {}   // ListItem<string> 에서 파생되어야..

Other Generic Types

// Delegate
public delegate Rt SomeDelegate<T, Rt> (T param);  // Func<T, Rt> 와 같은 기능..
// Func
public delegate TResult Func<T1, T2, T3, T4, TResule> (T1 p1, T2 p2, T3 p3, T4 pr);
// 대부분의 추상 함수에 사용 가능.  4개 인수와 1개 리턴 값.
// Action 은 리턴 값이 없는 함수에 사용 가능.

Covariance and Contra variance

object[] objList = new object[3];
objList[2] = 10;
string[] strArr = new string[] { "one", "two", "thr" };
objList = strArr; // 이런 할당을 허용할 것인가..
// 좀 더 복잡한..
objList[2] = 10; // Runtime exception .. 어레이가 스트링 형이므로..
int[] intArr = new .... ;
objList = intArr; // intArr 는 밸류타입임.. 이 경우 covariance 는 레퍼런스 타잎만 지원

Variance 는 언어를 더 직관적으로 기능하게 하는 요소다.

List<object> objLst = new ...;
List<string> strLst = new ...;
objLst = strLst; // 허용 안됨.
// IEnumerable<T> 의 예.
public interface IEnumerable<out T> : IEnumerable { }  // retrieved from methods 에서 사용 가능. not passed into them.
IEnumeralbe<object> objSeq = new .. ;
IEnumeralbe<string> strSeq = new .. ;
objSeq = strSeq; // 가능.

4.0 에서 in, out 제레릭에서 사용 가능. 데이터 흐름의 방향을 제어 가능.

Chap. 5. Lazy Listing with Iterators

데이터를 효율적으로 다루기.

The Meaning of Laziness [9/23]

Linq 도 이같은 원리에 근거.

Enumerating Things with .NET

IEnumerable 인터페이스.
MoveNext(), Current(), Reset() …

Implementing Iterator Functions [9/24]

C# 2.0에서 도입된 IEnumerable / IEnumerator 조합을 이용. 제네릭, 넌제네릭 모두 가능.
특별한 형태의 리턴.  yield return 문.  Laziness ..  p49 코드를 볼 것.
리스트를 다 채우는 것이 아니라… 필요할 때 가져온다.. (미리 할 필요가 없다. 중간에 멈추면 후속 값 계산을 안 한다.).

Returning IEnumerator [9/29]

IEnumerable, IEnumerator ..

Chanining Iterators

.. laziness ..

.

Chap. 6. Encapsulating Data in Closures

Scope문제 Closure를 이용 해결.

Constructing Functions Dynamically [9/30]

C# 1.0 : ~ = C ..
delegate, event  : multicast
C# 2.0 : 무명함수.  함수를 만들어서 외부 스코프에 리턴하는 것은 이득이 많음.

The Problem with Scope

엄격한 스코프.
함수 플글에선 변하는 값을 별로 안 좋아함. 가이드 라인은 : { 변하는 값을 전혀 갖지 않음 }
가장 좁은 스코프 안에 집어 넣는 것.
순수 함수는 로컬 변수만 이용. 외부 참조 없음.   => 첫 반응은 incredulity.. 회의..
전역 변수가 않 좋은 이유 : 특정 시점에 어떤 값을 갖을 지 알 수 없음. ..
클래스 멤버는 좁은 스코프.
초기화 과정에서 나중에 쓰일 변수가 있다면 ?  클로져를 이용하는 대안..

How Closures Work

함수를 리턴하는 경우.. 그 안에 로컬 변수..  리턴 된 후 그 함수를 실행시키면 크래쉬. => 컴파일러가 그 값을 보관.
컴파일러는 무명 클래스를 생성하고 인스턴스 생성해서 그 함수를 부른 함수 내부에 둔다.
무명함수는 그 무명 클래스 내부의 함수로 생성. 그 콜러가 지속할 때까지 살아 있는다.  로컬 변수는 무명클래스의 필드로 된 것.
동적 함수는 객체 지향의 메서드 오버로딩과 유사. 하지만, 동적으로 생성됨.

Functional Programming in C# [ Ch. 1, 2, 3 ] __ Oliver Sturm

Chap. 1. A Look at Functional Programming History

What is Functional Programming ?

함수형 언어에서 Referential transparency 는 중요한 개념.  리턴 값이 입력 값에만 의존.
명령형 (imperative) 프로그래밍 과 대조.
함수형 언어 패러다임을 따르는 언어 : recursion 등 .. 을 쓰느냐..
-> 재귀 함수에서 스택에 위치해서 오버플로 하는 언어..  는 재귀를 쓰지 말아야.
고차 함수 : 함수를 인자로 받거나 리턴하는.
C에서는 무명 함수가 없다.
함수형 언어는 컴퓨터에서 문제를 푸는 방법을 알려주는 것. 일의 순서를 나열하는 것 보다는.. referential transparancy 는 이런 의미..

Functional Languages

Haskell, Erlang, Clojure.

The relationship to OOP

C#, F# .. albeit .

Chap. 2. Putting Functional Programming into a Modern Context

Concurrency Programming 에 의한 함수형 패턴 필요성.
Pararrel.foreach ..

Managing Side effects

Agile Programming Methodologies

함수 차원에서의 모듈화. 세분화된 작업을 할 때의 리팩토링. 클래스 차원에서는 너무 작업이 크다. ?

Declarative Programming

Funtional Programming is a Mindset

Is Functional Programming in C# A Good Idea?

Chap. 3. Functions, Delegates, & Lamda Expressions

Functions and Methods

C# 은 클래스 외에서의 함수는 인정 안함. => Methods 라 불림.

Reusing Functions

Anonymous Functions and Lambda Expressions

[sorting ] 비교 함수. 예.
[custom delegate ]

Func<object, object, bool> compareInt4 =
    (a, b) => ((int) a) > ((int) b);
Func<int, int, int> add = (x, y) => x + y;

람다 함수에서 var 사용 불가. 선언 시 타잎 추론 가능해야 함

Extension Methods [9/19]

Generic 도 가능.

Referential Transparency [9/21]

명령형 프로그램을 말할 때 대부분 ‘상태’ 에 관한 것이다.
명령형 프로그램의 주된 이슈중 하나는 코드가 점점 커진다는 점.
실행 순서에 촛점을 맞추므로 함수/메서드가 참조하기에 불투명해지는 경향이 있다. 같은 인수를 넣어도 동일한 결과가 나온다는 보장이 없다.
함수에서 사용하는 변수들이 여러 영역 (글로벌 .. )에서 가졍오기 때문.
RT 는 이와 반대. 이 단어는 어느 식에나 적용 가능하고, 프로그램을 바꾸지 않고 식이 값으로 바뀌어도 된다는 것.
수학에서 식은 항상 RT 하다. 즉, 3 + 2 는 5로 치환 가능하다.
어떤 함수는 RT 가 불가능. DateTime.Now, ReadByte 같은 것들. 특히 void 를 리턴하는 것들은 식으로 쓰일 수 없고, 참조적으로 불투명하다.
함수형 프로그램의 가장 중요한 컨셉중의 하나는 함수 구현에서 부작용을 피하는 것.
이것은 RT 와 매우 밀접한 관계이다. 순수한 함수는 인수로부터만 결과값을 만들어 부작용이 전혀 없는 것.
함수는 다른 함수를 부르거나 자신의 스코프 밖의 값을 사용할 수도 있다. PI 를 사용하는 예.

The general description of pure functions and side effects leaves out the perspective of the call site, from which a pure function can also be defined by saying that a call into a pure function is expected to be referentially transparent. 이 말이 정확하지는 않더라도  ..
순수한 함수를 쓰려면 인수만을 사용하고 끝에 리턴값을 리턴하라.  외부 변수에 접근하려면 그 일을 하는 다른 순수한 함수를 부르고.
실제 데이터요소에 접근하려면 그것이 상수 임을 확실히 하라. 이 조건에 맞지 않으면 부작용이다.
어떤 언어는 문법이 이를 불가능하게 함. 스크린에 뭘 출력하고 파일에 쓰는 것 들은 이 관점에서 모두 부작용임.

결과적으로 부작용을 피하는 것보다 더 중요한 것이 있다 : 부작용을 관리하는 것.  언어에 따라 이것이 쉽기도, 어렵기도.
순수한 함수를 쓰는 순수한 언어에서는 이를 회피하는 방법이 있다. 하스켈에서는 모나드가 이것을 가능하게 한다.
C#은 특별한 게 없다.  단지 아키텍쳐적인, 구조적인 문제일 뿐.

순수함수.. 마지막 말.
이렇게 코딩을 하면, 실행 순서, 함수가 불리는 순서는 중요하지 않다는 것.
개발자는 어떻게 함수들이 의존성의 네트웤을 형성하는 지 정의한다. 컴파일러가 최적의 실행을 한다.
이것은 최적화가 가능하게 하고, 중복된 코드는 자동제거될 수 있고, 캐시 적용가능하고, 로직파트는 병렬처리가 가능하다.
이런 가능성 리스트는 무한하고 많은 순수함수 환경은 이런 접근을 자동화한다.
충분한 이론-챕터가 나중에 이런 것들의 장점과 확장된 아이디어를 보여줄 것임.

닷넷 4.0 에서 code contracts 개념 도입.
PureAttribute.

안드로이드 구글 플레이어 올리기..

안드로이드는 50메가 제한이 있음..

.. 어떻게 유니티에서 파일을 나눠서 apk 파일을 만들 것인가 ?  ==> 애셋 번들을 만들라.  방법 잘 정리된 블로그 글.

.. 어떻게 나눠진 파일을 올리는가 ?

zip 으로 압축해서 올림.  android\obb\패키지명\main.버전코드.패키지명.obb 이런식으로 된다고?..  파일명은 신경 꺼라.  바로가기

안드로이드 개발자 사이트 번역

APK Expansion Files (확장파일)

구글 플레이는 현재 50메가 이하의 파일을 요구한다. 대부분의 어플에게 이 용량은  코드와 애셋을 합쳐 충분할 것이다. 하지만 고퀄리티 그래픽이나 미디어 파일, 큰 애셋을 갖는 어플은 더 많은 공간을 요구한다. 이전에는 50메가 이상의 경우 사용자가 앱을 오픈할 때  개발자가 추가적인 리소스를 호스팅하고 다운로드를 제공해야 했다.  추가적인 파일을 호스팅하는 것은 비용이 들고 UX 도 이상적이지 않다. 이 과정을 쉽게하기 위해 구글 플레이는 2개의 대용량 파일을 붙일 수 있게 했다.

구글 플레이는 확장파일을 비용 없이 제공한다.  확장파일은 기기의 공유 스토리지 위치 (SD 카드 또는 USB-마운터블 파티션 – 즉 “외장” 공간) 에 저장된다. 대부분의 기기에서 구글 플레이는 확장 파일을 APK 파일 다운로드와 동시에 받아 사용자가 처음 열었을 때 모든 것이 다 준비되도록 한다.  하지만, 어떤 경우에는 어플이 구글 플레이로부터 어플 시작 시 파일을 다운로드 해야 한다.

Overview

구글 플레이 안드로이드 개발 콘솔을 통해서 APK를 올릴 때 마다 하나 또는 두개의 확장파일을 추가하는 옵션이 주어진다. 각 파일은 2기가 까지이며 어떤 포맷이든 허용되나 다운로드 시 bandwidth 를 유지할 수 있는 압축된 파일을 추천한다. 개념적으로 각 확장파일은 다른 역할을 한다.

# ‘main’ 확장파일은 추가적인 리소스에 대한 주된 확장파일이다.

# ‘patch’ 확장파일은 메인 파일에 대한 부가적인 파일로 작은 업데이트 용도의 파일이다.

두 확장 파일을 어떤 방법으로든 쓸 수 있지만, 메인 파일이 중요한 애셋을 포함하고 업데이트는 가끔 하도록 권장한다. 패치 파일은 더 작고 패치를 위한 파일..

하지만, 어플이 새 패치 파일만을 업데이트 했더라도, 개발자는 매니패스트 의 versionCode 를 업데이트 해서 새로운 APK 를 올려야 한다.

\/\/ Note : 패치 확장파일은 실질적으론 메인 확장 파일과 동일함. 어떻게 사용해도 무방. 시스템은 앱의 패칭을 위해 패치 확장파일을 사용하지 않음. 패치는 스스로 해야 함.

File name format

각 확장 파일은 zip, pdf, mp4 등 어떤 포맷도 가능하다. 파일 타입에 관계 없이 구글 플레이는 opaque binary blobs 로 간주하고 다음과 같은 기준으로 리네임한다.

[main|patch].<expansion-version>.<package-name>.obb

세가지 콤포넌트.

main  or  patch
파일이 메인인지 패치인지 구별. 각 APK 에 하나의 메인과 하나의 패치만 가능.

<expansion-version>
확장이 ‘첫번째’ 참조되는 정수의 버전 코드  . (어플의 android:versionCode 값과 일치)
‘첫번째’ 는 개발자 콘솔이 업로드된 확장 파일을 재사용하는 것(새로운 APK 파일과 함께)을 허용하기 때문에 강조되었음.  이것은 처음 파일을 올렸을 때의 버전을 유지한다.

<package-name>
어플의 자바-스타일 패키지 이름.

예>   main.314159.com.example.app.obb  이렇게 됨.

Storage location

구글 플레이가 확장파일을 다운로드 할 때, 시스템의 공유 공간에 저장한다. 제대로 작동되기 위해서 파일을 지우거나, 옮기거나, 이름을 바꾸지 말것. 어플이 구글 플레이에서 다운로드 해야 할 때, 사용자는 바로 같은 곳에 저장해야 한다.

정해진 위치는 다음과 같다.

<shared-storage>/Android/obb/<package-name>/

# <shared-storage> 는 공유 공간이며 getExternalStorageDirectory() 로 받는다.

# <package-name>  은 getPackageName() 으로 얻음.

각 어플에는 메인/패치 파일이 가능. 이전 버전은 새로운 확장 파일로 업데이트하면 overwrite 됨.

파일을 언-팩 해야하면 .obb 파일을 지우지 말고 같은 디렉토리에 풀린 데이터를 저장하지 말라.  압축 해제된 파일은 getExternalFilesDir() 에 지정된 곳에 저장해야 한다. 하지만, 가능하면 해제 과정 없이 확장 파일을 바로 사용하는 것이 제일 좋다. 예를 들면 집 파일을 바로 읽는 라이브러리 같은 경우..

/\/\ Note : APK 파일과는 다르게 어떤 파일이라도 저장 가능하다.

/\/\ Tip : 미디어 파일을 집 압축 한다면 미디어 플레이백 콜을 오프셋, 길이 조절로 부를 수 있다. (MediaPlayer.setDataSource() &  SoundPool.load() ) 압축 해재 없이. 이 과정을 통해 부가적인 압축을 하지 않아도 된다. 예를 들어 집 툴을 쓸 때 -n 옵션을 써서 압축을 안 할 수 있다.

Download process

대부분의 경우 확장 파일은 APK 파일과 함께 다운로드, 저장 된다. 하지만, 어떤 경우에은 구글 플레이는 확장 파일을 다운로드 하지 못하거나 사용자가 이전에 내려받은 파일을 지울 수 있다. 이러한 경우에 대비하여 어플은 파일 자체를 다운로드할 수 있어야 한다.  구글 플레이가 제공하는 URL 을 통해서.

다운로드 프로세스

1. 사용자가 구글 플레이에서 앱 선택.
2. 구글 플레이가 확장파일을 다운로드 할 수 있으면 (대부분의 경우) APK 와 함께 파일 다운로드. 확장 파일을 다운로드 할 수 없을 때는 APK 만 한다.
3. 사용자가 앱을 런칭할 때, 앱은 확장 파일이 있는 지 확인해야 함.  있으면 레디 투 고. 없으면 구글 플레이의 HTTP 에서 다운로드 해야 함. 앱은 구글 플레이 클라이언트에 Application Licensing 서비스를 이용하여 요청해야 한다. 이것은 이름, 파일 크기, URL 에 대응함. 이 정보로 파일을 다운로드 하고 정당한 위치에 저장한다.

주의 : 파일 다운로드 코드를 포함하는 것이 중요하다. 라이브러리 제공했으니 최소의 작업량으로 가능할 것.

Development checklist

내용 요약

1. 50메가 이상이 필요한 지 판단. 가능한 한 작게.. 여러 기기를 위해서라면 복수의 APK  를 고려하라.
2. 메인 확장 파일로 뭘 뺄 지 결정.
3. 기기의 ‘공유 저장 위치’ 로부터 읽어 들이도록 개발. 파일 포맷이 무관하면 ‘집’ 해서 APK Expansion Zip Library 를 이용하도록.
4. 초기에 확장 파일 유무 검사. 없으면 다운로드 받도록. Downloader Library  를 사용하면 간단하다.
테스팅.

Rules and Limitations

IAP plugin 설명..

일단 iTunesConnect 에서 제품 셋업을 하고 테스트 유저 1 ~ 2를 생성하면 테스트 할 준비가 된 것.

씬에 StoreKitManager.cs 스크립트가 연결된 게임 오브젝트가 있어야 한다.

네이티브 코드로 부터의 콜백함수는 그 클래스의 메소드를 부를 것이다.

애플은 구매를 ‘초기화’ 하기 전에 먼저 ‘리트리브’ 하는 앱들을 리젝 시켜왔다.

사용자에게 구매를 허용하기 전에 항상 requestProductData 를 불러주도록.

Server Product model Overview Image

스토어킷은 비동기적으로 이루어지므로 실패 유무의 콜백 함수를 유심히 봐야 한다.

중요한 함수는  productPuchased()  임..  이것이 오면 구매가 원활히 이루어진 것임.

StoreKitManager 네이티브로부터의 콜백을 모두 노출함.

[ storeKitEventListener ] 프리팹을 당신의 씬에 가져다 놓으면 미리 연결된 함수를 통해 모니터링 가능하다.

Xcode 의 로그를 보는 것이 가장 도움이 됨.

또한, StoreKitManager  프리팹은 처음 로딩 씬에 추가되어 있어야 함.

아래는 애플의 가이드라인.  다음의 이유로 product identifier 가 in valid 로 리턴될 수 있음.

# 테스팅 하지 않는 애플 아이디는 완전히 로그아웃 할 것.. ( 세팅 -> 스토어 -> 사인 아웃 )

# 금융 동의에 완전히 서명하지 않음.

# 적당한 ‘제품 아이디’를 쓰지 않음.

# IAP 제품을 for sale 로 클리어 하지 않음.

# 제품 수정이 모든 서버에 전파 되지 않았음.

# 아이튠즈 커넥트의 제품을 리젝했음.

# 앱 리뷰가 준비될때까지 바이너리를 업로드 하지 말것.  개발용 바이너리가 있으면 리젝될 것임.  방법은 :: 앱내구매 없이 올려서 승인을 받고,  바이너리가 승인을 받으면 앱내구매 기능을 테스트 한다. ??

앱내구매 테스트 팁

# 번들 아이디를 유니티 /   Xcode 에서 이중 체크 할 것.

# 프로비저닝 파일 유효

# 테스트 유저만 아이튠즈 커넥트 포탈을 사용할 것.

# 테스트 사이에는 앱을 지울 것..  requestProductData 로부터 데이터를 받을  수 있으므로.

샘플소스는 작동 안될 것임.. 참고용.