Anim Blueprint2017. 12. 23. 22:26

목표 

AI Character가 F 키를 누르면 걷기 시작하고, G 키를 누르면 달리기 시작한다


AI Character 가 미리 지정된 지점을 향하여 이동할 때 F 키를 누르면 걷기 시작하고 이어서 G 키를 누르면 달리기 시작한다

Animation Blueprint 를 사용하여 State Machine 을 작성하여 상태에 따라서 적절한 애니메이션이 적용되도록 할 수 있다

ThirdPersonCharacter를 복제하여 AI Character로 사용한다

AIController를 기반으로 한 BP_AIController 블루프린트를 생성하여 AI Character를 제어하도록 등록한다

BP_AIController의 이벤트 그래프에 AI Character를 제어하는 내용을 작성한다


1. 공백 블루프린트 프로젝트를 생성한다

2. 컨텐츠 브라우저의 [신규추가] 버튼을 누르고 [피쳐 및 컨텐츠 팩 추가] 를 선택 > 3인칭 선택 > 프로젝트에 추가를 선택한다. 이렇게 하면 ThirdPersonCharacter가 컨텐츠 브라우저에 포함된다

3. ThirdPersonCharacter를 복제하여 원하는 작업용 폴더에 이동하고 이름을 AI_Character으로 변경한다

4. AI_Character 클래스를 열고 카메라와 붐을 제거한다

5. AIController를 기반으로 BP_AIController 블루프린트를 생성하고 AI_Character의 AI Controller Class에 등록한다


언리얼에서 애니메이션은 Skeleton에 설정하는 것이므로 AI_Character의 Mesh를 선택하고 [디테일] 뷰의 Skeleton 항목에서 마우스를 올리고 Skeletal Mesh가 저장된 경로를 확인한다. 아래의 그림에서는 SK_Mannequin 인 것을 알 수 있다


위에서 확인된 Skeletal Mesh의 경로를 컨텐츠 브라우저에서 찾아서 해당 파일 위에 마우스를 올려보면 Skeletal Mesh의 Skeleton 경로를 확인할 수 있다. 아래의 그림에서는 Skeleton 이 UE4_Mannequin 인 것을 알 수 있다


위에서 확인된 바는 우리가 ThirdPersonCharacter를 복제하여 AI_Character를 생성했는데, 해당 캐릭터의 Skeleton은 UE4_Mannequin이라는 사실이다. 언리얼에서 애니메이션을 적용하려면 Skeleton을 타겟으로 설정하여 애니메이션을 설정하므로 우리가 복제한 캐릭터에게 애니메이션을 설정하려면 타겟 Skeleton은 UE4_Mannequin 으로 지정해야 한다는 것이다


6. 컨텐츠 브라우저에서 마우스 우측 > 애니메이션 > Animation Blueprint 선택하고 다음과 같이 설정하고 이름을 AI_AnimBP 으로 입력한다


생성된 AI_AnimBP를 더블클릭하여 열고 애님 그래프에 아래처럼 StateMachine을 추가한다





StateMachine 노드의 이름을 AI State 으로 변경하고 더블클릭하여 다음과 같이 상태를 추가하고 상태 사이를 연결한다



위의 그림에서 보여지는 각 상태 노드에 해당 애니메이션을 드래그하여 설정한다




위의 상태 연결 구조를 약간 변경하여 아래와 같이 삼각형 구조가 되도록 한다


이제 각 상태의 전환규칙(Transition Rule)을 설정할 순서이다. 각 상태 사이에 있는 원형 이이콘을 더블클릭하여 전환규칙을 작성할 수 있다. 키보드에서 I, F, G 키가 눌릴 때마다 Idle, Walk, Run 상태로 전환되도록 할 것이므로 키보드의 눌림에 따라서 값이 변경되는 String 변수를 하나 선언하고 그 값에 따라서 애니메이션이 반응하도록 한다


다음 그림과 같이 String 변수 AnimState 를 선언한다. 이렇게 애니메이션 블루프린트에 선언된 변수는 애님 그래프이벤트 그래프에서 공히 사용할 수 있다.



위에서 선언한 변수의 값은 BP_AIController에서 선언된 변수의 값을 참조할 예정이므로 먼저 BP_AIController의 이벤트 그래프에 아래처럼 변수를 선언하고 I, F, G 키가 눌릴 때마다 AnimState변수의 값이 변경되도록 한다. 또한 [디테일]뷰의 Input 항목에서 Disabled 대신에 Player0 으로 설정해야 한다


위처럼 Pawn 클래스나 콘트롤러 클래스에 선언된 변수는 애니메이션 블루프린트에서 쉽게 접근할 수 있는 방법이 제공된다



다시 애니메이션 블루프린트로 돌아와서 블루프린트의 변수 AnimState 에 값을 설정하는 로직을 이벤트 그래프에 다음과 같이 작성한다. 


위의 절차를 마치면 BP_AIController에서 변경된 AnimState 변수의 값은 애니메이션 블루프린트의 AnimState 변수에 까지 전달된다. 이제 AnimState 변수의 값을 애니메이션 전환규칙에서 참조하여 전환을 결정하면 된다


Idle, Walk 상태의 전환규칙 아이콘을 더블클릭하고 다음과 같이 전환규칙을 작성한다


다른 모든 전환규칙도 위와같은 방법으로 설정하면 된다 달라지는 것은 Idle, Walk, Run과 같은 문자열이다


위와같은 절차를 통해 완성된 애니메이션 블루프린트는 Skeleton이 아닌 Skeletal Mesh에 설정해야 한다. 애니메이션 블루프린트를 생성할 때의 타겟은 Skeleton이었지만, 완성된 애니메이션 블루프린트를 적용할 대상은 Skeletal Mesh인 것이다


AI_Character 를 열고 Mesh 컴포넌트를 선택한 상태에서 우츠 [디테일] 뷰의 Animation 패널에서 다음 그림처럼 설정한다. 위에서 생성한 AI_AnimBP를 Skeletal Mesh에 설정하는 것이다




뷰포트에 Target Point 액터를 배치한다

뷰포트의 플로어에 Nav Mesh Bound Volumn을 설정한다

AI_Character 를 컨텐츠 브라우저에서 드래그하여 뷰포트의 적당한 위치에 놓고 바라보는 방향을 조정한다




BP_AIController의 이벤트 그래프를 최종적으로 아래처럼 작성한다. 걷기와 달리기 애니메이션이 실행될 때는 캐릭터의 이동 속도도 달라져야 하므로 CharacterMovement 컴포넌트를 활용하여 캐릭터의 이동속도를 달리 설정한 내용이다




게임을 실행하고 I, F, G 키를 누를 때마다 AI_Character가 TargetPoint 를 향하여 이동하면서 다른 애니메이션이 실행되고 이동 속도도 달라지는 것을 확인할 수 있다


F키를 누르면 걷는 애니메이션과 느린 속도(200)가 확인된다



G키를 누르면 달리는 애니메이션과 빠른 속도(400)가 확인된다


Posted by cwisky
AI Controller2017. 12. 23. 01:46

목표 : 계단위에 서 있던 AI Character가 키보드에서 F 키를 누르면 계단을 자연스럽게 내려가서 특정 위치에서 멈춘다


1. 공백 프로젝트를 생성한다

2. 컨텐츠 브라우저에서 [신규 추가] > [피쳐 또는 컨텐츠 팩추가] > 3인칭 선택 > 프로젝트에 추가

3. 컨텐츠 브라우저에 새로 추가된 폴더에서 ThirdPersonCharacter 를 찾아 마우스 우측 > 복제 > 이름을 BP_AICharacter 으로한다

4. 새로 복제된 BP_AICharacter 를 드래그하여 원하는 폴더 안에 이동한다

5. 계단을 자연스럽게 이동할 수 있는 기능은 AI에 포함되어 있으므로 AIController 를 상속한 클래스 블루프린트를 생성하여 제어하여야 한다. AIController 를 기반으로 BP_AICharacter 를 생성한다

6. BP_AICharacter 에서 AI Controller Class 항목에 BP_AIController 를 지정한다


7. BP_AIController를 열고 툴바에서 [클래스 디폴트]를 선택하고 [디테일] 뷰 / Input / Auto Receive Input 항목에 Player0를 선택한다

8. 언리얼 에디터 뷰포트에  TargetPoint를 드래그하여 설정한다. AICharacter가 이동할 목표점으로 삼으려고 한다

9. BP_AIController의 이벤트 그래프에 다음의 내용을 입력한다


위의 그래프에서 Get All Actors of Class 노드에는 Target Point를 설정한다


10. 뷰포트에 굽은 계단을 드래그하여 놓고 계단 꼭대기에 BP_AICharacter를 드래그하여 놓는다

11. 뷰포트 플로어 전체와 계단 상부를 덮을 수 있도록 Nav Mesh Bounds Volumn를 드래그하여 설정한다. 이때 P키를 누르면 AI가 이동할 수 있는 영역은 초록색으로 표시되므로 AI가 작동하는 영역을 쉽게 알 수 있다



Nav Mesh Bounds Volumn은 다음과 같이 선택하여 드래그할 수 있다


Posted by cwisky
Timeline Anim2017. 12. 22. 12:22

목표 : F키가 눌리면 큐브가 올라가서 일정한 높이에 스무스하게 멈추고, G키를 누르면 큐브가 내려와서 원래의 위치로 스무스하게 복귀하도록 Time Line 노드를 활용한다


블루프린트에서 타임라인 노드를 추가하고 키보드를 눌러서 큐브를 올라가고 내려가게 하는 애니메애션을 구현하는 예


블루프린트 액터를 생성하고 큐브를 컴포넌트로 추가하고 이벤트 그래프에서 아래의 내용을 작성한다




위에서 사용된 타임라인 노드를 더블클릭하여 아래처럼 그래프를 작성한다. 사용된 2개의 타임라인 그래프는 동일한게 작성하면 된다



Posted by cwisky
Selection Sort2017. 12. 22. 12:08

목표 : 임의의 Float 유형의 데이터 10개를 배열에 저장하고 선택정렬 알고리듬을 사용하여 정렬한 후에 배열의 원소를 화면에 출력한다


언리얼 에디터의 툴바에서 [블루프린트 > 레벨블루프린트 열기] 를 선택하고 [이벤트 그래프] 탭을 눌러 아래처럼 작성한다


블루프린트에서 배열원소의 선택정렬 알고리듬 구현 예



게임을 실행하면 다음과 같이 내림차순으로 정렬된 배열의 원소를 확인할 수 있다


Posted by cwisky
Database2017. 12. 21. 21:12


Student 테이블, Point 테이블을 작성하고 다음과 같은 기초정보를 테이블에 저장할 때 SQL 문장을 사용한다



테이블 스키마

Student (num number(PK), id varchar2, pwd varchar2, name varchar2, phone varchar2, email varchar2)

Point (num number(FK), subject1 number, subject2 number, subject3 number)



작성할 SQL문장

  1. 위의 테이블을 생성하는 SQL문장과 그 실행결과를 제출하시오
  2. 위의 테이블에 각각 6행의 데이터를 입력하는 SQL문장과 그 실행결과를 제출하시오
  3. subject1의 최고점수를 기록한 플레이어의 번호와 이름, 점수를 가져오는 SQL문장을 작성한다
  4. subject2의 1위~5위까지의 이름과 점수를 가져오는 SQL문장을 작성한다
  5. 5번 학생의 전화번호를 123-4567-8901로 변경하는 SQL 문장을 작성한다
  6. subject3의 점수가 가장 저조한 학생의 점수기록을 삭제하는 SQL문장을 작성한다



테이블 생성

CREATE TABLE student

(

  num number PRIMARY KEY,

  id varchar2(20),

  pwd varchar2(20),

  name varchar2(20),

  phone varchar2(20),

  email varchar2(20)

);


CREATE TABLE point

(

  num number REFERENCES student(num),

  subject1 number,

  subject2 number,

  subject3 number

);



2개의 테이블에 기본 데이터 입력

INSERT INTO student VALUES (11, 'kang', 'kang', 'kanggildong', '010-1111-2222', 'kang@naver.com');

INSERT INTO student VALUES (12, 'kim', 'kim', 'kimgildong', '010-1111-2222', 'kim@naver.com');

INSERT INTO student VALUES (13, 'park', 'park', 'parkgildong', '010-1111-2222', 'parkg@naver.com');

INSERT INTO student VALUES (14, 'lee', 'lee', 'leegildong', '010-1111-2222', 'lee@naver.com');

INSERT INTO student VALUES (15, 'choi', 'choi', 'choigildong', '010-1111-2222', 'choi@naver.com');

INSERT INTO student VALUES (16, 'hong', 'hong', 'honggildong', '010-1111-2222', 'hongg@naver.com');


INSERT INTO point VALUES (11, 10,15,20);

INSERT INTO point VALUES (12, 25,30,35);

INSERT INTO point  VALUES (13, 50,45,40);

INSERT INTO point VALUES (14, 60,55,70);

INSERT INTO point VALUES (15, 85,75,80);

INSERT INTO point VALUES (16, 50,65,90);



subject1의 최고점수를 기록한 플레이어의 번호와 이름, 점수를 가져오는 SQL문장을 작성한다

SELECT p.num, name, subject1 

FROM student p INNER JOIN point s 

ON p.num=s.num

WHERE p.num =

(

    SELECT num FROM point WHERE subject1=

    (

        SELECT MAX(subject1) FROM point

    )

);



subject2의 1위~5위까지의 이름과 점수를 가져오는 SQL문장을 작성한다

SELECT name, subject2 FROM

(

    SELECT name, subject2, ROWNUM rn FROM

    (

        SELECT * FROM student p INNER JOIN point s

        ON p.num = s.num ORDER BY s.subject2

    )t1

)

WHERE rn BETWEEN 1 AND 5;



15번 이용자의 전화번호를 010-1111-2222로 변경하는 SQL 문장을 작성한다

UPDATE student SET phone='010-1111-2222' WHERE num=15;



subject3의 점수가 가장 저조한 이용자의 점수기록을 삭제하는 SQL문장을 작성한다

DELETE FROM point WHERE subject3=

(

    SELECT MIN(subject3) FROM point

);


Posted by cwisky
Android Development2017. 12. 7. 13:14

언리얼에서 안드로이드 개발환경 구성


https://docs.unrealengine.com/latest/KOR/Platforms/Android/GettingStarted/index.html


언리얼 엔진 4 (UE4) 는 CodeWorks for Android 1R6u1 라는 특수 버전 안드로이드 소프트웨어 개발 키트(SDK)를 사용한다. JDK, Android SDK, Android NDK, Gradle 등을 모두 포함하고 있으므로 안드로이드 개발환경을 쉽게 구성할 수 있다


언리얼 엔진과 안드로이드 SDK 호환성을 유지하기 위해 안드로이드용 CodeWorks 를 UE4.17.2 이상의 버전에 번들로 포함되어 있다. UE4.18 에서 Gradle 빌드 시스템이 기본으로 켜진다

UE4.21에서의 설치파일 기본적인 위치는 다음과 같다


C:\Program Files\Epic Games\UE_4.21\Engine\Extras\AndroidWorks\Win64\CodeWorksforAndroid-1R7u1-windows.exe


설치파일을 더블클릭하여 설치를 시작하고 이어지는 설정화면에서는 디폴트로 두고 설치를 진행한다

설치가 진행되는 중에 디바이스 드라이버를 설치는 과정에서 동의를 묻을 때 허용을 선택하고 설치를 계속한다


CodeWorks for Android 1R6u1 에디터와 런처 둘 다 닫힌 상태로 설치해야 설치에 문제가 없다.


CodeWorks for Android 1R6u1 인스톨러의 정상 완료를 위해서는 Visual Studio 가 설치되어 있어야 합니다. 지원되는 버전은 2013, 2015, 2017 입니다 (2017.12.07 현재)

Visual Studio 설치옵션에서 [C++을 이용한 데스크톱 개발] 항목을 반드시 선택한다


상세한 절차는 위에서 제시한 언리얼 사이트 링크를 눌러서 참조한다


위의 사이트에서는 CodeWorks for Android 설치언리얼에서 모바일 프로젝트 생성, 안드로이드 기기에서 게임 테스트하기(안드로이드 디버깅), 안드로이드 기기에 설치할 APK  패키징하기 등의 내용이 상세히 소개되어 있다


위의 사이트에서 안내하는대로 따라 했지만 잘 안된다면 아래의 내용을 참고한다


목표:

UE4에서 Android 관련 설정 및 개발하여 Android 기기에서 테스트를 수행하고 최종적으로 배포판을 생성하는 전반적인 절차를 수행할 수 있다


참고사이트:

http://api.unrealengine.com/KOR/Platforms/GearVR/QuickStart/index.html


UE4의 Android 개발환경

 - http://api.unrealengine.com/KOR/Platforms/Android/GettingStarted/index.html


UE4를 이용한 안드로이드 모바일 프로젝트 전반적 절차

  1.  UE4에서 필수 안드로이드 셋업
  2.  UE4에서 Android 프로젝트 생성 및 설정
  3.  UE4에서 개발 및 완료
  4.  UE4에서 Android 모바일 기기에 설치 및 실행 테스트
  5.  UE4에서 최종 배포판(릴리즈)용 패키징


1. UE4에서 필수 안드로이드 셋업

  • Visual Studio 2017 Community 설치(C++ 데스크톱 개발, C++ 게임 개발, C++ 모바일 게임 개발 선택)
  • VS 설치옵션에 [C++을 이용한 데스크톱 개발] 항목은 필수
  • UE4.18부터 CodeWorksForAndroid 설치파일을 내장하고 있으므로 UE4설치 경로에서 찾아서 실행한다
  • CodeWorksForAndroid 를 실해하면, Android SDK, Androd NDK, JDK, Gradle 등이 모두 설치된다
  • Java_Home 환경변수에 JDK의 bin 디렉토리를 포함한 상위 디렉토리가 등록되어 있는지 확인한다
  • Path 환경변수에 adb.exe 의 경로가 등록되어 있는지 확인한다
  • 만약 VS2017가 설치되어 있고 CodeWorks를 설치하는 중에 Visual Studio를 인식하지 못하는 오류가 발생하면 VS2015를 설치한 후에 다시 CodeWorks를 설치하면 된다


2. 안드로이드 기기에서 설정

  • 개발환경이 설치된 PC에 USB로 Android 디바이스 연결
  • 드라이버가 자동으로 설치되지 않으면 수동설치 요구됨
  • Android 디바이스에서 Settings 메뉴 실행
  • 개발자 옵션 선택(이 항목이 보이지 않으면 먼저 이 옵션을 활성화해야 함)
  • 활성화안내: http://api.unrealengine.com/KOR/Platforms/Android/GettingStarted/2/index.html
  • 개발자 모드가 활성화되지 않은 경우에는 다음과 같이 설정한다
  • 설정 > 디바이스 정보 > 소프트웨어 정보 > 빌드번호 7번 탭 > 활성화되면 다시 개발자 옵션 선택
  • USB 디버깅 선택 > 허용 창에서 [확인] > 우측에 파란색으로 표시되면 설정성공
  • PC에서 USB 분리 후 다시 연결
  • CMD에서 윈도우와 안드로이드가 정상적으로 연결된 상태인지 확인
  • CMD 실행 : Window+R > cmd입력 엔터 > adb devices 입력 엔터
  • 안드로이드 폰에서 "USB 디버깅 허용" 을 묻는 메시지 뜨면 "이 컴퓨터에서 항상 허용" 을 선택
  • 오류가 없이 연결되고 디바이스의 ID가 표시되면 성공
  • 인식 안되면 [USB 구성] 항목에서 MTP, PTP 등의 몇가지 프로토콜을 변경해가면서 확인한다


3. UE4에서 모바일용 프로젝트 생성 및 프로젝트 세팅

  • New Project > Blueprint/C++> Third Person 선택
  • 모바일/태블릭 > 스케일가능 3D 또는 2D > 시작용 컨텐츠 없음
  • 프로젝트 이름 : UE4_AndroidProj 등을 입력 > 프로젝트 생성 버튼
  • 편집 > 프로젝트 세팅 > 플랫폼 > 안드로이드
  • APK Packaging : [지금환경설정] 버튼 클릭
  • [SDK 라이선스 수락] > [동의]
  • Map & Mode > Default Map 항목에 현재 레벨이름 입력
  • Platforms > Android > Minimum SDK Version : 21
  • Platforms > Android > Target SDK Version : 21
  • Platforms > Android > Android Package Name : 임의로 설정
  • Platforms > Android > Build 항목 검사
  • Platforms > Android > Google Play Services : [지금 환경설정] 버튼 누름
  • Platforms > Android SDK > SDK Config : 설치된 SDK 경로(Java, Android SDK, NDK, ANT 등) 설정


4. 레벨 디플로이

  • USB로 안드로이드 디바이스와 연결한다
  • 윈도우 CMD에서 "adb devices" 명령을 이용하여 연결여부를 확인한다
  • 안드로이드에 디플로이하려는 레벨을 에디터에 연다
  • [실행] 버튼 우측의 작은 삼각형을 누르고 현재 연결된 디바이스 항목을 선택한다
  • 몇분 후에 UE4 우측 하단에 현재 실행상태가 나타난다
  • 안드로이드 디바이스에 디플로이가 완료되면 알림 메시지가 표시된다(10분 정도 기다림)
  • 안드로이드 디바이스에 디플로이가 완료되면 디바이스에서 프로젝트가 실행된다
  • 안드로이드 화면위에서 4손가락을 대면 지원하는 텍스쳐 포맷이 표시되므로 패키징할 때 참고한다
  • 안드로이드에서 게임을 테스트한다
  • 4개의 손가락을 화면에 대면 명령 입력창에 quit 입력하면 게임을 종료할 수 있다
  • JDK가 설치되어 있어야 하고 환경변수 JAVA_HOME가 설정되어 있지 않으면 중간에 오류가 발생함
  • rungradle.bat 오류해결: http://hannom.tistory.com/114
  • Android Studio를 이용하여 기본 프로젝트를 생성하는 과정에서 Gradle 관련 파일이 설치되고 오류 원인이 해결됨


5. 게임 패키징(배포용 패키징)

  • 편집 > 패키지 프로젝트 > 빌드 환경설정 > Shipping
  • 편집 > 패키지 프로젝트 > 안드로이드 > Android(확인된 텍스쳐 포맷) 선택
  • 안드로이드 디플로이하면서 확인괸 텍스쳐 포맷을 찾아서 위에서 선택하면 된다
  • 패키징된 게임을 저장할 경로 선택
  • 패키징 상황은 화면 우측하단에 표시되고 성공시 메시지가 표시된다
  • USB로 안드로이드 디바이스를 연결
  • 패키징된 폴더에서 Install[프로젝트이름]Development.bat 파일을 실행한다
  • BAT 파일이 작업을 마치면 APK 파일이 생성되며 연결된 안드로이드 디바이스에 설치됨
  • USB로 디바이스가 연결되어 있지 않으면 APK 파일만 생성될 뿐이다


mixamo 에서 다운로드한 캐릭터가 안드로이드에서 보이지 않는다면

Project Settings > Android  선택

Build 항목에서

uncheck Support OpenGL ES2 and check Support OpenGL ES3.1.


Posted by cwisky
Unreal C++/Log2017. 11. 25. 11:46

언리얼 엔진에서 디버그 메시지를 출력(Log)하는 다양한 방법


https://wiki.unrealengine.com/Logs,_Printing_Messages_To_Yourself_During_Runtime


로그 출력창 열기

창 > 개발자 툴 > 출력로그


UE_LOG(LogTemp, Warning, TEXT("Your message"));


로그레벨 지정자

- Fatal : 로그파일과 콘솔에 항상 출력되며 프로그램이 종료한다

- Error : 적색으로 콘솔과 파일에 출력된다

 - Warning : 황색으로 콘솔과 파일에 출력된다

- Display : 콘솔과 파일에 출력된다

 - Log : 파일에 출력된다. 에디터에서 실행할 때는 콘솔에도 출력된다

- Verbose : 로그파일에만 출력된다

- VeryVerbose : 로그파일에만 출력되며 매우 상세한 메시지가 출력된다




사용예 (한글이 깨지는 경우에는 이 페이지 하단 내용 참조)

UE_LOG(LogTemp, Warning, TEXT("Hello %s"), TEXT("World"));

UE_LOG(LogTemp, Warning, TEXT("Hello %s, %d, %f"),TEXT("World"), 100, 3.14);

UE_LOG(LogTemp, Warning, TEXT("플레이어 이름: %s"), TEXT("홍길동"));


FString fs(TEXT("홍길동"));

UE_LOG(LogTemp, Warning, TEXT("플레이어:%s, 점수:%d"), *fs, 89);



콘솔이 아닌 스크린에 로그 출력하기

#include <EngineGlobals.h>

 #include <Runtime/Engine/Classes/Engine/Engine.h>

 // ...

 GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("This is an on screen message!"));

 GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Some variable values: x: %f, y: %f"), x, y));



첫번째 아규먼트: 키, -1을 키로 가진 메시지는 서로 덮어쓰지 않고 다른 행에 출력된다. 양수를 키로 사용하면 뒤에 오는 로그가 앞의 로그를 덮어쓰게 된다
두번째 아규먼트는 출력할 기간(초)이다

위의 방법을 조금 더 편리하게 사용하려면 다음과 같이 매크로를 선언하여 사용하면 된다

#include <EngineGlobals.h>
#include <Runtime/Engine/Classes/Engine/Engine.h>

#define print(text) if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::White,text)

//

print(FString::Printf(TEXT("변수의 값 확인: x: %f, y: %f"), 2.71818, 3.14));



스크린에 한글을 출력하는 예

#include <EngineGlobals.h>

#include <Runtime/Engine/Classes/Engine/Engine.h>

............

GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("한글: x: %f, y: %f"), 100, 100));


출력로그에 한글 출력하기

UE_LOG(LogTemp, Warning, TEXT("플레이어 이름: %s"), TEXT("홍길동"));


C++에서 블루프린트로 한글을 리턴하여 스크린에 출력하려는 경우

FText t = FText::FromString(TEXT("Hello 한글"));

return t; // 리턴된 한글 텍스트는 블루프린트를 사용하여 스크린에 출력했을 때 깨지지 않았다



스크린이나 출력로그에서 한글이 깨지는 경우

만약 Visual Studio 2017 을 이용하여 C++ 코드를 작성하고 언리얼 엔진에서 컴파일한 후에 위의 코드를 실행했을 때 화면이나 출력로그에 표시된 한글이 깨져 있다면 Visual Studio에서 파일을 [다른이름으로저장]할 때 저장버튼 우측에 있는 작은 삼각형을 누르고 [인코딩하여 저장]을 선택하면 다양한 인코딩을 선택할 수 있다.

Visual Studio2017에서는 디폴트로 [한국어-코드페이지 949]로 설정되어 있는데 [유니코드(서명이 있는 UTF-8) - 코드페이지 65001] 으로 변경한 결과 한글이 깨지는 문제가 해결되었다

https://msdn.microsoft.com/ko-kr/library/dxfdkfke.aspx




Posted by cwisky
Unreal C++/Custom Object2017. 11. 23. 22:00

C++에서 작성된 Object 파생 클래스를 블루프린트에서 사용하는 방법


C++에서 Actor 파생 클래스를 생성하면 블루프린트에서도 아무런 설정 없이도 Spawn Actor From Class 노드를 사용하여 인스턴스를 사용할 수가 있다


그러나 C++에서 생성한 Object 파생 클래스는 Spawn Actor from Class노드를 사용할 수 없으므로 약간 설정을 달리해야 블루프린트에서 사용할 수가 있다


C++에서 Object를 파생한 클래스를 선언할 때 클래스 선언문 위에 언리얼 매크로인 UCLASS(Blueprintable, BlueprintType)를 선언해야 한다. 그리고 블루프린트에서 호출하는 속성이나 함수에는 UPROPERTY(), UFUNCTION() 매크로를 추가해야 한다


UCLASS(Blueprintable) : C++ 클래스를 기반으로 블루프린트 클래스로 파생할 수 있다

UCLASS(BlueprintType) : C++ 클래스의 변수를 블루프린트에서 선언할 수 있다


UPROPERTY(EditAnywhere) : 언리얼 에디터에 속성이 노출되어 값을 설정할 수 있다(블루프린트의 '인스턴스 편집' 설정과 같은 개념)

UPROPERTY(BlueprintReadWrite) : C++ 함수를 블루프린트에서 Set, Get 노드를 사용하여 값을 읽거나 변경할 수 있다


함수 파라미터에 사용되는 UPARAM(ref) 도 있는데, UFUNCTION(BlueprintCallable)으로 지정한 함수의 파라미터 중에서 참조형으로 선언된 파라미터는 블루프린트에서 출력값(리턴핀)으로 나타나도록 되어 있다. 그러므로 함수 파라미터를 참조형으로 선언하려면 파라미터 자료형 왼쪽에 UPARAM(ref)를 추가로 선언해주어야 한다


위와 같이 코드상에서 설정하면 블루프린트에서 Construct Object from Class 노드를 사용하여 블루프린트에서 인스턴스를 생성하고 속성과 함수를 사용할 수가 있다. 또한 C++ 클래스를 기반으로 블루프린트 클래스를 생성하여 사용할 수도 있는데, 언리얼에서 해당 C++ 클래스 위에서 마우스 우측을 누르고 [MyObject 기반 블루프린트 클래스 생성] 을 선택하면 블루프린트 클래스가 별도로 생성되므로  Construct Object from Class 노드를 사용하여 인스턴스를 생성하고 사용할 수가 있다


언리얼 기반에서 어떤 클래스를 기반으로 하위 클래스를 파생할 것인가?

Plain Old C++ Object : 객체의 생성부터 소멸까지 개발자가 모두 관리하려는 경우

UObject : Garbage Collection, Network Marshalling, Serialization이 요구될 때

 - ConstructObject 를 이용한 객체 생성: 객체의 초기화의 모든 절차를 자동화함

 - NewObject 를 이용한 객체 생성: 객체의 초기화를 개발자가 직접 하는 경우

 - https://docs.unrealengine.com/en-us/Programming/UnrealArchitecture/Objects

AActor : 레벨 위에 보여져야 하는 경우, 월드 아웃라이너를 통해 관리하려는 경우

 - CPP 클래스를 작성하여 Actor 를 정의했더라도 액터에 다른 컴포넌트를 추가하려면 작성된 CPP 클래스를 기반으로 블루프린트 클래스를 생성하여 보다 편리하고 빠르게 작업을 할 수가 있다

 - http://api.unrealengine.com/INT/API/Runtime/Engine/GameFramework/AActor/index.html

APawn : AI Controller나 플레이어에 의해 조종되어야 할 액터

 - https://docs.unrealengine.com/en-us/Gameplay/Framework/Pawn

ACharacter : 두발로 걸어야 하는 액터

 - https://docs.unrealengine.com/en-us/Gameplay/Framework/Pawn/Character


언리얼엔진 기반의 C++클래스 작성시 위의 클래스를 상속해야 하는 경우가 대부분이며 다른 부모 클래스를 기반으로 하위 클래스를 파생하는 것도 물론 가능하다



C++ 프로젝트를 생성한다


Content Browser 에서 마우스 우측 > 새 C++ 클래스 > 부모 클래스 선택 창에서 Object를 선택하고 [다음] 버튼을 누르고 경로선택 창에서 [클래스 생성] 버튼을 누르면 클래스가 생성되고 컴파일이 진행되고 이어서 Visual Studio 가 실행되면서 헤더와 소스파일을 편집할 수가 있다


헤더파일 (적색으로 표시된 부분은 추가된 내용)

// Fill out your copyright notice in the Description page of Project Settings.


#pragma once


#include "CoreMinimal.h"

#include "UObject/NoExportTypes.h"

#include "MyObject.generated.h"


/**

 *

 */

UCLASS(Blueprintable, BlueprintType)

class BP_CPP_API UMyObject : public UObject

{

GENERATED_BODY() // 내부에서 private 설정함

public:


UMyObject() {};


UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="MyObject")

FString message;


UFUNCTION(BlueprintCallable, Category="MyObject")

void SetMessage(FString msg);

};



소스파일 (적색으로 표시된 부분은 추가된 내용)

// Fill out your copyright notice in the Description page of Project Settings.


#include "MyObject.h"


void UMyObject::SetMessage(FString msg)

{

this->message = msg;

}


Visual Studio에서 위와 같이 편집한 후에 저장하고 다시 언리얼 에디터의 툴바에서 [컴파일] 버튼을 눌러서 컴파일을 완료한다


블루프린트에서 다음과 같이 MyObject 클래스의 인스턴스를 생성하고 사용할 수가 있다



C++ Object 파생클래스를 기반으로 블루프린트 클래스를 생성하여 블루프린트 클래스를 사용하는 절차


위와 같은 방법으로 C++에서 Object 파생 클래스를 작성했다면 언리얼 Content Browser의 C++ 클래스 위에서 마우스 우측 > [MyObject를 기반으로 블루프린트 클래스 생성]을 선택하면 블루프린트 클래스를 생성할 수가 있다. 



C++ 클래스 UObject 를 기반으로 생성한 블루프린트 클래스는 블루프린트에서 위와 동일하게 Construct Object from Class 노드를 사용하여 인스턴스를 생성하고 사용할 수가 있다


Posted by cwisky
Unreal C++/Custom Actor2017. 11. 23. 21:04

C++으로 작성한 커스텀 액터 클래스를 블루프린트에서 사용하기


Actor 클래스를 상속하여 C++에서 커스텀 액터 클래스를 생성하면 블루프린트에서는 SpawnActorFromClass 노드를 사용하여 일반 블루프린트로 만든 액터와 다를 바 없이 생성하여 사용할 수가 있다


언리얼 엔진을 실행하고 C++ 프로젝트를 생성한다


Content Browser 에서 마우스 우측 > 새 C++ 클래스 > 부모 클래스 선택 창에서 Actor 를 선택하고 [다음] 버튼을 누른다


파일 저장 경로를 선택하는 창에서 [클래스 생성] 버튼을 누르면 클래스가 생성되어 언리얼에 컴파일 되고 이어서 Visual Studio 가 실행되면서 생성된 클래스 헤더파일과 소스파일이 편집가능한 상태가 된다


필요한 속성이나 함수를 추가하고 정의한다


헤더파일과 소스파일을 저장하고 다시 언리얼 에디터의 툴바에서 [컴파일] 버튼을 눌러 컴파일한다


블루프린트에서 Spawn Actor from Class 노드를 추가하고 Class 핀에 커스텀 액터클래스의 이름을 지정하면 된다. 블루프린트에서 작성한 블루프린트 Actor 클래스를 사용하는 방법과 다를 바가 없다


생성된 C++액터클래스의 헤더파일 (적색으로 표시한 내용은 추가된 부분임)

// Fill out your copyright notice in the Description page of Project Settings.


#pragma once


#include "CoreMinimal.h"

#include "GameFramework/Actor.h"

#include "MyActor.generated.h"


UCLASS()

class BP_CPP_API AMyActor : public AActor

{

GENERATED_BODY()

public:

// Sets default values for this actor's properties

AMyActor();


protected:

// Called when the game starts or when spawned

virtual void BeginPlay() override;


public:

// Called every frame

virtual void Tick(float DeltaTime) override;


UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="MyActor")

FString message;


UFUNCTION(BlueprintCallable, Category="MyActor")

void SetMessage(FString msg);


};



생성된 C++ 액터클래스의 소스파일(적색으로 표시한 내용은 추가된 부분임)

// Fill out your copyright notice in the Description page of Project Settings.


#include "MyActor.h"



// Sets default values

AMyActor::AMyActor()

{

  // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.

PrimaryActorTick.bCanEverTick = true;


}


// Called when the game starts or when spawned

void AMyActor::BeginPlay()

{

Super::BeginPlay();

}


// Called every frame

void AMyActor::Tick(float DeltaTime)

{

Super::Tick(DeltaTime);


}


void AMyActor::SetMessage(FString msg)

{

this->message = msg;

}



블루프린트에서 C++ 커스텀 액터를 생성(Spawn)하고 사용하는 예



Posted by cwisky

언리얼 엔진에서 지원하는 C++ 컨테이너 사용 예


언리얼 엔진에서 지원하는 C++ 컨테이너에는 아래와 같은 것들이 있는데, 다른 고급언어에서 지원하는 List, Set, Map 과 같은 컬렉션 API와 유사한 특징을 갖고 있다

 

  • TArray<T> : 원소의 중복허용, 순서유지
  • TSet<T> : 원소의 중복안됨, 순서유지
  • TMap<T,S> : 키, 값의 쌍으로 데이터를 저장함, 키는 중복 안됨



언리얼 엔진에서 BlueprintFunctionLibrary 하위 클래스를 작성하고 아래와 같은 내용으로 TArray<T> 를 테스트한다


TArray<FString> UMyBlueprintFunctionLibrary::ArrayTest()

{

TArray<FString> strArr;


strArr.Add(FString("Smith"));

strArr.Add(FString("Jone"));

strArr.Add(FString("Scott"));

strArr.Add(FString("Andy"));

strArr.Add(FString("Andy")); // 중복저장도 허용되고, 저장순서도 유지된다

strArr.Insert(FString("WARD"),0);


int len = strArr.Num();


//인덱스를 이용한 배열의 원소접근

for (int i = 0; i < len; i++) {

FString name = strArr[i];

}

//반복자를 이용한 배열의 원소접근

for (TArray<FString>::TIterator it = strArr.CreateIterator(); it; ++it) { //후증가는 구현안됨

FString name = *it;

}


return strArr;

}



블루프린트 그래프에서 다음과 같이 TArray<T>를 한다 (C++코드를 수정했으면 블루프린트에서도 살짝 변경하여 다시 저장해주면 제대로 반영되는 것 같다)




TSet<T> 테스트 : 저장 순서가 유지되고 중복저장은 안된다


TSet<int> UMyBlueprintFunctionLibrary::SetTest()

{

TSet<int> set;


set.Add(2);

set.Add(1);

set.Add(3);

set.Add(5);

set.Add(4);


set.Add(5); // 오류는 아니지만 중복저장은 안됨


// TSet은 인덱스를 이용하여 접근할 수는 없다(반복자만 가능)

for (TSet<int>::TIterator it = set.CreateIterator(); it; ++it) { // 후증가 기능은 정의되지 않음

int num = *it;

FString sNum = FString::FromInt(*it);

}

return set;

}



블루프린트에서 다음과 같이 TSet<T>을 테스트할 수 있다




TMap<T,S>의 테스트


TMap<FString, FString> UMyBlueprintFunctionLibrary::MapTest()

{

TMap<FString, FString> map;


map.Add(FString(TEXT("1번")), FString(TEXT("Adam")));

map.Add(FString(TEXT("2번")), FString(TEXT("Marry")));

map.Add(FString(TEXT("3번")), FString(TEXT("Jone")));

map.Add(FString(TEXT("4번")), FString(TEXT("Smith")));

map.Add(FString(TEXT("5번")), FString(TEXT("Andy")));

map.Add(FString(TEXT("5번")), FString(TEXT("Ward"))); // 중복안됨,기존 5번 항목을 덮어씀


FString name = map[FString(TEXT("2번"))];

for (TMap<FString, FString>::TIterator it = map.CreateIterator(); it; ++it) {

FString key = it->Key;     // K는 대문자

FString name = it->Value;  // V는 대문자

}


return map;

}



TMap<T,S>는 블루프린트에서 다음과 같이 테스트할 수 있다


Posted by cwisky