새로 생성한 스크립트
- Character : 애니메이션 상태 스크립트
- Item : 버프 프리펩 같은 아이템이 어떻게 소환되고 어떻게 사용되는지 예시로 만든 추상클래스
- Buff : Item을 상속받아 정의될 버프클래스
- UseItem : 아이템을 직접적으로 사용하는 클래스
- 0312 static 변경
fbx
- 3Dx Max + Maya = Fbx
- fbx : 3D 개체 데이터와 함께 애니메이션 데이터도 포함하는 파일이다.
- 장점 : FBX 파일은 카메라, 조명, 기하학, 애니메이션 제작에 사용되는 골격 등 전체 3D 장면을 위한 데이터를 저장한다.
- Blender도 Fbx를 호환해준다.
- Unity, Unreal이 Fbx를 사용한다.
- 캐릭터와 애니메이션의 기본 샘플은 ‘믹사모’라는 사이트에서 가져올 수 있다.
- pack은 사용 안하는게 좋다. ⇒ 애니메이션 만들때 하나하나 끊어서 사용해야 할 수 있다.
- 사람이나 사물은 중심이 다르니 바닥에 맞춰 사용해야한다.
캐릭터 넣기
- Assets → import new assets 클릭
- 화면에 끌어 놓는다.
- 에셋 폴더에 있는 아바타 클릭 후 → Materials → Textures → Extract Textures 클릭 ⇒ 아바타에 텍스쳐를 가져오는 기능
- Materials → Materials 클릭 ⇒ 가져온 텍스쳐를 아바타에 넣는 기능
- Rig → Animation Type → Humanoid 클릭(Legacy : 고전게임용, Generic : 동물 애니메이션 용)
- Rig → Avatar Definition → Configure를 클릭하면 아타바의 뼈대와 본 매핑과 근육을 조정하는 탭을 확인할 수 있다.
애니메이션 넣기
- Assets → import new assets 클릭
- 에셋 폴더에 애니메이션 2개를 같이 클릭 후 → Rig → Source → 애니메이션을 넣을 아바타 선택 → Animation Type → humanoid 선택
- 에셋 폴더에 우클릭 → Create → Animator 생성 → 아바타 오브젝트 클릭 후 → Animator → Controller에 방금 생성한 Animator 끌어다 놓기
- Animator 창에 에셋 폴더에 있는 애니메이션 에셋 끌어다 놓기
- Entry와 연결 되어있다면 플레이를 누를 시 해당 애니메이션이 실행된다.
- Has Exit Time : 루프가 아닌 애니메이션은 끝나면 이전 상태로 돌아가게하는 기능이다.
- Animator창 → Parameters → Name검색 창 오른쪽에 + 토글 클릭 → Trigger 선택
- Animator창 → idle 애니메이션 우클릭 → Make Transition 클릭 후 Magic Spell Casting에 클릭 → 반대 작업도 똑같이 진행 → 연결된 화살표 클릭
- Idle → Spell Casting : Has Exit Time 해제 → Conditions + 클릭
- 플레이 누르고 애니메이터 창에 Casting 토글 활성화하면 다음 애니메이션으로 넘어가고 끝나면 Idle 애니메이션으로 돌아온다.
if (Input.GetKeyDown(KeyCode.Space))
animator.SetTrigger("Casting");
FSM (유한상태기계) - 전이
- 유한 상태 기계 또는 유한 오토마톤은 컴퓨터 프로그램과 전자 논리 회로를 설계하는 데에 쓰이는 수학적 모델이다. (간단히 ‘상태 기계’라고 부르기도 한다.)
- 즉, 상태란 전이를 시작하기 위해 대기하고 있는 시스템의 행동적 노드를 의미한다.
- 진입 동작 : 상태에 진입할 때 수행되는 동작
- 퇴장 동작 : 상태로부터 퇴장할 때 수행되는 동작
- 전이 : 어떠한 조건이 만족되거나 이벤트가 발생하였을 때 수행되는 일련의 동작을 의미한다.
- Idle →← Walk → ←Run ⇒ 전이
- 이리저리 꼬일 수 있지만 substate machine이라는 게 있어서 분할해서 쓸 수 있다.
- FSM의 핵심은 단 하나의 상태만을 가진다는 점이다.
- FSM 장점 : 상태를 기준으로 어떤 동작을 수행할지 결정하기 때문에 현재 상태만 알 수 있으면 어떤 동작을 수행하려 하는지 명확히 파악할 수 있고 구현이 쉽다.
- 단점 : 상태가 많아질 수록 상태 전이 조건이 매우 복잡해진다.
프리펩 및 유니티 기본 설정 고정
- 앞으로 폴더는 01_Scene, Scripts, Prefabs, Character로 한다.
- 프리펩은 쓸 것만 따로 뺴놓아야 메모리가 안 부족해진다.
behavior tree(행동트리)
- 행동트리 : 루트 노드에서 시작해 깊이 우선 탐색(DFS)로 자식노드를 평가하고 평가 결과를 다시 부모 노드에게 반환하는 구조를 가진다.
- Action task : 실제 행동을 표현하는 단말 노드
- true 또는 false를 반환한다.
- 스택에 처음 올라갈 때 OnStart()가 불리고, true 나 false를 반환하지 않으면 계속해서 OnUpdate()가 불린다.
- true 나 false가 반환되면 스택에서 빠지면서 OnEnd()가 불린다.
- EndAction()과 같은 메서드를 명시적으로 호출해서 Action을 끝내기도 하고, 어떤 구현들에서는 true, false, running 과 같은 반환값을 기반으로 Action이 끝났는지 판단하기도 한다.
- Composite task : 복합 태스크는 여러개의 자식으로 구성된 테스크다.
- 복합 테스크의 핵심 용도는 노드의 flow를 제어하는 것이다.
- 기본 실행 순서는 위에서 아래로, 왼쪽에서 오른쪽으로 실행된다.
- Select composite : 자식 노드가 true를 반환할 때 까지 자식 노드들을 실행한다.
- Sequence composite : 자식 노드가 false를 반환할 때까지 자식 노드들을 실행한다.(순차적 실행)
- Conditional Aborts : 조건부 취소로 실행 흐름에 영향을 주는 역할로, 어떤 변수를 계속 감시하고 있다가 변수의 값이 바뀌게 되면 지금의 실행 흐름을 취소시키고 자신의 노드로부터 재평가를 하는 것이다.
- Decoration task : ‘조건’을 의미한다. Decoration은 하나의 자식만을 가질 수 있고, 조건을 만족하면 자식을 실행하고, 조건을 만족하지 못하면 false를 반환한다.
Particles
- 입자들이 모여 하나의 효과를 나타낸다.
- 이런 그래픽들은 그냥 사서 쓰는게 좋다.
- 캐릭터 오브젝트 인스펙터 창에 프리펩을 넣는다.
프리펩 애니메이션 이벤트 타이밍
- 이벤트를 넣고싶은 애니메이션 동작을 폴더에서 클릭 → Animation → Events → 이벤트를 넣고 싶은 동작을 찾아서 멈춘 후 흰색 바에 우클릭 → Add Animation Event 클릭 → Function에 이름 정의 → Object에 이벤트를 정의할 함수가 있는 스크립트 찾아서 클릭
private void Play_Casting() //함수를 넣을 이벤트 이름과 같아야한다.
{
if (prefab != null)
{
Instantiate(prefab, Vector3.zero, Quaternion.identity);
}
}
코루틴
- 코루틴 : 작업을 다수의 프레임에 분산할 수 있다.
- Unity에서 코루틴은 실행을 일시 정지하고 제어를 Unity에 반환하지만 중단한 부분에서 다음 프레임을 계속할 수 있는 메서드다.
- 메서드를 호출하면 실행을 완료한 뒤 호출한 메서드에 제어와 선택적 반환 값을 반환한다.
- 즉, 메서드 내에서 발생한 모든 행동은 단일 프레임 업데이트 내에서 발생해야 한다.
- 시간의 흐름에 따른 이벤트의 시퀀스나 절차상의 애니메이션을 포함하기 위해 메서드 콜을 사용하고자 하는 상황에서 ‘코루틴’을 사용할 수 있다.
- 코루틴은 ‘스레드’가 아니다.
- 동기작업은 여전히 메인 스레드에서 실행된다.
- 메인 스레드에 소요되는 CPU 시간을 줄이려면 다른 스크립트 코드에서와 마찬가지로 코루틴의 작업 차단을 방지하는 것이 중요하다.
- 코루틴은 HTTP 전송, 에셋 로드, 파일 I/O 완료 등을 기다리는 것과 같이 긴 비동기 작업을 처리해야 하는 경우 ‘코루틴’을 사용하는 것이 가장 좋다.
- 코루틴도 멤버함수여서 자기자신을 사용할 수 있다.
[SerializeField]
private GameObject prefab;
private Animator animator;
animator = GetComponent<Animator>(); //오브젝트에 있는 애니메이터 컴포넌트를 가져온다.
if (Input.GetKeyDown(KeyCode.Alpha1)) //KeyCode.Alpha1 : 키보드 위에 숫자키
{
animator.SetTrigger("Casting");
}
private void Play_Casting() //함수를 넣을 이벤트 이름과 같아야한다.
{
if (prefab != null)
{
GameObject obj = Instantiate(prefab, Vector3.zero, Quaternion.identity);
StartCoroutine(Destroy_GameObject(obj));
}
}
private IEnumerator Destroy_GameObject(GameObject particle) //생성된 프리펩 오브젝트 클론을 3초뒤 삭제하는 코루틴함수
{
yield return new WaitForSeconds(3); //3초 뒤 / 코루틴은 yield return으로 반환한다.
Destroy(particle);
}
프리펩 애니메이션 루프 해제
- 프리펩 더블클릭 → 애니메이션이 들어가있다면 Particle System이 들어가있다 → Open Editor 클릭 → 접혀져있으니 해당 프리펩 내용이 다 나올때까지 Particle Effect 창을 늘린다. → 모든 해당 내용에서 Looping 해제
- 파티클 작동 시간을 늘리고 싶다면 Particle Effect 창에서 Duration의 값을 모든 내용에서 늘린다.
프로세스
- IPC : 프로세스끼리 메세지를 주고받는 기술 ⇒ I/O를 통해서 주고받는데 I/O가 작동하면 ‘인터럽트’가 걸린다.
- IPC 프로세스 간 통신이란 실행 프로세스 간에 통신을 가능케하는 메커니즘들에 대한 통칭을 뜻합니다.
- 즉, 프로세스 간에 서로 통신하는 규칙에 관한 문제를 해결합니다.
- 통상, 호스트의 기종, 운영체제 등이 무엇인지 관계없이 일정 규칙으로 통신하는 것이 매우 중요합니다.
- 이것으로, 두 프로세스 간에 일정 포멧과 순서를 따르는 메세지를 주고 받으며 통신을 하게됩니다.
- 멀티테스킹 운영체제 내 또는 네트워크화 분산된 컴퓨터들 사이에 각각 실행되는 프로세스 간에 정보의 교환을 가능케 하는 다양한 기법들을 의미합니다.
- IPC는 전송 계층(Layer 4) 또는 세션계층(Layer 5)에서 이루어 집니다.
- 프로세스 : 운영체제로부터 자원(메모리 등)을 할당받아 프로그램을 실행시킨다.
- 각 프로세스는 독립된 주소 공간을 가지며, 서로의 메모리에 접근할 수 없다.
- 프로세스는 하나 이상의 스레드로 구성될 수 있다.
- 프로세스 끼리 데이터를 교환하려면 소켓이나 공유 메모리 같은 IPC를 이용해야한다.
- 여러개의 프로그램을 동시에 돌리는 방법 : 병렬
- 쓰레드 : 함수단위, 프로세스를 쪼개서 여러 동작을 한번에 처리하는 방법
스레드
- 스레드 : 프로세스를 여러 개의 조각으로 나눈 것으로, 한 OS에서 여러 프로세스가 작업하는 것처럼, 한 프로세스에서 여러 스레드가 동시에 작업을 처리할 수 있게 해준다.
- 장점 : 대화형 프로그램에서 멀티 스레드를 이용하면 응답성을 높일 수 있다.(하나의 스레드는 하나의 작업만 가능하지만 여러개의 스레드는 여러 작업을 동시에 처리할 수 있다.)
- 멀티 프로세스 방식에 비해 멀티 스레드 방식이 자원 공유가 쉽다. (스레드끼리 코드 내의 변수를 같이 사용하는 것만으로도 데이터 교환을 할 수 있다.)
- 경제성이 좋다. (이미 프로세스에 할당된 메모리와 자원을 그대로 사용하므로 메모리와 자원을 할당하는 비용을 지불하지 않아도 된다.)
- 단점 : 구한하기가 매우 까다롭다. (자식 스레드 중 하나에 문제가 생기면 ‘전체 프로세스’에 영향이 발생한다.)
- 스레드를 너무 많이 사용하면 오히려 성능이 더 저하된다. (스레드가 CPU를 사용하기 위해서는 작업 간 전환을 해야하는데, 이 작업이 비용을 많이 소모한다.)
- 너무 작업 간 전환을 수행하면 실제로 일하는 시간에 비해 작업 전환에 사용하는 시간이 커져 성능이 저하된다.
추상 클래스
- 추상 클래스는 인스턴스화할 수 없다.
- 추상 클래스의 목적은 여러 파생 클래스에서 공유할 수 있는 기본 클래스의 공통적인 정의를 제공하는 것이다.
- 추상 함수는 메서드 정의 안쓰고 세미콜론(;)을 붙여서 끝마친다.
- 반드시 abstract를 붙여서 써야한다.
- 이때, 추상함수를 하나이상 포함하고 있는 클래스는 abstract를 붙여 추상함수로 만든다.
- 추상함수는 메모리를 할당할 수 없다. (변수나 메서드를 정의할 수 없다.)
- 만들어진 추상클래스를 상속받는 클래스는 추상클래스 안의 메서드를 반드시 사용해야한다.
- 이때 추상클래스를 상속받은 클래스가 추상 재정의를 하지 않으면 그 클래스도 추상으로 만들어야하기 때문에 재정의를 강제해야한다.
- 아이템 만들때도 사용한다.
- 아이템을 어떻게 사용하는지 모르니까 메서드를 만들고 abstract를 붙여 정의하지 않는다.
- 구체화(재정의)는 상속받는 클래스가 구현한다.
public abstract class Item //모노비헤비어는 컴포넌트에 할당할 스크립만 사용한다.
sealed
- 클래스 앞에 붙으면 상속이 불가능하게 된다.
- 기본 클래스의 가상 메서드 또는 속성을 재정의하는 메서드 또는 속성에 sealed 한정자를 사용할 수도 있다.
- 이렇게 되면 사용자 클래스에서 클래스가 파생되고 특정 가상 메서드 또는 속성을 재정의하지 못하도록 할 수 있다.
- sealed 한정자는 항상 override와 함께 사용해야 한다.
- 구조체는 암시적으로 봉인되므로 상속할 수 없다.
직렬화(Serialization)
- 직렬화는 객체를 다른형식으로 변환하여 데이터를 저장하거나 전송하는 프로세스를 말한다.
- 직렬화와 짝을 이루는 것은 스트림을 개체로 변환하는 deserialization이다.
- 데이터의 저장
- 객체의 현재 상태를 저장하기 위해 사용한다. 저장된 데이터는 다시 읽어와서 사용한다.
- 데이터 전송
- 네트워크를 통해서 다른 시스템으로 전송하거나 통신을 위해서 많이 사용한다.
- 복원 및 복구
- 프로그램이 중단 됐을 때 객체의 이전 상태를 복원하거나 복구하기 위해 사용된다.
- RAM과 SSD의 사이에는 I/O(Byte stream)이 있고 이 통로 사이엔 N/W(네트워크)도 있다.
- 메모리에 접근하지 못하는 C#에서 바이트 스트림을 통과할 수 있도록 byte 배열로 만들어 주는것을 의미한다.
- 변수는 직렬화가 가능하지만, 함수는 직렬화가 안된다.
역직렬화
- 직렬화의 반대로, 직렬화된 데이터를 원래 데이터 구조로 복원하는 작업을 말한다.
- 데이터 복원
- 데이터 읽기
- 네트워크로 전송된 데이터를 프로그램이 읽을 수 있는 형태로 변환 해준다.
- 데이터 공유
- 다른 시스템과 데이터를 공유하고 객체를 전달하는데 사용된다.