ݺߣ

ݺߣShare a Scribd company logo
쪼꼬두유’s 방황기
2015.12.05 데브루키
첫번째달의레포트
LINQ = Language Integrated Query
SEVENTEEN
멤버 중에 성인 멤버를 구분해 내기 위해서 코드를 짜는데
첫번째달의레포트
LINQ = Language Integrated Query
1
2
3
4
5
6
7
8
9
var NotMinor = from Member in seventeen
where Member.Age > 19
orderby Member.Age
select Member;
foreach(Member member in NotMinor)
{
Console.WriteLine(member);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
List<Member> NotMinor = new List<Member>();
foreach (Member member in seventeen)
{
if (member.Age > 19)
NotMinor.Add(member);
}
NotMinor.Sort((memberA, memberB) => memberA.Age - memberB.Age);
foreach (Member member in NotMinor)
{
Console.WriteLine(member);
} c
LINQ를 쓰면
코드가 단순해지며
가독성이 올라간다.
첫번째달의레포트
LINQ = LINQ는 Language Integrated Query
var NotMinor = from Member in seventeen
where Member.Age > 19
orderby Member.Age
select Member;
데이터를 검색하기 위해서 데이터를 검색할 범위를 지정해줌
반드시 범위를 지정해주고 시작해야 한다.
Foreach 처럼 사용하면 된다.
첫번째달의레포트
LINQ = LINQ는 Language Integrated Query
var NotMinor = from Member in seventeen
where Member.Age > 19
orderby Member.Age
select Member;
Foreach랑 다른 점은
Foreach의 element 변수에는 실제로 array의 데이터가 저장
된다.하지만 LINQ에서는 element 변수에 데이터가 저장되지
않고, 단순히 'array에 존재하는 요소'라는 의미로만 사용된다.
첫번째달의레포트
LINQ = LINQ는 Language Integrated Query
var NotMinor = from Member in seventeen
where Member.Age > 19
orderby Member.Age
select Member;
from에서 사용 가능한 타입은 IEnumerable<T> 인터페이스를
상속하는 타입이다. C#에서의 배열이나 컬렉션등은 모두
IEnumerable<T>을 상속하기 때문에 배열이나 컬렉션 타입이
라면 전부 사용 가능하다.
첫번째달의레포트
LINQ = LINQ는 Language Integrated Query
지정한 데이터 범위 내에서 한 번 더 데이터 범위를 지정하려면
from절을 중첩해서 사용하면 된다.
var Students = from student in studentList
from score in student.score
where score > 89
select new {student.name, failScore = score};
첫번째달의레포트
LINQ = LINQ는 Language Integrated Query
var NotMinor = from Member in seventeen
where Member.Age > 19
orderby Member.Age
select Member;
where은 범위 내에서 데이터를 걸러내는 필터 역할을 한다. 따
라서 where에서는 데이터를 걸러내기 위한 필터 조건을 작성해
주면 된다. 그러면 해당 조건에 참이 되는 데이터만 걸러지게 된
다.
첫번째달의레포트
LINQ = LINQ는 Language Integrated Query
var NotMinor = from Member in seventeen
where Member.Age > 19
orderby Member.Age
select Member;
orderby는 걸러진 데이터를 정렬해주는 연산자이다.
기본 오름차순 정렬이고 뒤에 descending을 붙여주면 내림차
순 정렬을 한다.
첫번째달의레포트
LINQ = LINQ는 Language Integrated Query
var NotMinor = from Member in seventeen
where Member.Age > 19
orderby Member.Age
select Member;
최종적으로 검색된 데이터를 추출하는 역할을 한다. 추출된 데
이터의 타입은 select절에 지정한 변수의 타입으로 결정되며,
무명형식(타입)으로 만들어서 추출할 수도 있다.
첫번째달의레포트
LINQ = LINQ는 Language Integrated Query
var NotMinor = from Member in seventeen
where Member.Age > 19
orderby Member.Age
select Member.name;
최종적으로 검색된 데이터를 추출하는 역할을 한다. 추출된 데
이터의 타입은 select절에 지정한 변수의 타입으로 결정되며,
무명형식(타입)으로 만들어서 추출할 수도 있다.
첫번째달의레포트
LINQ = LINQ는 Language Integrated Query
var NotMinor = from Member in seventeen
where Member.Age > 19
orderby Member.Age
select new{Name = Member.Name, Age = Member.Age};
최종적으로 검색된 데이터를 추출하는 역할을 한다. 추출된 데
이터의 타입은 select절에 지정한 변수의 타입으로 결정되며,
무명형식(타입)으로 만들어서 추출할 수도 있다.
첫번째달의레포트
LINQ = LINQ는 Language Integrated Query
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var Group = from person in peopleList
group person by person.Sex == "남자" into data
select new { sexCeheck = data.Key, People = data };
foreach(var group in Group)
{
if(group.sexCeheck == true)
{
Console.WriteLine("<남자>");
foreach (var person in group.People)
Console.WriteLine("이름 : " + person.Name);
}
else
{
Console.WriteLine("<여자>");
foreach (var person in group.People)
Console.WriteLine("이름 : " + person.Name);
}
} c
첫번째달의레포트
LINQ = LINQ는 Language Integrated Query
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var Group = from person in peopleList
group person by person.Sex == "남자" into data
select new { sexCeheck = data.Key, People = data };
foreach(var group in Group)
{
if(group.sexCeheck == true)
{
Console.WriteLine("<남자>");
foreach (var person in group.People)
Console.WriteLine("이름 : " + person.Name);
}
else
{
Console.WriteLine("<여자>");
foreach (var person in group.People)
Console.WriteLine("이름 : " + person.Name);
}
} c
Group 데이터
sexCheck
FALSE
sexCheck
TRUE
첫번째달의레포트
LINQ = LINQ는 Language Integrated Query
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
List<Member> seventeen = new List<Member>();
seventeen.Add(new Member() { Name = "에스쿱스", Age = 21 });
seventeen.Add(new Member() { Name = "정한", Age = 21 });
seventeen.Add(new Member() { Name = "조슈아", Age = 21 });
seventeen.Add(new Member() { Name = "준", Age = 20 });
seventeen.Add(new Member() { Name = "호시", Age = 20 });
seventeen.Add(new Member() { Name = "우지", Age = 20 });
seventeen.Add(new Member() { Name = "원우", Age = 20 });
seventeen.Add(new Member() { Name = "도겸", Age = 19 });
seventeen.Add(new Member() { Name = "민규", Age = 19 });
seventeen.Add(new Member() { Name = "디에잇", Age = 19 });
seventeen.Add(new Member() { Name = "승관", Age = 18 });
seventeen.Add(new Member() { Name = "버논", Age = 18 });
seventeen.Add(new Member() { Name = "디노", Age = 17 });
List<Body> bodies = new List<Body>();
bodies.Add(new Body() { Name = "도겸", Height = 179, Weight = 66 });
bodies.Add(new Body() { Name = "민규", Height = 185, Weight = 53 });
bodies.Add(new Body() { Name = "승관", Height = 174, Weight = 60 });
bodies.Add(new Body() { Name = "버논", Height = 175, Weight = 56 });
bodies.Add(new Body() { Name = "디노", Height = 170, Weight = 56 });
var Minors = from member in seventeen
join body in bodies on member.Name equals body.Name
select new { Name = member.Name, Age = member.Age, Height = body.Height, Weight = body.Weight };
foreach(var member in Minors)
{
Console.WriteLine(member);
} c
첫번째달의레포트
LINQ = LINQ는 Language Integrated Query
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
List<Member> seventeen = new List<Member>();
seventeen.Add(new Member() { Name = "에스쿱스", Age = 21 });
seventeen.Add(new Member() { Name = "정한", Age = 21 });
seventeen.Add(new Member() { Name = "조슈아", Age = 21 });
seventeen.Add(new Member() { Name = "준", Age = 20 });
seventeen.Add(new Member() { Name = "호시", Age = 20 });
seventeen.Add(new Member() { Name = "우지", Age = 20 });
seventeen.Add(new Member() { Name = "원우", Age = 20 });
seventeen.Add(new Member() { Name = "도겸", Age = 19 });
seventeen.Add(new Member() { Name = "민규", Age = 19 });
seventeen.Add(new Member() { Name = "디에잇", Age = 19 });
seventeen.Add(new Member() { Name = "승관", Age = 18 });
seventeen.Add(new Member() { Name = "버논", Age = 18 });
seventeen.Add(new Member() { Name = "디노", Age = 17 });
List<Body> bodies = new List<Body>();
bodies.Add(new Body() { Name = "도겸", Height = 179, Weight = 66 });
bodies.Add(new Body() { Name = "민규", Height = 185, Weight = 53 });
bodies.Add(new Body() { Name = "승관", Height = 174, Weight = 60 });
bodies.Add(new Body() { Name = "버논", Height = 175, Weight = 56 });
bodies.Add(new Body() { Name = "디노", Height = 170, Weight = 56 });
var Minors = from member in seventeen
join body in bodies on member.Name equals body.Name
select new { Name = member.Name, Age = member.Age, Height = body.Height, Weight = body.Weight };
foreach(var member in Minors)
{
Console.WriteLine(member);
} c
A
B
C
B
C
D
B
C
첫번째달의레포트
LINQ = LINQ는 Language Integrated Query
A
B
C
B
C
D
A
B
C
1
2
3
4
5
var Minors = from member in seventeen
join body in bodies on member.Name equals body.Name into temp
from body in temp.DefaultIfEmpty(
new Body() { Height = 0, Weight = 0})
select new { Name = member.Name, Age = member.Age, Height = body.Height, Weight = body.Weight };
c
그만두고나서
두 번째 달은...
그만두고나서
두 번째 달은...
그만두고나서
두 번째 달은...
그만두고나서
두 번째 달은...
그만두고나서
두 번째 달은...
카메라에 찍히는지 안 찍히는지 검사하는 함수
두번째달의레포트
근데 계속 돌려도 안없어지고 쌓이더라...
두번째달의레포트
알고봤더니 표시되지 않는 SceneView도 카메라로 표시하더라...
두번째달의레포트
UML 다이어그램
객체지향 시스템에 존재하는 클래스, 클래스 안의 필드, 메소드, 서로 협력하거나 상속하는 클래
스 사이의 연결 관계를 나타내는 그림
Rectangle
-width: int
-height: int
/area: double
+ Rectangle(width: int, height: int)
+ distance(r: Rectangle): double
Student
-name: String
-id: int
-totalStudents: int
#getID(): int
+getName(): String
~getrEmailAddress(): String
+getTotalStudents(): int
+ public
# protected
- private
~ package, namespace
/ derived(상속 받음)
Underline : static variable
두번째달의레포트
UML 다이어그램
객체지향 시스템에 존재하는 클래스, 클래스 안의 필드, 메소드, 서로 협력하거나 상속하는 클래
스 사이의 연결 관계를 나타내는 그림
두번째달의레포트
UML 다이어그램
객체지향 시스템에 존재하는 클래스, 클래스 안의 필드, 메소드, 서로 협력하거나 상속하는 클래
스 사이의 연결 관계를 나타내는 그림
클래스: 실선/검은 헤드 화살표
추상 클래스: 실선/흰 헤드 화살표 Class
인터페이스: 점선/흰 헤드 화살표
두번째달의레포트
Unity5 이전의 Shaders
물체의 기본적인 음영과 하이라이팅 효과를 부여하는 스페큘러 모델을 구현한 쉐이더가
기본적인 유니티의 표준 쉐이더 이고, 이 스페큘러 모델은 반짝임(Shininess) 또는 스페
큘러 파워(Power)라고 불리는 수치를 조정해 물체가 반사되는 하이라이팅 영역을 조절
하여 사용하였다.
두번째달의레포트
Unity5 이전의 Shaders
실제로 잘 와닿지 않고 접근하기 어렵다는 측면이 있다.
그래서 발전한 것이 물리 기반 쉐이딩이다.
두번째달의레포트
물리 기반 쉐이딩(Physically Based Shading)
Roughness, 물체의 표면이 거친 정도
두번째달의레포트
물리 기반 쉐이딩(Physically Based Shading)
Metallic, 물체의 금속성(특유의 색상과 반사 능력이 있는지)
두번째달의레포트
물리 기반 쉐이딩(Physically Based Shading)
Energy conservation, 에너지 보존 법칙(오브젝트가 빛의 양을 받는 만큼만 반사하도록 조절)
두번째달의레포트
Unity5의 Standard Shader
Standard 와 Standard(Specular setup)
두번째달의레포트
Unity5의 Standard Shader
Rendering Mode
Opaque – default, 투명하지 않은 영역에서의
일반 솔리드 오브젝트에 사용
Cutout – 불투명과 투명영역 사이의 하드 엣지
를 가진 투명효과를 만들 수 있다. 이 모드에서는
반투명 영역이 존재하지 않고, 텍스처는 어느 한
쪽이 100%불투명하거나 보이지 않는다. 구멍이
나 너덜너덜한 잎, 천 같은 투명도를 사용하는 머
티리얼의 형상을 생성할 때 유용하다.
Transparent – 투명한 플라스틱이나 유리 등의
현실적인 투명한 머티리얼과 같은 렌더링에 적합
하다. 머티리얼 자체는 텍스처의 알파 체널과 틴
트 컬러의 알파에 근거한 투명도 값이다. 반사와
조명의 하이라이트는 진짜 투명한 재질 처럼 나타
내준다.
두번째달의레포트
Unity5의 Standard Shader
Fade – 투명도 값이 스펙큘러 하이라이트 및 반
사를 포함해서 오브젝트를 완전히 fade out 할
수 있게 해준다. 이 모드는 오브젝트의 fade in,
fade out 애니메이션을 적용하는 경우에 유용하
다. Transparent와 다르게 반사와 하이라이트도
fade out 되기 때문에 투명한 플라스틱이나 유리
같은 현실적인 투명한 머티리얼을 렌더링하는 데
에는 적합하지 않다.
Rendering Mode
두번째달의레포트
Unity5의 Standard Shader
알베도 색상 알파값은 머티리얼의 투명도를 제어
하는데 이것은 Rendering Mode가
transparent모드 중 하나이며 Opaque가 아닐
때 적용된다. 현실적인 투명한 오브젝트 표현을
위해서는 알베도의 알파값을 조절하면 된다.
알베도 파라미터로 지정되는 텍스쳐를 사용할 경
우, 알베도 텍스쳐 이미지의 알파체널을 통해서
머티리얼의 투명성을 제어할 수 있다. 알파체널값
은 흰색은 완전히 불투명한 것을 말하고 검정은
완전 투명한 것을 의미하며 transparency레벨
에 맵핑된다.
Albedo – 표면의 기본 색상
두번째달의레포트
Unity5의 Standard Shader
Metallic - 표면이 얼마나 금속 같은가를 결정한
다. 1일수록 금속에 가까움.
Smoothness – 표면의 매끄러운 정도를 결정한
다. 1일수록 거울 효과에 가까움
반드시 금속인 머티리얼을 위해서만 있는 것이 아
니다.
Metallic에 텍스쳐를 사용한다면 Smoothness
와 Metallic의 값을 지정할 수 없게 되는데 이럴
경우 텍스쳐의 Red Channel에 따라 Metallic을
조절하고 Alpha Channel을 통해 Smoothness
를 조절한다.
Metallic, Smoothness
두번째달의레포트
Unity5의 Standard Shader
저해상도 모델 데이터를 이용하여 고해상도 모델
데이터의 모습을 표현하여 시뮬레이션 하므로 적
은 시스템 리소스를 이용하여 많은 시스템 리소스
를 사용한 것 과 같은 효율적인 작업을 진행하게
해준다.
Bump map은 1가지 채널의 흑백 이미지만을 사
용해 어두운 부분은 들어가고 밝은 부분은 튀어나
오게 만들어 놓았다.
Normal map은 3가지의 채널(RGB)을 사용해
수직, 수평, 깊이(x, y, z)를 표현한다. 여섯 방향
에서 빛을 쏴 계산하는데 Positive Light는 0-
127까지의 숫자를, Negative Light는 128-
255의 숫자를 갖고 있다.
Normal map(Bump mapping)
두번째달의레포트
Unity5의 Standard Shader
요즘 기준인 Tangent 방식의 Normal Map은
각각의 면을 기준으로 RGB값을 산출하는데 Blue
체널의 값은 반쪽만 쓰이게 된다. (면의 뒷면은 고
려할 필요가 없기 때문에 사용하지 않는다) 그래
서 요새 사용하는 Normal Map은 푸르딩딩한
Normal Map이다
머티리얼에 노말맵을 적용시킬 때 texture type
이 normal맵으로 설정되어 있지 않다면 Fix버튼
이 뜬다
Normal map(Bump mapping)
두번째달의레포트
Unity5의 Standard Shader
Height map = Parallax Mapping =
Displacement Mapping
Height map은 Bump map이랑 비슷하지만
bump map은 높이가 있는 것처럼 표현 할 뿐이
고 height map은 실제 지형의 높이를 만든다. 따
라서 height map이 비용이 좀 비싸다.
Height map
texture mapping, + normal mapping, + height mapping
두번째달의레포트
Unity5의 Standard Shader
모델의 영역이 강하거나 약한 간접조명을 받아야
하는 지에 대한 정보를 제공하는데 사용. (간접조
명은 GI에서 옴)
occlusion Map이 노출이나 주변 조명에서 숨겨
진 캐릭터의 소매 같은 영역을 식별한다.
Occlusion Map
두번째달의레포트
Unity5의 Standard Shader
표면에서 방출되는 빛의 색상과 강도를 제어한다.
값이 클수록 자체 발광하는 것처럼 보인다.
모니터 스크린, 자동차 디스크 브레이크, 제어판
버튼, 어둠 속에서 빛나는 괴물의 눈 등에 사용한
다.
Emission
두번째달의레포트
Unity5의 Standard Shader
Emission Map은 발광하는 물체인 만큼 GI
에 영향을 미치기 때문에 GI Option이 있다.
• None – 혼자 자체발광 중. 주변에
는 영향을 미치지 않는다.
• Realtime – 오브젝트의 발광이 실
시간으로 GI에 영향을 미친다. 따라
서 움직이는 물체에도 영향을 미친
다.
• Baked – 오브젝트의 빛을 static
Light Map에 구워 점등되어 있는
것처럼 보이게 한다. 하지만 동적으
로 움직이는 물체에는 영향을 받지
않는다.
Emission
두번째달의레포트
Unity5의 Standard Shader
캐릭터의 피부에 모공이나 털 같은 피부의
세부사항을 추가하거나 벽돌 벽에 작은 균열
이나 이끼를 추가하거나 큰 금속 용기에 작
은 상처나 찰과상을 추가하는 등의 작업에
사용한다.
두 번째 Albedo맵과 Normal맵을 사용할
수 있다.
Detail Mask는 부분적으로만 Secondary
Map가 적용되도록 하는 mask이다. 예를
들면 입술과 눈썹에는 피부의 모공이 표시되
지 않도록 하는 것이다.
Secondary Maps(Detail Maps) & Detail Mas
두번째달의레포트
Unity5의 Standard Shader
두번째달의레포트
Unity5의 Standard Shader
두번째달의레포트
OBSERVER PATTERN (옵저버 패턴)
객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들한테 연락이 가고 자
동으로 내용이 갱신되는 1:N 의존성을 정의
푸시 기반 알림이 필요한 곳에 사용
데이터의 주인은 주제이다. 옵저버는 데이터가 변경되었을 때 주제에서 갱신
해 주기를 기다린다.
1:N: 상태를 저장하고 지배하는 것은 주제 객체이다.
세번째달의레포트
OBSERVER PATTERN (옵저버 패턴)
 주제가 옵저버에 대해서 아는 것은 옵저버가 특정 인터페이스
(Observer Interface)를 구현한다는 것 뿐이다.
 옵저버는 언제든지 새로 추가 할 수 있다.
 새로운 형식의 옵저버를 추가하려고 할 때도 주제를 전혀 변경할 필요
가 없다.
 주제와 옵저버는 서로 독립적으로 재 사용할 수 있다.
 주제나 옵저버가 바뀌더라도 서로에게 영향을 미치지 않는다.
세번째달의레포트
OBSERVER PATTERN (옵저버 패턴)
 옵저버에게 알림을 전송하는 개체인 주제객체. 주제객체는 IObservable<T> 인터페이스를 구현하는 클래스 또는
구조체이다. 주제객체는 주제객체로부터 알림을 수신하려는 옵저버가 호출하는 단일 메서드
Iobservable<T>.Subscribe를 구현해야 한다.
 주제객체로부터 알림을 수신하는 개체인 옵저버. 옵저버는 IObserver<T> 인터페이스를 구현하는 클래스 또는 구
조체이다. 옵저버는 모두 주제객체에 의해 호출되는 다음 세 개의 메서드를 구현해야 한다
 IObserver<T>.OnNext - 옵저버에게 새 정보나 현재 정보를 제공합니다.
 IObserver<T>.OnError - 오류가 발생했음을 옵저버에게 알립니다.
 IObserver<T>.OnCompleted - 주제객체가 알림 전송을 완료했음을 나타냅니다.
 일반적으로 주제객체는 System.Collections.Generic.List<T> 개체와 같은 컨테이너 개체를 사용하여 알림을 구
독한 IObserver<T> 구현에 대한 참조를 보유합니다. 이 목적으로 저장소 컨테이너를 사용하면 주제객체가 0개에
서 무한대까지 옵저버를 처리할 수 있다. 옵저버가 알림을 수신하는 순서는 정의되지 않는다. 주제객체가 임의 메
서드를 사용하여 순서를 결정할 수 있다.
 알림이 완료될 때 주제객체가 옵저버를 제거할 수 있도록 하는 Idisposable을 구현한다. 옵저버는 Subscribe 메
서드로부터 Idisposable 구현에 대한 참조를 수신하므로 주제객체가 알림 전송을 완료하기 전에
Idisposable.Dispose 메서드를 호출하여 구독을 취소할 수도 있다.
 주제객체가 해당 옵저버에게 전송하는 데이터를 포함하는 개체. 이 개체의 형식은 IObservable<T> 및
IObserver<T> 인터페이스의 제네릭 형식 매개 변수에 해당합니다. 이 개체는 IObservable<T> 구현과 동일할 수
도 있지만 일반적으로 별도 형식입니다.
세번째달의레포트
OBSERVER PATTERN (옵저버 패턴)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class BaggageInfo
{
private int flightNo;
private string origin;
private int location;
internal BaggageInfo(int flight, string from, int carousel)
{
this.flightNo = flight;
this.origin = from;
this.location = carousel;
}
public int FlightNumber {
get { return this.flightNo; }
}
public string From {
get { return this.origin; }
}
public int Carousel {
get { return this.location; }
}
} c
세번째달의레포트
OBSERVER PATTERN (옵저버 패턴)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class BaggageHandler : IObservable<BaggageInfo>
{
private List<IObserver<BaggageInfo>> observers;
private List<BaggageInfo> flights;
public BaggageHandler()
{
observers = new List<IObserver<BaggageInfo>>();
flights = new List<BaggageInfo>();
}
public IDisposable Subscribe(IObserver<BaggageInfo> observer)
{
// Check whether observer is already registered. If not, add it
if (! observers.Contains(observer)) {
observers.Add(observer);
// Provide observer with existing data.
foreach (var item in flights)
observer.OnNext(item);
}
return new Unsubscriber<BaggageInfo>(observers, observer);
}
c
s
주제객체
세번째달의레포트
OBSERVER PATTERN (옵저버 패턴)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public void BaggageStatus(int flightNo, string from, int carousel)
{
var info = new BaggageInfo(flightNo, from, carousel);
// Carousel is assigned, so add new info object to list.
if (carousel > 0 && ! flights.Contains(info)) {
flights.Add(info);
foreach (var observer in observers)
observer.OnNext(info);
}
else if (carousel == 0) {
// Baggage claim for flight is done
var flightsToRemove = new List<BaggageInfo>();
foreach (var flight in flights) {
if (info.FlightNumber == flight.FlightNumber) {
flightsToRemove.Add(flight);
foreach (var observer in observers)
observer.OnNext(info);
}
}
foreach (var flightToRemove in flightsToRemove)
flights.Remove(flightToRemove);
flightsToRemove.Clear();
}
}
} c
세번째달의레포트
OBSERVER PATTERN (옵저버 패턴)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
internal class Unsubscriber<BaggageInfo> : IDisposable
{
private List<IObserver<BaggageInfo>> _observers;
private IObserver<BaggageInfo> _observer;
internal Unsubscriber(List<IObserver<BaggageInfo>> observers, IObserver<BaggageInfo> observer)
{
this._observers = observers;
this._observer = observer;
}
public void Dispose()
{
if (_observers.Contains(_observer))
_observers.Remove(_observer);
}
} c
세번째달의레포트
OBSERVER PATTERN (옵저버 패턴)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class ArrivalsMonitor : IObserver<BaggageInfo>
{
private string name;
private List<string> flightInfos = new List<string>();
private IDisposable cancellation;
private string fmt = "{0,-20} {1,5} {2, 3}";
public ArrivalsMonitor(string name)
{
if (String.IsNullOrEmpty(name))
throw new ArgumentNullException("The observer must be assigned a name.");
this.name = name;
}
public virtual void Subscribe(BaggageHandler provider)
{
cancellation = provider.Subscribe(this);
}
public virtual void Unsubscribe()
{
cancellation.Dispose();
flightInfos.Clear();
}
public virtual void OnCompleted()
{
flightInfos.Clear();
} c
옵저버
세번째달의레포트
OBSERVER PATTERN (옵저버 패턴)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public virtual void OnNext(BaggageInfo info)
{
bool updated = false;
if (info.Carousel == 0) {
var flightsToRemove = new List<string>();
string flightNo = String.Format("{0,5}", info.FlightNumber);
foreach (var flightInfo in flightInfos) {
if (flightInfo.Substring(21, 5).Equals(flightNo)) {
flightsToRemove.Add(flightInfo);
updated = true;
}
}
foreach (var flightToRemove in flightsToRemove)
flightInfos.Remove(flightToRemove);
flightsToRemove.Clear();
}
else {
string flightInfo = String.Format(fmt, info.From, info.FlightNumber, info.Carousel);
if (! flightInfos.Contains(flightInfo)) {
flightInfos.Add(flightInfo);
updated = true;
}
}
if (updated) {
flightInfos.Sort();
Console.WriteLine("Arrivals information from {0}", this.name);
foreach (var flightInfo in flightInfos)
Console.WriteLine(flightInfo);
세번째달의레포트
OBSERVER PATTERN (옵저버 패턴)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Example
{
public static void Main()
{
BaggageHandler provider = new BaggageHandler();
ArrivalsMonitor observer1 = new ArrivalsMonitor("BaggageClaimMonitor1");
ArrivalsMonitor observer2 = new ArrivalsMonitor("SecurityExit");
provider.BaggageStatus(712, "Detroit", 3);
observer1.Subscribe(provider);
provider.BaggageStatus(712, "Kalamazoo", 3);
provider.BaggageStatus(400, "New York-Kennedy", 1);
provider.BaggageStatus(712, "Detroit", 3);
observer2.Subscribe(provider);
provider.BaggageStatus(511, "San Francisco", 2);
provider.BaggageStatus(712);
observer2.Unsubscribe();
provider.BaggageStatus(400);
provider.LastBaggageClaimed();
}
} cs
세번째달의레포트
OBSERVER PATTERN (옵저버 패턴)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Example
{
public static void Main()
{
BaggageHandler provider = new BaggageHandler();
ArrivalsMonitor observer1 = new ArrivalsMonitor("BaggageClaimMonitor1");
ArrivalsMonitor observer2 = new ArrivalsMonitor("SecurityExit");
provider.BaggageStatus(712, "Detroit", 3);
observer1.Subscribe(provider);
provider.BaggageStatus(712, "Kalamazoo", 3);
provider.BaggageStatus(400, "New York-Kennedy", 1);
provider.BaggageStatus(712, "Detroit", 3);
observer2.Subscribe(provider);
provider.BaggageStatus(511, "San Francisco", 2);
provider.BaggageStatus(712);
observer2.Unsubscribe();
provider.BaggageStatus(400);
provider.LastBaggageClaimed();
}
} c
세번째달의레포트
OBSERVER PATTERN (옵저버 패턴)
옵저버 패턴 사용시 주의점
예외처리
공급자 - OnError 메서드 호출
• 공급자는 관찰자가 특정 방식으로 예외를 처리한다고 예상하거나 처리하도록 요구해서는
안 됩니다.
• 공급자는 업데이트 제공 기능을 손상시키는 예외를 처리할 때 OnError 메서드를 호출해
야 합니다.이러한 예외에 대한 정보를 관찰자에게 전달할 수 있습니다.다른 경우에는 관
찰자에게 예외에 대해 알릴 필요가 없습니다.
• 공급자는 특정 요구 사항이 있는 경우 자체 예외를 처리해야 합니다.
관찰자 - OnError 메서드를 구현
• 관찰자는 OnNext 또는 OnError 등의 인터페이스 구현에서 예외를 throw해서는 안 됩
니다.관찰자가 예외를 throw하는 경우 해당 예외는 처리되지 않습니다.
• 호출 스택을 유지하려면 OnError 메서드로 전달된 Exception 개체를 throw하려는 관
찰자는 예외를 throw하기 전에 래핑해야 합니다.이렇게 하려면 표준 예외 개체를 사용해
야 합니다.
세번째달의레포트
OBSERVER PATTERN (옵저버 패턴)
옵저버 패턴 사용시 주의점
스레딩
일반적으로 공급자는 컬렉션 개체로 표시되는 구독자 목록에 특정 관찰자를 추가하
여 IObservable<T>.Subscribe 메서드를 구현하며, 구독자 목록에서 특정 관찰자를 제거하
여 IDisposable.Dispose 메서드를 구현합니다.관찰자는 언제든지 이러한 메서드를 호출할 수
있습니다. 또한 공급자/관찰자 계약에서는 IObserver<T>.OnCompleted 콜백 메서드 후 구
독 취소 담당자를 지정하지 않으므로 공급자와 관찰자가 모두 목록에서 같은 멤버를 제거하려고
할 수 있습니다.이러한 가능성 때문에 Subscribe 및 Dispose 메서드는 모두 스레드로부터 안
전해야 합니다.일반적으로는 이를 위해 동시 컬렉션 또는 잠금을 사용합니다.스레드로부터 안전
하지 않은 구현은 스레드로부터 안전하지 않음을 명시적으로 문서화해야 합니다.
추가로 보장할 내용은 공급자/관찰자 계약을 기반으로 하는 계층에 지정해야 합니다.구현자는
관찰자 계약에 대한 사용자의 혼동을 방지하기 위해 추가 요구를 사항을 적용하는 경우 이를 명
확하게 표시해야 합니다.
그 외
관찰자는 OnNext 또는 OnError 등의 인터페이스 구현에서 예외를 throw해서는 안 됩니다.관
찰자가 예외를 throw하는 경우 해당 예외는 처리되지 않습니다.
호출 스택을 유지하려면 OnError 메서드로 전달된 Exception 개체를 throw하려는 관찰자는
예외를 throw하기 전에 래핑해야 합니다.이렇게 하려면 표준 예외 개체를 사용해야 합니다.
세번째달의레포트
DECORATOR PATTERN (데코레이터 패턴)
세번째달의레포트
DECORATOR PATTERN (데코레이터 패턴)
세번째달의레포트
DECORATOR PATTERN (데코레이터 패턴)
데코레이터는 서브 클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법.
장점
1. 데코레이터의 수퍼클래스는 자신이 장식하고 있는 객체의 수퍼클래스와 같다.
2. 한 객체를 여러 개의 데코레이터로 감쌀 수 있다.
3. 데코레이터는 자신이 감싸고 있는 객체와 같은 수퍼클래스를 가지고 있기 때문에 원래 객
체(싸여져 있는 객체)가 들어갈 자리에 데코레이터 객체를 넣어도 상관 없습니다.
4. 데코레이터는 자신이 장식하고 있는 객체에게 어떤 행동을 위임하는 것 외에 원하는 추가
적인 작업을 수행할 수 있습니다.
5. 객체는 언제든지 감쌀 수 있기 때문에 실행중에 필요한 데코레이터를 마음대로 적용할 수
있습니다.
단점
1. 데코레이터 패턴을 이용해 디자인을 하다 보면 잡다한 클래스가 많아 질 수 있다.
2. 겹겹이 애워싼 객체의 정체를 알기가 힘들다.
3. 상속을 통해 확장할 수도 있지만, 디자인 유연성 면에서는 별로 좋지 않다.
세번째달의레포트
DECORATOR PATTERN (데코레이터 패턴)
데코레이터는 서브 클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법.
세번째달의레포트
DECORATOR PATTERN (데코레이터 패턴)
데코레이터는 서브 클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법.
1
2
3
4
5
6
7
8
9
10
11
public abstract class Beverage
{
protected String description = "제목없음";
public abstract double cost();
public virtual string getDescription()
{
return description;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
public class Espresso : Beverage
{
public Espresso()
{
description = "에스프레소 커피";
}
public override double cost()
{
return 1.99;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
public class DarkRoast : Beverage
{
public DarkRoast()
{
description = "다크로스트 커피";
}
public override double cost()
{
return .99;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
public class Decaf : Beverage
{
public Decaf()
{
description = "디카페인 커피";
}
public override double cost()
{
return 1.05;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
public class HouseBlend: Beverage
{
public HouseBlend()
{
description = "하우스블랜드 커피";
}
public override double cost()
{
return .89;
}
} c
세번째달의레포트
DECORATOR PATTERN (데코레이터 패턴)
데코레이터는 서브 클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법.
1
2
3
4
public abstract class CondimentDecorator : Beverage
{
public override abstract string getDescription();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Milk: CondimentDecorator
{
private Beverage beverage;
public Milk(Beverage beverage)
{
this.beverage = beverage;
}
public override string getDescription()
{
return beverage.getDescription() + ", 스팀밀크";
}
public override double cost()
{
return beverage.cost() + .10;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Soy : CondimentDecorator
{
private Beverage beverage;
public Soy(Beverage beverage)
{
this.beverage = beverage;
}
public override string getDescription()
{
return beverage.getDescription() + ", 두유";
}
public override double cost()
{
return beverage.cost() + .15;
}
}
세번째달의레포트
그만두고나서
11월에 들어서...
그만두고나서
11월에 들어서...
그만두고나서
11월에 들어서...
그만두고나서
11월에 들어서...

More Related Content

2015.12.05 쪼꼬두유 방황기

  • 2. 첫번째달의레포트 LINQ = Language Integrated Query SEVENTEEN 멤버 중에 성인 멤버를 구분해 내기 위해서 코드를 짜는데
  • 3. 첫번째달의레포트 LINQ = Language Integrated Query 1 2 3 4 5 6 7 8 9 var NotMinor = from Member in seventeen where Member.Age > 19 orderby Member.Age select Member; foreach(Member member in NotMinor) { Console.WriteLine(member); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 List<Member> NotMinor = new List<Member>(); foreach (Member member in seventeen) { if (member.Age > 19) NotMinor.Add(member); } NotMinor.Sort((memberA, memberB) => memberA.Age - memberB.Age); foreach (Member member in NotMinor) { Console.WriteLine(member); } c LINQ를 쓰면 코드가 단순해지며 가독성이 올라간다.
  • 4. 첫번째달의레포트 LINQ = LINQ는 Language Integrated Query var NotMinor = from Member in seventeen where Member.Age > 19 orderby Member.Age select Member; 데이터를 검색하기 위해서 데이터를 검색할 범위를 지정해줌 반드시 범위를 지정해주고 시작해야 한다. Foreach 처럼 사용하면 된다.
  • 5. 첫번째달의레포트 LINQ = LINQ는 Language Integrated Query var NotMinor = from Member in seventeen where Member.Age > 19 orderby Member.Age select Member; Foreach랑 다른 점은 Foreach의 element 변수에는 실제로 array의 데이터가 저장 된다.하지만 LINQ에서는 element 변수에 데이터가 저장되지 않고, 단순히 'array에 존재하는 요소'라는 의미로만 사용된다.
  • 6. 첫번째달의레포트 LINQ = LINQ는 Language Integrated Query var NotMinor = from Member in seventeen where Member.Age > 19 orderby Member.Age select Member; from에서 사용 가능한 타입은 IEnumerable<T> 인터페이스를 상속하는 타입이다. C#에서의 배열이나 컬렉션등은 모두 IEnumerable<T>을 상속하기 때문에 배열이나 컬렉션 타입이 라면 전부 사용 가능하다.
  • 7. 첫번째달의레포트 LINQ = LINQ는 Language Integrated Query 지정한 데이터 범위 내에서 한 번 더 데이터 범위를 지정하려면 from절을 중첩해서 사용하면 된다. var Students = from student in studentList from score in student.score where score > 89 select new {student.name, failScore = score};
  • 8. 첫번째달의레포트 LINQ = LINQ는 Language Integrated Query var NotMinor = from Member in seventeen where Member.Age > 19 orderby Member.Age select Member; where은 범위 내에서 데이터를 걸러내는 필터 역할을 한다. 따 라서 where에서는 데이터를 걸러내기 위한 필터 조건을 작성해 주면 된다. 그러면 해당 조건에 참이 되는 데이터만 걸러지게 된 다.
  • 9. 첫번째달의레포트 LINQ = LINQ는 Language Integrated Query var NotMinor = from Member in seventeen where Member.Age > 19 orderby Member.Age select Member; orderby는 걸러진 데이터를 정렬해주는 연산자이다. 기본 오름차순 정렬이고 뒤에 descending을 붙여주면 내림차 순 정렬을 한다.
  • 10. 첫번째달의레포트 LINQ = LINQ는 Language Integrated Query var NotMinor = from Member in seventeen where Member.Age > 19 orderby Member.Age select Member; 최종적으로 검색된 데이터를 추출하는 역할을 한다. 추출된 데 이터의 타입은 select절에 지정한 변수의 타입으로 결정되며, 무명형식(타입)으로 만들어서 추출할 수도 있다.
  • 11. 첫번째달의레포트 LINQ = LINQ는 Language Integrated Query var NotMinor = from Member in seventeen where Member.Age > 19 orderby Member.Age select Member.name; 최종적으로 검색된 데이터를 추출하는 역할을 한다. 추출된 데 이터의 타입은 select절에 지정한 변수의 타입으로 결정되며, 무명형식(타입)으로 만들어서 추출할 수도 있다.
  • 12. 첫번째달의레포트 LINQ = LINQ는 Language Integrated Query var NotMinor = from Member in seventeen where Member.Age > 19 orderby Member.Age select new{Name = Member.Name, Age = Member.Age}; 최종적으로 검색된 데이터를 추출하는 역할을 한다. 추출된 데 이터의 타입은 select절에 지정한 변수의 타입으로 결정되며, 무명형식(타입)으로 만들어서 추출할 수도 있다.
  • 13. 첫번째달의레포트 LINQ = LINQ는 Language Integrated Query 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 var Group = from person in peopleList group person by person.Sex == "남자" into data select new { sexCeheck = data.Key, People = data }; foreach(var group in Group) { if(group.sexCeheck == true) { Console.WriteLine("<남자>"); foreach (var person in group.People) Console.WriteLine("이름 : " + person.Name); } else { Console.WriteLine("<여자>"); foreach (var person in group.People) Console.WriteLine("이름 : " + person.Name); } } c
  • 14. 첫번째달의레포트 LINQ = LINQ는 Language Integrated Query 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 var Group = from person in peopleList group person by person.Sex == "남자" into data select new { sexCeheck = data.Key, People = data }; foreach(var group in Group) { if(group.sexCeheck == true) { Console.WriteLine("<남자>"); foreach (var person in group.People) Console.WriteLine("이름 : " + person.Name); } else { Console.WriteLine("<여자>"); foreach (var person in group.People) Console.WriteLine("이름 : " + person.Name); } } c Group 데이터 sexCheck FALSE sexCheck TRUE
  • 15. 첫번째달의레포트 LINQ = LINQ는 Language Integrated Query 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 List<Member> seventeen = new List<Member>(); seventeen.Add(new Member() { Name = "에스쿱스", Age = 21 }); seventeen.Add(new Member() { Name = "정한", Age = 21 }); seventeen.Add(new Member() { Name = "조슈아", Age = 21 }); seventeen.Add(new Member() { Name = "준", Age = 20 }); seventeen.Add(new Member() { Name = "호시", Age = 20 }); seventeen.Add(new Member() { Name = "우지", Age = 20 }); seventeen.Add(new Member() { Name = "원우", Age = 20 }); seventeen.Add(new Member() { Name = "도겸", Age = 19 }); seventeen.Add(new Member() { Name = "민규", Age = 19 }); seventeen.Add(new Member() { Name = "디에잇", Age = 19 }); seventeen.Add(new Member() { Name = "승관", Age = 18 }); seventeen.Add(new Member() { Name = "버논", Age = 18 }); seventeen.Add(new Member() { Name = "디노", Age = 17 }); List<Body> bodies = new List<Body>(); bodies.Add(new Body() { Name = "도겸", Height = 179, Weight = 66 }); bodies.Add(new Body() { Name = "민규", Height = 185, Weight = 53 }); bodies.Add(new Body() { Name = "승관", Height = 174, Weight = 60 }); bodies.Add(new Body() { Name = "버논", Height = 175, Weight = 56 }); bodies.Add(new Body() { Name = "디노", Height = 170, Weight = 56 }); var Minors = from member in seventeen join body in bodies on member.Name equals body.Name select new { Name = member.Name, Age = member.Age, Height = body.Height, Weight = body.Weight }; foreach(var member in Minors) { Console.WriteLine(member); } c
  • 16. 첫번째달의레포트 LINQ = LINQ는 Language Integrated Query 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 List<Member> seventeen = new List<Member>(); seventeen.Add(new Member() { Name = "에스쿱스", Age = 21 }); seventeen.Add(new Member() { Name = "정한", Age = 21 }); seventeen.Add(new Member() { Name = "조슈아", Age = 21 }); seventeen.Add(new Member() { Name = "준", Age = 20 }); seventeen.Add(new Member() { Name = "호시", Age = 20 }); seventeen.Add(new Member() { Name = "우지", Age = 20 }); seventeen.Add(new Member() { Name = "원우", Age = 20 }); seventeen.Add(new Member() { Name = "도겸", Age = 19 }); seventeen.Add(new Member() { Name = "민규", Age = 19 }); seventeen.Add(new Member() { Name = "디에잇", Age = 19 }); seventeen.Add(new Member() { Name = "승관", Age = 18 }); seventeen.Add(new Member() { Name = "버논", Age = 18 }); seventeen.Add(new Member() { Name = "디노", Age = 17 }); List<Body> bodies = new List<Body>(); bodies.Add(new Body() { Name = "도겸", Height = 179, Weight = 66 }); bodies.Add(new Body() { Name = "민규", Height = 185, Weight = 53 }); bodies.Add(new Body() { Name = "승관", Height = 174, Weight = 60 }); bodies.Add(new Body() { Name = "버논", Height = 175, Weight = 56 }); bodies.Add(new Body() { Name = "디노", Height = 170, Weight = 56 }); var Minors = from member in seventeen join body in bodies on member.Name equals body.Name select new { Name = member.Name, Age = member.Age, Height = body.Height, Weight = body.Weight }; foreach(var member in Minors) { Console.WriteLine(member); } c A B C B C D B C
  • 17. 첫번째달의레포트 LINQ = LINQ는 Language Integrated Query A B C B C D A B C 1 2 3 4 5 var Minors = from member in seventeen join body in bodies on member.Name equals body.Name into temp from body in temp.DefaultIfEmpty( new Body() { Height = 0, Weight = 0}) select new { Name = member.Name, Age = member.Age, Height = body.Height, Weight = body.Weight }; c
  • 23. 카메라에 찍히는지 안 찍히는지 검사하는 함수 두번째달의레포트
  • 24. 근데 계속 돌려도 안없어지고 쌓이더라... 두번째달의레포트
  • 25. 알고봤더니 표시되지 않는 SceneView도 카메라로 표시하더라... 두번째달의레포트
  • 26. UML 다이어그램 객체지향 시스템에 존재하는 클래스, 클래스 안의 필드, 메소드, 서로 협력하거나 상속하는 클래 스 사이의 연결 관계를 나타내는 그림 Rectangle -width: int -height: int /area: double + Rectangle(width: int, height: int) + distance(r: Rectangle): double Student -name: String -id: int -totalStudents: int #getID(): int +getName(): String ~getrEmailAddress(): String +getTotalStudents(): int + public # protected - private ~ package, namespace / derived(상속 받음) Underline : static variable 두번째달의레포트
  • 27. UML 다이어그램 객체지향 시스템에 존재하는 클래스, 클래스 안의 필드, 메소드, 서로 협력하거나 상속하는 클래 스 사이의 연결 관계를 나타내는 그림 두번째달의레포트
  • 28. UML 다이어그램 객체지향 시스템에 존재하는 클래스, 클래스 안의 필드, 메소드, 서로 협력하거나 상속하는 클래 스 사이의 연결 관계를 나타내는 그림 클래스: 실선/검은 헤드 화살표 추상 클래스: 실선/흰 헤드 화살표 Class 인터페이스: 점선/흰 헤드 화살표 두번째달의레포트
  • 29. Unity5 이전의 Shaders 물체의 기본적인 음영과 하이라이팅 효과를 부여하는 스페큘러 모델을 구현한 쉐이더가 기본적인 유니티의 표준 쉐이더 이고, 이 스페큘러 모델은 반짝임(Shininess) 또는 스페 큘러 파워(Power)라고 불리는 수치를 조정해 물체가 반사되는 하이라이팅 영역을 조절 하여 사용하였다. 두번째달의레포트
  • 30. Unity5 이전의 Shaders 실제로 잘 와닿지 않고 접근하기 어렵다는 측면이 있다. 그래서 발전한 것이 물리 기반 쉐이딩이다. 두번째달의레포트
  • 31. 물리 기반 쉐이딩(Physically Based Shading) Roughness, 물체의 표면이 거친 정도 두번째달의레포트
  • 32. 물리 기반 쉐이딩(Physically Based Shading) Metallic, 물체의 금속성(특유의 색상과 반사 능력이 있는지) 두번째달의레포트
  • 33. 물리 기반 쉐이딩(Physically Based Shading) Energy conservation, 에너지 보존 법칙(오브젝트가 빛의 양을 받는 만큼만 반사하도록 조절) 두번째달의레포트
  • 34. Unity5의 Standard Shader Standard 와 Standard(Specular setup) 두번째달의레포트
  • 35. Unity5의 Standard Shader Rendering Mode Opaque – default, 투명하지 않은 영역에서의 일반 솔리드 오브젝트에 사용 Cutout – 불투명과 투명영역 사이의 하드 엣지 를 가진 투명효과를 만들 수 있다. 이 모드에서는 반투명 영역이 존재하지 않고, 텍스처는 어느 한 쪽이 100%불투명하거나 보이지 않는다. 구멍이 나 너덜너덜한 잎, 천 같은 투명도를 사용하는 머 티리얼의 형상을 생성할 때 유용하다. Transparent – 투명한 플라스틱이나 유리 등의 현실적인 투명한 머티리얼과 같은 렌더링에 적합 하다. 머티리얼 자체는 텍스처의 알파 체널과 틴 트 컬러의 알파에 근거한 투명도 값이다. 반사와 조명의 하이라이트는 진짜 투명한 재질 처럼 나타 내준다. 두번째달의레포트
  • 36. Unity5의 Standard Shader Fade – 투명도 값이 스펙큘러 하이라이트 및 반 사를 포함해서 오브젝트를 완전히 fade out 할 수 있게 해준다. 이 모드는 오브젝트의 fade in, fade out 애니메이션을 적용하는 경우에 유용하 다. Transparent와 다르게 반사와 하이라이트도 fade out 되기 때문에 투명한 플라스틱이나 유리 같은 현실적인 투명한 머티리얼을 렌더링하는 데 에는 적합하지 않다. Rendering Mode 두번째달의레포트
  • 37. Unity5의 Standard Shader 알베도 색상 알파값은 머티리얼의 투명도를 제어 하는데 이것은 Rendering Mode가 transparent모드 중 하나이며 Opaque가 아닐 때 적용된다. 현실적인 투명한 오브젝트 표현을 위해서는 알베도의 알파값을 조절하면 된다. 알베도 파라미터로 지정되는 텍스쳐를 사용할 경 우, 알베도 텍스쳐 이미지의 알파체널을 통해서 머티리얼의 투명성을 제어할 수 있다. 알파체널값 은 흰색은 완전히 불투명한 것을 말하고 검정은 완전 투명한 것을 의미하며 transparency레벨 에 맵핑된다. Albedo – 표면의 기본 색상 두번째달의레포트
  • 38. Unity5의 Standard Shader Metallic - 표면이 얼마나 금속 같은가를 결정한 다. 1일수록 금속에 가까움. Smoothness – 표면의 매끄러운 정도를 결정한 다. 1일수록 거울 효과에 가까움 반드시 금속인 머티리얼을 위해서만 있는 것이 아 니다. Metallic에 텍스쳐를 사용한다면 Smoothness 와 Metallic의 값을 지정할 수 없게 되는데 이럴 경우 텍스쳐의 Red Channel에 따라 Metallic을 조절하고 Alpha Channel을 통해 Smoothness 를 조절한다. Metallic, Smoothness 두번째달의레포트
  • 39. Unity5의 Standard Shader 저해상도 모델 데이터를 이용하여 고해상도 모델 데이터의 모습을 표현하여 시뮬레이션 하므로 적 은 시스템 리소스를 이용하여 많은 시스템 리소스 를 사용한 것 과 같은 효율적인 작업을 진행하게 해준다. Bump map은 1가지 채널의 흑백 이미지만을 사 용해 어두운 부분은 들어가고 밝은 부분은 튀어나 오게 만들어 놓았다. Normal map은 3가지의 채널(RGB)을 사용해 수직, 수평, 깊이(x, y, z)를 표현한다. 여섯 방향 에서 빛을 쏴 계산하는데 Positive Light는 0- 127까지의 숫자를, Negative Light는 128- 255의 숫자를 갖고 있다. Normal map(Bump mapping) 두번째달의레포트
  • 40. Unity5의 Standard Shader 요즘 기준인 Tangent 방식의 Normal Map은 각각의 면을 기준으로 RGB값을 산출하는데 Blue 체널의 값은 반쪽만 쓰이게 된다. (면의 뒷면은 고 려할 필요가 없기 때문에 사용하지 않는다) 그래 서 요새 사용하는 Normal Map은 푸르딩딩한 Normal Map이다 머티리얼에 노말맵을 적용시킬 때 texture type 이 normal맵으로 설정되어 있지 않다면 Fix버튼 이 뜬다 Normal map(Bump mapping) 두번째달의레포트
  • 41. Unity5의 Standard Shader Height map = Parallax Mapping = Displacement Mapping Height map은 Bump map이랑 비슷하지만 bump map은 높이가 있는 것처럼 표현 할 뿐이 고 height map은 실제 지형의 높이를 만든다. 따 라서 height map이 비용이 좀 비싸다. Height map texture mapping, + normal mapping, + height mapping 두번째달의레포트
  • 42. Unity5의 Standard Shader 모델의 영역이 강하거나 약한 간접조명을 받아야 하는 지에 대한 정보를 제공하는데 사용. (간접조 명은 GI에서 옴) occlusion Map이 노출이나 주변 조명에서 숨겨 진 캐릭터의 소매 같은 영역을 식별한다. Occlusion Map 두번째달의레포트
  • 43. Unity5의 Standard Shader 표면에서 방출되는 빛의 색상과 강도를 제어한다. 값이 클수록 자체 발광하는 것처럼 보인다. 모니터 스크린, 자동차 디스크 브레이크, 제어판 버튼, 어둠 속에서 빛나는 괴물의 눈 등에 사용한 다. Emission 두번째달의레포트
  • 44. Unity5의 Standard Shader Emission Map은 발광하는 물체인 만큼 GI 에 영향을 미치기 때문에 GI Option이 있다. • None – 혼자 자체발광 중. 주변에 는 영향을 미치지 않는다. • Realtime – 오브젝트의 발광이 실 시간으로 GI에 영향을 미친다. 따라 서 움직이는 물체에도 영향을 미친 다. • Baked – 오브젝트의 빛을 static Light Map에 구워 점등되어 있는 것처럼 보이게 한다. 하지만 동적으 로 움직이는 물체에는 영향을 받지 않는다. Emission 두번째달의레포트
  • 45. Unity5의 Standard Shader 캐릭터의 피부에 모공이나 털 같은 피부의 세부사항을 추가하거나 벽돌 벽에 작은 균열 이나 이끼를 추가하거나 큰 금속 용기에 작 은 상처나 찰과상을 추가하는 등의 작업에 사용한다. 두 번째 Albedo맵과 Normal맵을 사용할 수 있다. Detail Mask는 부분적으로만 Secondary Map가 적용되도록 하는 mask이다. 예를 들면 입술과 눈썹에는 피부의 모공이 표시되 지 않도록 하는 것이다. Secondary Maps(Detail Maps) & Detail Mas 두번째달의레포트
  • 48. OBSERVER PATTERN (옵저버 패턴) 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들한테 연락이 가고 자 동으로 내용이 갱신되는 1:N 의존성을 정의 푸시 기반 알림이 필요한 곳에 사용 데이터의 주인은 주제이다. 옵저버는 데이터가 변경되었을 때 주제에서 갱신 해 주기를 기다린다. 1:N: 상태를 저장하고 지배하는 것은 주제 객체이다. 세번째달의레포트
  • 49. OBSERVER PATTERN (옵저버 패턴)  주제가 옵저버에 대해서 아는 것은 옵저버가 특정 인터페이스 (Observer Interface)를 구현한다는 것 뿐이다.  옵저버는 언제든지 새로 추가 할 수 있다.  새로운 형식의 옵저버를 추가하려고 할 때도 주제를 전혀 변경할 필요 가 없다.  주제와 옵저버는 서로 독립적으로 재 사용할 수 있다.  주제나 옵저버가 바뀌더라도 서로에게 영향을 미치지 않는다. 세번째달의레포트
  • 50. OBSERVER PATTERN (옵저버 패턴)  옵저버에게 알림을 전송하는 개체인 주제객체. 주제객체는 IObservable<T> 인터페이스를 구현하는 클래스 또는 구조체이다. 주제객체는 주제객체로부터 알림을 수신하려는 옵저버가 호출하는 단일 메서드 Iobservable<T>.Subscribe를 구현해야 한다.  주제객체로부터 알림을 수신하는 개체인 옵저버. 옵저버는 IObserver<T> 인터페이스를 구현하는 클래스 또는 구 조체이다. 옵저버는 모두 주제객체에 의해 호출되는 다음 세 개의 메서드를 구현해야 한다  IObserver<T>.OnNext - 옵저버에게 새 정보나 현재 정보를 제공합니다.  IObserver<T>.OnError - 오류가 발생했음을 옵저버에게 알립니다.  IObserver<T>.OnCompleted - 주제객체가 알림 전송을 완료했음을 나타냅니다.  일반적으로 주제객체는 System.Collections.Generic.List<T> 개체와 같은 컨테이너 개체를 사용하여 알림을 구 독한 IObserver<T> 구현에 대한 참조를 보유합니다. 이 목적으로 저장소 컨테이너를 사용하면 주제객체가 0개에 서 무한대까지 옵저버를 처리할 수 있다. 옵저버가 알림을 수신하는 순서는 정의되지 않는다. 주제객체가 임의 메 서드를 사용하여 순서를 결정할 수 있다.  알림이 완료될 때 주제객체가 옵저버를 제거할 수 있도록 하는 Idisposable을 구현한다. 옵저버는 Subscribe 메 서드로부터 Idisposable 구현에 대한 참조를 수신하므로 주제객체가 알림 전송을 완료하기 전에 Idisposable.Dispose 메서드를 호출하여 구독을 취소할 수도 있다.  주제객체가 해당 옵저버에게 전송하는 데이터를 포함하는 개체. 이 개체의 형식은 IObservable<T> 및 IObserver<T> 인터페이스의 제네릭 형식 매개 변수에 해당합니다. 이 개체는 IObservable<T> 구현과 동일할 수 도 있지만 일반적으로 별도 형식입니다. 세번째달의레포트
  • 51. OBSERVER PATTERN (옵저버 패턴) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class BaggageInfo { private int flightNo; private string origin; private int location; internal BaggageInfo(int flight, string from, int carousel) { this.flightNo = flight; this.origin = from; this.location = carousel; } public int FlightNumber { get { return this.flightNo; } } public string From { get { return this.origin; } } public int Carousel { get { return this.location; } } } c 세번째달의레포트
  • 52. OBSERVER PATTERN (옵저버 패턴) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class BaggageHandler : IObservable<BaggageInfo> { private List<IObserver<BaggageInfo>> observers; private List<BaggageInfo> flights; public BaggageHandler() { observers = new List<IObserver<BaggageInfo>>(); flights = new List<BaggageInfo>(); } public IDisposable Subscribe(IObserver<BaggageInfo> observer) { // Check whether observer is already registered. If not, add it if (! observers.Contains(observer)) { observers.Add(observer); // Provide observer with existing data. foreach (var item in flights) observer.OnNext(item); } return new Unsubscriber<BaggageInfo>(observers, observer); } c s 주제객체 세번째달의레포트
  • 53. OBSERVER PATTERN (옵저버 패턴) 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 public void BaggageStatus(int flightNo, string from, int carousel) { var info = new BaggageInfo(flightNo, from, carousel); // Carousel is assigned, so add new info object to list. if (carousel > 0 && ! flights.Contains(info)) { flights.Add(info); foreach (var observer in observers) observer.OnNext(info); } else if (carousel == 0) { // Baggage claim for flight is done var flightsToRemove = new List<BaggageInfo>(); foreach (var flight in flights) { if (info.FlightNumber == flight.FlightNumber) { flightsToRemove.Add(flight); foreach (var observer in observers) observer.OnNext(info); } } foreach (var flightToRemove in flightsToRemove) flights.Remove(flightToRemove); flightsToRemove.Clear(); } } } c 세번째달의레포트
  • 54. OBSERVER PATTERN (옵저버 패턴) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 internal class Unsubscriber<BaggageInfo> : IDisposable { private List<IObserver<BaggageInfo>> _observers; private IObserver<BaggageInfo> _observer; internal Unsubscriber(List<IObserver<BaggageInfo>> observers, IObserver<BaggageInfo> observer) { this._observers = observers; this._observer = observer; } public void Dispose() { if (_observers.Contains(_observer)) _observers.Remove(_observer); } } c 세번째달의레포트
  • 55. OBSERVER PATTERN (옵저버 패턴) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public class ArrivalsMonitor : IObserver<BaggageInfo> { private string name; private List<string> flightInfos = new List<string>(); private IDisposable cancellation; private string fmt = "{0,-20} {1,5} {2, 3}"; public ArrivalsMonitor(string name) { if (String.IsNullOrEmpty(name)) throw new ArgumentNullException("The observer must be assigned a name."); this.name = name; } public virtual void Subscribe(BaggageHandler provider) { cancellation = provider.Subscribe(this); } public virtual void Unsubscribe() { cancellation.Dispose(); flightInfos.Clear(); } public virtual void OnCompleted() { flightInfos.Clear(); } c 옵저버 세번째달의레포트
  • 56. OBSERVER PATTERN (옵저버 패턴) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public virtual void OnNext(BaggageInfo info) { bool updated = false; if (info.Carousel == 0) { var flightsToRemove = new List<string>(); string flightNo = String.Format("{0,5}", info.FlightNumber); foreach (var flightInfo in flightInfos) { if (flightInfo.Substring(21, 5).Equals(flightNo)) { flightsToRemove.Add(flightInfo); updated = true; } } foreach (var flightToRemove in flightsToRemove) flightInfos.Remove(flightToRemove); flightsToRemove.Clear(); } else { string flightInfo = String.Format(fmt, info.From, info.FlightNumber, info.Carousel); if (! flightInfos.Contains(flightInfo)) { flightInfos.Add(flightInfo); updated = true; } } if (updated) { flightInfos.Sort(); Console.WriteLine("Arrivals information from {0}", this.name); foreach (var flightInfo in flightInfos) Console.WriteLine(flightInfo); 세번째달의레포트
  • 57. OBSERVER PATTERN (옵저버 패턴) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Example { public static void Main() { BaggageHandler provider = new BaggageHandler(); ArrivalsMonitor observer1 = new ArrivalsMonitor("BaggageClaimMonitor1"); ArrivalsMonitor observer2 = new ArrivalsMonitor("SecurityExit"); provider.BaggageStatus(712, "Detroit", 3); observer1.Subscribe(provider); provider.BaggageStatus(712, "Kalamazoo", 3); provider.BaggageStatus(400, "New York-Kennedy", 1); provider.BaggageStatus(712, "Detroit", 3); observer2.Subscribe(provider); provider.BaggageStatus(511, "San Francisco", 2); provider.BaggageStatus(712); observer2.Unsubscribe(); provider.BaggageStatus(400); provider.LastBaggageClaimed(); } } cs 세번째달의레포트
  • 58. OBSERVER PATTERN (옵저버 패턴) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class Example { public static void Main() { BaggageHandler provider = new BaggageHandler(); ArrivalsMonitor observer1 = new ArrivalsMonitor("BaggageClaimMonitor1"); ArrivalsMonitor observer2 = new ArrivalsMonitor("SecurityExit"); provider.BaggageStatus(712, "Detroit", 3); observer1.Subscribe(provider); provider.BaggageStatus(712, "Kalamazoo", 3); provider.BaggageStatus(400, "New York-Kennedy", 1); provider.BaggageStatus(712, "Detroit", 3); observer2.Subscribe(provider); provider.BaggageStatus(511, "San Francisco", 2); provider.BaggageStatus(712); observer2.Unsubscribe(); provider.BaggageStatus(400); provider.LastBaggageClaimed(); } } c 세번째달의레포트
  • 59. OBSERVER PATTERN (옵저버 패턴) 옵저버 패턴 사용시 주의점 예외처리 공급자 - OnError 메서드 호출 • 공급자는 관찰자가 특정 방식으로 예외를 처리한다고 예상하거나 처리하도록 요구해서는 안 됩니다. • 공급자는 업데이트 제공 기능을 손상시키는 예외를 처리할 때 OnError 메서드를 호출해 야 합니다.이러한 예외에 대한 정보를 관찰자에게 전달할 수 있습니다.다른 경우에는 관 찰자에게 예외에 대해 알릴 필요가 없습니다. • 공급자는 특정 요구 사항이 있는 경우 자체 예외를 처리해야 합니다. 관찰자 - OnError 메서드를 구현 • 관찰자는 OnNext 또는 OnError 등의 인터페이스 구현에서 예외를 throw해서는 안 됩 니다.관찰자가 예외를 throw하는 경우 해당 예외는 처리되지 않습니다. • 호출 스택을 유지하려면 OnError 메서드로 전달된 Exception 개체를 throw하려는 관 찰자는 예외를 throw하기 전에 래핑해야 합니다.이렇게 하려면 표준 예외 개체를 사용해 야 합니다. 세번째달의레포트
  • 60. OBSERVER PATTERN (옵저버 패턴) 옵저버 패턴 사용시 주의점 스레딩 일반적으로 공급자는 컬렉션 개체로 표시되는 구독자 목록에 특정 관찰자를 추가하 여 IObservable<T>.Subscribe 메서드를 구현하며, 구독자 목록에서 특정 관찰자를 제거하 여 IDisposable.Dispose 메서드를 구현합니다.관찰자는 언제든지 이러한 메서드를 호출할 수 있습니다. 또한 공급자/관찰자 계약에서는 IObserver<T>.OnCompleted 콜백 메서드 후 구 독 취소 담당자를 지정하지 않으므로 공급자와 관찰자가 모두 목록에서 같은 멤버를 제거하려고 할 수 있습니다.이러한 가능성 때문에 Subscribe 및 Dispose 메서드는 모두 스레드로부터 안 전해야 합니다.일반적으로는 이를 위해 동시 컬렉션 또는 잠금을 사용합니다.스레드로부터 안전 하지 않은 구현은 스레드로부터 안전하지 않음을 명시적으로 문서화해야 합니다. 추가로 보장할 내용은 공급자/관찰자 계약을 기반으로 하는 계층에 지정해야 합니다.구현자는 관찰자 계약에 대한 사용자의 혼동을 방지하기 위해 추가 요구를 사항을 적용하는 경우 이를 명 확하게 표시해야 합니다. 그 외 관찰자는 OnNext 또는 OnError 등의 인터페이스 구현에서 예외를 throw해서는 안 됩니다.관 찰자가 예외를 throw하는 경우 해당 예외는 처리되지 않습니다. 호출 스택을 유지하려면 OnError 메서드로 전달된 Exception 개체를 throw하려는 관찰자는 예외를 throw하기 전에 래핑해야 합니다.이렇게 하려면 표준 예외 개체를 사용해야 합니다. 세번째달의레포트
  • 61. DECORATOR PATTERN (데코레이터 패턴) 세번째달의레포트
  • 62. DECORATOR PATTERN (데코레이터 패턴) 세번째달의레포트
  • 63. DECORATOR PATTERN (데코레이터 패턴) 데코레이터는 서브 클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법. 장점 1. 데코레이터의 수퍼클래스는 자신이 장식하고 있는 객체의 수퍼클래스와 같다. 2. 한 객체를 여러 개의 데코레이터로 감쌀 수 있다. 3. 데코레이터는 자신이 감싸고 있는 객체와 같은 수퍼클래스를 가지고 있기 때문에 원래 객 체(싸여져 있는 객체)가 들어갈 자리에 데코레이터 객체를 넣어도 상관 없습니다. 4. 데코레이터는 자신이 장식하고 있는 객체에게 어떤 행동을 위임하는 것 외에 원하는 추가 적인 작업을 수행할 수 있습니다. 5. 객체는 언제든지 감쌀 수 있기 때문에 실행중에 필요한 데코레이터를 마음대로 적용할 수 있습니다. 단점 1. 데코레이터 패턴을 이용해 디자인을 하다 보면 잡다한 클래스가 많아 질 수 있다. 2. 겹겹이 애워싼 객체의 정체를 알기가 힘들다. 3. 상속을 통해 확장할 수도 있지만, 디자인 유연성 면에서는 별로 좋지 않다. 세번째달의레포트
  • 64. DECORATOR PATTERN (데코레이터 패턴) 데코레이터는 서브 클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법. 세번째달의레포트
  • 65. DECORATOR PATTERN (데코레이터 패턴) 데코레이터는 서브 클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법. 1 2 3 4 5 6 7 8 9 10 11 public abstract class Beverage { protected String description = "제목없음"; public abstract double cost(); public virtual string getDescription() { return description; } } 1 2 3 4 5 6 7 8 9 10 11 12 public class Espresso : Beverage { public Espresso() { description = "에스프레소 커피"; } public override double cost() { return 1.99; } } 1 2 3 4 5 6 7 8 9 10 11 12 public class DarkRoast : Beverage { public DarkRoast() { description = "다크로스트 커피"; } public override double cost() { return .99; } } 1 2 3 4 5 6 7 8 9 10 11 12 public class Decaf : Beverage { public Decaf() { description = "디카페인 커피"; } public override double cost() { return 1.05; } } 1 2 3 4 5 6 7 8 9 10 11 12 public class HouseBlend: Beverage { public HouseBlend() { description = "하우스블랜드 커피"; } public override double cost() { return .89; } } c 세번째달의레포트
  • 66. DECORATOR PATTERN (데코레이터 패턴) 데코레이터는 서브 클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법. 1 2 3 4 public abstract class CondimentDecorator : Beverage { public override abstract string getDescription(); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Milk: CondimentDecorator { private Beverage beverage; public Milk(Beverage beverage) { this.beverage = beverage; } public override string getDescription() { return beverage.getDescription() + ", 스팀밀크"; } public override double cost() { return beverage.cost() + .10; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Soy : CondimentDecorator { private Beverage beverage; public Soy(Beverage beverage) { this.beverage = beverage; } public override string getDescription() { return beverage.getDescription() + ", 두유"; } public override double cost() { return beverage.cost() + .15; } } 세번째달의레포트