https://www.udemy.com/share/100YVuA0sbd1tXRng=/

 

이거보고 공부했읍니다.

가격도 매우 저렴합니다 언리얼 블로그에서 링크통해가면 더 할인도 되요(영어주의)

 

 

 

리플리케이트로 움직이는 액터의 

 

 

헤더파일

 

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

#pragma once

#include "CoreMinimal.h"
#include "Engine/StaticMeshActor.h"
#include "MovingPlatform.generated.h"

/**
 * 
 */
UCLASS()
class TEST_API AMovingPlatform : public AStaticMeshActor
{
	GENERATED_BODY()

public:
	AMovingPlatform();
	
	virtual void Tick(float DeltaTime) override;

	virtual void BeginPlay() override;

	UPROPERTY(EditAnywhere)//블프나 에디터상에서 모두 편집가능
		float Speed = 20;

	UPROPERTY(EditAnywhere, Meta = (MakeEditWidget = true))//에디터상 위젯에 나타냄
		FVector TargetLocation;

	void AddActiveTrigger(); //이동
	void RemoveActiveTrigger(); //해제

private:
	FVector GlobalTargetLocation;
	FVector GlobalStartLocation;

	UPROPERTY(EditAnywhere)
		int ActiveTriggers = 0; //트리거 발동조건
};

 

구현부

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

#include "MovingPlatform.h"

//움직이는 스태틱메쉬
AMovingPlatform::AMovingPlatform() {
	//틱 이벤트 사용
	PrimaryActorTick.bCanEverTick = true;

	//이물체가 이동성을 가지는지 설정 Enum형
	SetMobility(EComponentMobility::Movable);

}

void AMovingPlatform::BeginPlay()
{
	Super::BeginPlay();

	if (HasAuthority()) {
		//서버와 클라이언트를 동기화
		SetReplicates(true);
		SetReplicateMovement(true);
	}
	GlobalStartLocation = GetActorLocation();
	GlobalTargetLocation = GetTransform().TransformPosition(TargetLocation);
}

void  AMovingPlatform::Tick(float DeltaTime) {
	//부모로부터 가상함수를 재정의 하고있는지 확인
	Super::Tick(DeltaTime);

	if(ActiveTriggers >0 ) //트리거 발동되었을때.

	//참이면 서버, 거짓이면 단일 클라이언트일때를 분기
	if (HasAuthority()){
		//현재액터의 위치 변수저장하기
		FVector location = GetActorLocation();
	//틱마다 x축으로 델타시간*스피드 만큼 이동

	float JourneyLength = (GlobalTargetLocation - GlobalStartLocation).Size(); //목표지점과 첫지점의 거리
	float JourneyTravelled = (location - GlobalStartLocation).Size(); //현재내지점과 목표지점의 거리 

	if (JourneyTravelled >= JourneyLength) //목표지점 첫지점을 바꿈 
	{
		FVector Swap = GlobalStartLocation;
		GlobalStartLocation = GlobalTargetLocation;
		GlobalTargetLocation = Swap;
	}

	//방향벡터구하기
	FVector Direction = (GlobalTargetLocation - GlobalStartLocation).GetSafeNormal();
	//이동
	location += Speed * DeltaTime * Direction;
	SetActorLocation(location);
	
	
	
}
	
}

void AMovingPlatform::AddActiveTrigger()
{
	ActiveTriggers++;
}

void AMovingPlatform::RemoveActiveTrigger()
{
	if (ActiveTriggers > 0) {
		ActiveTriggers--;
	}
}

 

 

버튼이눌렸을때 액터가 움직이도록  하는 액터의 헤더파일 

 

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "PlatformTrigger.generated.h"

UCLASS()
class TEST_API APlatformTrigger : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	APlatformTrigger();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

private:
	UPROPERTY(VisibleAnywhere)
		class UBoxComponent* TriggerVolume;


	UFUNCTION() // 겹쳤을때 함수
		void OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

	UFUNCTION() // 나왔을대 함수
		void OnOverlapEnd(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

	UPROPERTY(EditAnywhere) //트리거가 발동되었을때 움직이는 플랫폼의 배열 
		TArray<class AMovingPlatform*> PlatformsToTrigger;

};

 

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

#include "PlatformTrigger.h"
#include "Components/BoxComponent.h"
#include "MovingPlatform.h"

// Sets default values
APlatformTrigger::APlatformTrigger()
{
 	// 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;

	TriggerVolume = CreateDefaultSubobject<UBoxComponent>(FName("TriggerVolume"));
	if(!ensure(TriggerVolume != nullptr)) return;
		RootComponent = TriggerVolume;

		TriggerVolume->OnComponentBeginOverlap.AddDynamic(this, &APlatformTrigger::OnOverlapBegin);
		TriggerVolume->OnComponentEndOverlap.AddDynamic(this, &APlatformTrigger::OnOverlapEnd);
}

// Called when the game starts or when spawned
void APlatformTrigger::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void APlatformTrigger::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

void APlatformTrigger::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	UE_LOG(LogTemp, Warning, TEXT("Activated"));

	for (AMovingPlatform* Platform : PlatformsToTrigger) //배열에있는 트리거들 모두순회
	{//이동트리거발동
		Platform->AddActiveTrigger();
	}

}

void APlatformTrigger::OnOverlapEnd(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	UE_LOG(LogTemp, Warning, TEXT("Deactivated"));

	
	for (AMovingPlatform* Platform : PlatformsToTrigger)
	{//이동트리거제거
		Platform->RemoveActiveTrigger();
	}
}

 

 

내가 3D맥스를 공부한 이유를 무쓸모로 만들어버린

 

Vroid를 유니티로 만들었다고 유니티에서만 써야한다는건 좀 뭔가 불합리해보여서

 

VR장비만으로 Vtuber 만드는김에 언리얼엔진에서도 써보고싶었다.

 

나온지 오래되지않은거라 영어,일본어,중국어로 구글링해봤는데 안나와서 직접 삽질하기로 결정!

 

vroid로 모델링을 만들어서 익스포트하면 

vrm확장자로 나온다.

 

이걸 fbx로 만들고싶다! 해서

 

시도한 첫번째방법.

이걸 gbl파일로 이름바꾸기하고 윈도우3D에서 fbx파일로 다른이름으로 저장!

텍스쳐 다날라가서 흰색 지점토만 나온다 ^오^

 

그래서 혼자 별짓다해서 드디어 방법을 찾아냄.

 

준비물.

 

VRoid

 

https://studio.vroid.com/download.html

 

VRoid

VRoid Studioは、人型アバター(キャラクター)の3Dモデルを作成できるWindows・Mac用アプリケーションで、どなたでも無償で利用可能になります。

studio.vroid.com

미소녀를 엄청나게 빠르게 모델링가능한 갓갓툴이다..

그러나 하이폴리곤 모델링이니 여러모델을 동시에 쓰기는 좀 힘들다.

전문 모델러가 리토폴로지하던가 머리카락 본도 손보고 등등 해야할게 좀 있을것이다.

그래도 버텍스가 많은만큼 이쁘게 나오고 쉐이더 공부하기 엄청조흠 굿굿.

 

 

 

https://github.com/dwango/UniVRM/releases

 

dwango/UniVRM

Unity package that can import and export VRM format - dwango/UniVRM

github.com

vrm을 유니티로 임포트 시켜주는 플러그인을 다운받는다.

 

 

그리고 에셋스토어에서 fbx익스포터를 다운받는다.

 

유니티 익숙한사람은 이쯤되면 감 올것이다.

 

자 이렇게 준비물 갖고오면 

 

유니티에 이렇게 보인다.

VRM탭에서 

import를 찾아 vrm파일을 임포트하면

요로케 프리팹으로 만들어준다.

 

 

유니티용답게 이쁘게 나오고 프레넬효과로 뽀샤시한 쉐이더가 적용되어있다.

 

스킨드메쉐 렌더러로 모퍼도 잘 임포트 되었다.

 

이제 지옥이 시작될것이니라

 

이 오브젝트를 하이어라키에서 오른클릭해서 fbx 익스포트를 한다.

 

스킨드메쉬 옵션 꺼져있는데 저거 체크해야한다.

 

나머지 옵션들 그대로 익스포트 ㄱ

 

그러면 스탠다드 쉐이더가 적용된 FBX의 몬슁긴 모델링이 나온다.

 

내가 맥스 배우고 저꼴나서 쉐이더 공부하기 시작했다.

 

이제 유니티 경로에있는 이 모델을 잘보이는 바탕화면이든 아무데나 복사해서 옮긴다!

이득우 교수님께서 IGC에서 발표해주신 언리얼 에디터 확장하기를 메인으로 공부 시작.

http://blog.naver.com/PostView.nhn?blogId=destiny9720&logNo=221381098226&categoryNo=21&parentCategoryNo=&from=thumbnailList

 

 

언리얼 위키

https://wiki.unrealengine.com/Creating_an_Editor_Module#Module_Folder_Structure

 

일본어 블로그

http://historia.co.jp/archives/370/

 

 

 

내가 이걸 정리하는 이유는 처음봤을때 자료를보며 누락된 내용이나 배경지식의 부족 때문에

삽질을 오지게해서다.

 

 

자 여기서 흔히 언리얼에서 코딩하는건 런타임모듈인데.

저기 에디터 모듈이라는거 따로 만들어줘야한다.

난 이거 언리얼에서 자동으로 만들어주는줄 알고 코드만 따라 쳐봤다가ㅋㅋ

왜 에러나지 하면서 하루종일 MSDN 쳐다보고있었다. ㅡㅡ

 

첫번째로 할일은 uproject파일을 메모장으로열면

프로젝트의 정보가 json파일 형태로 나타난다.

 

요걸

이렇게 모듈이름을 정해주도 타입을 에디터로 해서 추가해준다.

 

 

대표

사진 설명을 입력하세요.

 

저 폴더를 만들고

extensionEditor.target.cs 소스를

 

 

using UnrealBuildTool;
using System.Collections.Generic;

public class extensionEditorTarget : TargetRules
{
	public extensionEditorTarget(TargetInfo Target) : base(Target)
	{
		Type = TargetType.Editor;

		ExtraModuleNames.AddRange( new string[] { "extension", "extensionEditor" } );
	}
}

 

코드처럼 에디터 모듈을 코딩해준다.

 

 

일단 모듈을 만드려면 이렇게

소스폴더 안에 모듈폴더를 만들고

그 안에 폴더이름과 같은 파일들을 만들어줘야 하는데 내용물도 비슷해야 하므로

아예 새로만들면 같은 코딩을 두번해야하는 귀찮음이 있으니

프로젝트 만들면 있는 소스들을 복붙한다음 파일 이름이랑 안에 코드들만 바꿔주면 편하게만들 수 있다.

 

EditorStudy.build.cs 파일을 보고 의미를 찾아봤다.

 

 

이외에 API목록은 여기 찾아보면 있음 http://api.unrealengine.com/INT/API/

 

이제 헤더파일을 뜯어보자.

#pragma once

#include "CoreMinimal.h"


// 
class FExtensionModule : public IModuleInterface
{
public:
	// IModuleInterface 인터페이스 상속을 받으며 이 모듈이 로드,언로드 될때 호출할 가상함수 선언
	/** IModuleInterface implementation */
	virtual void StartupModule() override;
	virtual void ShutdownModule() override;
//이 두개는 cpp에서 무조건 구현해야함 안하면 에러뱉음
private:
	//FUIcommandlist 클래스는 에디터상의 멀티박스와 매핑해주는 클래스.
	TSharedPtr<class FUICommandList> CommandList;
};

열심히 구글링했는데 아직은 먼말인지 정확히 이해는 안되나 그런 인터페이스라고 대충 알아먹어두자.

 

 

그리고 모듈의 구현부

 

#include "extensionEditor.h"
#include "Modules/ModuleManager.h"

//멀티박스 추가에 필요한 헤더
#include "Framework/MultiBox/MultiBoxExtender.h"
#include "Framework/MultiBox/MultiBoxBuilder.h"
#include "LevelEditor.h"


// IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, extension, "extension" );
//Primary게임모듈은 한프로젝트에 하나만 있어야한다는 규칙이다.
//지금 만드는건 에디터용 보조모듈이니 임플리먼트 모듈로 만든다.
IMPLEMENT_MODULE(FextensionEditor, "ExtensionEditor");


#define LOCTEXT_NAMESPACE "Menu"

void FextensionEditor::StartupModule(){
}

void FextensionEditor::ShutdownModule() {

}

#undef LOCTEXT_NAMESPACE

 

이렇게 만들고 솔루션을 다시 빌드한 후 .

 

언리얼 에디터를 켜서러 새 c++ 클래스를 만들면.

 

그리고 모듈제작을 했으니 에디터 모듈이 제작가능해진다!

 

내가 이 모듈을 사용할때 어떤 명령을 내리고 어떤 동작을 실행할건지 또 정해줘야한다.

 

https://api.unrealengine.com/INT/API/Runtime/Slate/Framework/Commands/TCommands/index.html

TCommands

A base class for a set of commands.

api.unrealengine.com

 

https://api.unrealengine.com/INT/API/Runtime/Slate/Framework/Commands/FUICommandInfo/__ctor/index.html

FUICommandInfo::FUICommandInfo

Creates and initializes a new instance.

api.unrealengine.com

 

위 링크는 언리얼 에디터 내에 UI정보를 담고있는 커맨드에 대한 설명

 

 

다음글에서

 

인터페이스 상속받아서 구현해야하는 

StartupModule 과 
ShutdownModule를 

 

이제 내가 원하는 대로 코딩해보자

1. 프린세스 커넥트 

 

일본 cygames 답게 게임 진짜 공들여서 잘만들었다.

과금모델도 돈 잘벌리게 잘 설계해놨다.

게임성보다 호화 성우진 풀보이스 더빙과 애니메이션 퀄리티때문에 하게되는게임.

 

 

2. 밀리시타

 

캐릭터 렌더링도 이쁘게 잘나오고 최적화도 완전 잘되있다.

무엇보다 카메라 워킹이 정말 대박이라 연출에 배울게 많다!

라이트하게 즐길수 있어서 좋다.

정작 게임은안하고 오토돌리고 춤추는거 구경하고있다 ㅋㅋㅋㅋ

 

유나이트 재팬 2018때 최적화 노하우발표가있어서 봤는데 크리티컬한 부분은 공개를 안해줘서 아쉬움.

 

 

3. 붕괴3

모바일인데비해 액션과 이펙트 퀄리티가 정말 장난아닌데도 렉도 그다지 안걸리는 외계인기술 게임.

유나이트 2018때 발표보고 쉐이더 최적화 뽕맞아서 텍스쳐 하나도 못뽑는주제에 TA가 되고싶다고 생각하게 된 게임.

 

복귀한후 1년넘게 꾸준히 즐기는중.

근데도 아직 만렙을 못찍었다..

 

컨텐츠 업데이트량이 장난 아니라서 해야할 컨텐츠가 정말 많아서 좋다. 

 

4. 라스트오리진

 

오토만 돌렸는데 레벨은 거의 흑우가 되어있다 ㅋㅋ

똉컨이좀 나왔으면ㅜㅜ

 

20명남짓한 중소기업에서 만들어서 그런지 최적화, 버그 엄청많다.

근데 매력적인 캐릭터가 몇몇있어서 그거 모으려고 오토돌리는게임.

출시후 한달째인데 버그가 많고 캐릭터만 생기고 컨텐츠 업데이트가 없다.

 

과금모델만큼은 정말 혜자라고해도 무방하지만 덜만들어서 내놓았다고할까..

유저들이 QA하는 얼리억세스 게임 ㅠㅠ  

 

버그때메 겜이 안되서 거의 접은상태

'일상 > 게임' 카테고리의 다른 글

프리코네 vtuber 홍보전략  (0) 2019.04.08

넓은 바다나 호수를 누비는 레이싱게임을 

 

pc vr 플랫폼으로 만들어보고싶어서 여기까지만 만들어봤다.

 

물아래가아니라 위에서 움직일때 물살 가르는듯한 느낌을 이펙트 적용하는데에서 애먹었다. 

 

그리고 부력이라고 해야하나 아래로 갈수록 뜨는힘이 강해져야하고 

 

제동시에 걸리는 물의 저항과 가속도 구현하는데 제일 시간 오래걸렸다.

 

물위에서 높게 떠올랐을때 카메라가 아래를 보게해서 플레이어가 맵을 구경할 수 있게 하는게 포인트.

 

'포트폴리오 & 토이프로젝트 > 토이프로젝트' 카테고리의 다른 글

달려요 할아버지  (0) 2019.04.08
프로토 타입  (0) 2019.04.04

 

매 웨이브마다 루트 따라오는 몬스터를 잡아 벌은 재화로 스킬 강화하고 무기 강화하는식의 게임.

 

무기나 스킬에 속성이있어서 몬스터상성에 맞는 스킬과 공격을 해야함.

 

몬스터 모델링과 마법진 에셋만 썼음.

 

구현사항.

 

매 웨이브마다 웨이브 표시되며 일정수량의 몬스터 출현.

 

마법진의 종류가 4서클까지 총 16가지인데 이것들을 각자 다르게조합해서 다른 속성의 스킬나가는거 구현.

 

총쏘는거 맞는거 데미지와 속성 구현 

 

주먹으로 때리는것도 가능한데 x축 velocity값 구해서 타격 데미지계산 및 일정 계수 지나면 이펙트 나오도록 설정.

 

칼도 velocity값으로 직접 구현한 매터리얼로  트레일 효과만들어서 궤도이펙트 구현.

 

내비메쉬와 스플라인 써서 진행경로 표시해주는것 구현. 

 

 

 

 

개발 필요사항.

 

때릴때마다 뭔가 타격감 낼만한 것이 필요함.

 

한단계당 4개의 마법선택및 조합으로 16가지 마법진이 생기는데

이게 경우의 수가 16!라 스킬을 구현해야하는데 이거

스킬마다 속성달아주고 사운드 달아주고 이펙트 달아주고.. 데이터테이블 구조는 만들어놨지만 상당한 노가다가

요구됨. 

 

 

테스트용으로 만든 늑대들 100마리쯤 넣으니 렉걸려서.

본피직스 꺼놓고 죽을때만 켜게하고 순전히 캡슐콜리더만 써서 충돌처리하니까 잘됨.

근데 저렇게 끼는게 문제.

 

맵을 다듬던가 네비메쉬 설정좀 다듬어주면 될듯.

 

 

 

코멘트.

 

오로지 VR만의 조작방식을 타겟으로 만들어보고 싶어서 만든건데

 

VR시장 좁아서 아직 미래가 안보임. 

 

그리고 만들어보니 원하는 기능까지 나오긴 했는데 이펙트와 사운드가 없으니 타격감이 전혀없어서 정말 중요한것같음.

'포트폴리오 & 토이프로젝트 > 토이프로젝트' 카테고리의 다른 글

달려요 할아버지  (0) 2019.04.08
수중물리 구현  (0) 2019.04.04

+ Recent posts