유니티 엔진 (Unity Engine)

유니티..바이블 - 19장 마스터 데이터 퀘스트 (2화 끝)

원생계 2019. 10. 10. 22:05

.

.

1화에서 이어집니다.

1화 : https://wonsorang.tistory.com/544

 

유니티..바이블 - 19장 마스터 데이터 퀘스트 (1화)

. . 19장: 마스터 데이터 퀘스트 Excel Importer, 마스터 데이터의 구축과 활용, 레벨 디자인, ScriptableObject ​ - Excel Importer 플러그인을 이용한 엑셀 파일의 이용 방법 - 엑셀 파일을 이용하는 마스터..

wonsorang.tistory.com


MasterDataRepository 클래스를 만들어 퍼사드로 사용.

[Pseudo Code]

[CreateAssetMenu] //어셋 Create 메뉴에 MasterDataRepository 노출.

public class MasterDataRepository : ScriptableObject

{

[SerializeField] MstMonsters monsters; // 원본 엑셀에서 생성한 에셋을 연결.

// ...

public MstStageEntity GetMstStage( int id )

{

return stages.Entities.Find( entity => entity.id == id );

}

// ...

}

이 어셋은 Resources 폴더 아래에둬서 Resources.Load 로 동적 생성할 수 있도록 함.

엑셀 데이터 Importer 로 생성된 Assets 은 .assets 확장자로 YAML 타입 데이터. (Asset Serialization 타입이 Force Text 인 경우 Text 에디터로도 볼 수 있음)

하단의 Entities 엘리먼트 하위로 데이터가 늘어나는 구조.

=== Excel Importer 의 기타 기능 =====

플러그인의 몇 가지 추가 편리기능 소개

코멘트 행

행의 첫 셀 데이터가 # 문자로 시작하는 행은 주석으로 무시.

에셋 생성 경로 변경(지정)

ExcelAsset 어트리뷰트에 AssetPath 를 지정하면 원본엑셀 파일과 다른 디렉토리로 생성되게 할 수 있음.

[ExcelAsset(AssetPath=”Resources/MasterData”)]

public class MstItems : ScriptableObject { ... }

Resources 폴더 아래로 생성되도록 하면, MasterDataRepository 같은 중계 구조가 필요 없이 바로 동적 생성도 가능. Resources.Load( ... )

Enum 이용

Entity 클래스 필드 타입 Enum 으로, 원본 엑셀 해당 셀에 Enum타입 필드 이름을 입력하면 입포스 시 자동 변환. 엑셀 “데이터 입력 규칙”으로 드롭다운리스트 만들어두면 더 그럴싸.

=========================

마스터 데이터의 이용과 모델 클래스로의 변환

게임 진행에서, MasterDataRepository 는 데이터 원본 Entity 오브젝트만 취할 수 있음. 이 데이터는 const 로, 실제 객체에 반영할 땐 Model 클래스를 정의하고 객체를 생성해서 처리.

이 처리는 예제에서 ModelLoadAndSaveUseCase.cs 가 담당.

[Pseudo Code]

// ModelLoadAndSaveUseCase.cs

pubilc MosterModel GetnextMonster( int mstStageId )

{

MstStageMosterEntity nextStageMoster = MstDataRepo.GetRandomMonster( mstStageId );

return new MonsterModel( mstMonsterEntity, nextStageMonster.level );

}

...

// MonsterModel.cs

public class MonsterModel

{

생성자( MstMonsterEntity, level )

{

self.mylevel = level;

self.myMaxHitPoint = Formula.EnhancedValue( mstEntity.baseHitPoint, level ); // 가중치 계산

self.myCurHitPoint = myMaxHitPoint;

... 초기화 초기화 초기화

}

자기자신데미지처리()

{

self.myCurHitPoint = Mathf.Clamp( HitPoint 감소처리, 0, 최대치 ); // 바운더리 처리

}

플레이어공격처리( 플레이어모델 )

{

실제 데미지 = 데미지계산( 베이스 공격력, 플레이어 방어력 );

// Do Something

}

}

EnhancedValueLevel = max( BaseValue + (Level - 1) ), BaseValue * 1.15^(Level-1) )

스테이지에 지정된 몬스터 레벨에 맞게 몬스터의 능력치 속성들에 일정 가중치를 더해주는 식.

모델 데이터의 이용과 표시

생성한 모델을 화면에 표시하고 이벤트 등을 제어하는 클래스 BattlePresenter

외형 처리는 View 클래스. MonsterView, StageView

BattlePresenter 에서 모두 초기화.

3// ObserveModel 은 UserModel 을 인자로 받는데, 함수명이 좀 더 명확해야겠는데

빈 Action을 선언하고,

이렇게 활용 중. OnTab 은 StageView 의 Event Trigger 로 PointerClick 이 발생할 때 호출 중.

AttackToMonster() 함수의 내부에서는 monsterView의 PlayDamage 를 호출하는데, 애니메이션 종료 콜백으로 람다식을 전달하고, 이 람다 함수에서 데미지 처리등을 수행.

monterView.PlayDamage( (Action 타입의 람다식으로 전달) )

=> monterView.PlayDamage( () => { ... } );

가볍게 만들기에 좋아보이긴 하나, 코드 가독성은 좀 떨어지는 것 같다.

람다식은 함수 이름이 명확하질 않으니.

람다 콜백으로 처리하다보니, 멤버로 attacking 플래그를 둬서 예외처리를 하는데, 역시나 좋아보이진 않다.

아무튼 이렇게 처리 중.

=== COLUMN ==========

샘플 게임의 레벨 디자인 흐름

(레벨 디자인 전문가 X, 참고 정도로만)

유저 파라미터 고정

초기HP, 공격력 등 기본 파라미터는 적당히 짐작으로 결정. 이 값을 기준으로 전체 밸런스 조정 예정.

이후에는 변경하지 않는다.

몬스터 파라미터 조정

몬스터가 얼마나 강한지 나타내는 퍼포먼스 값을 HP, 공격력, 방어력 값으로부터 엑셀 자동계산되게. (엑셀 시트의 CurrentPerformance 열)

다음, 몬스터를 어느 정도의 성능 값으로 할지 목표값 할당. (TagetPerformance 열)

마지막, HP, 공격력, 방어력 값을 몬스터 이미지에 맞게 조정, 성능의 현재값과 목푯값 맞춤.

시뮬레이션 시트 = 어느정도의 유저 능력 레벨로 그 몬스터를 쓰러뜨릴지 정보 참고해서 위 값을 조정.

몬스터 드롭 스킬 포인트 조정

성능 값으로부터 일정 비율이 되게 자동 계산. 약한 몬스터가 대량의 스킬 포인트를 갖고 있는 걸 막고, 레벨업 속도를 감안하여 전체 비율을 제어하는 상수 조정.

몬스터 출현 스테이지와 레벨 조정

MstStageMonsters.xlsx 로부터 MstMonsters.xlsx 값을 참조, 입력 레벨의 성능 값을 자동 표시. 비슷한 세기 정도의 몬스터가 같은 스테이지에 나오도록 조정.

전체 플레이 조정

실제 플레이로 값 조정 반복. 유저 저장 데이터 편집해서 초,중,종반 상태 재현/시뮬레이션. 실제 레벨 상향을 그대로 두기도.

최종에는, 초기 데이터로 마지막까지 실제 플레이, 그 감/느낌으로 마스터 데이터 피드백 반영 반복.

결국 노가다.

====================

[참고자료]

Unity Doc : Scriptable Object

스크립터블 오브젝트로 게임을 설계하는 멋진 방법 세 가지

https://unity3d.com/kr/how-to/architect-with-scriptable-objects

 

Architect your code in Unity the smart way with Scriptable Objects - Unity

ScriptableObject is a serializable Unity class that allows you to store large quantities of shared data independent from script instances. Using Scriptable Objects makes it easier to build in a level of flexible communication between the different systems

unity3d.com

.

.

728x90
반응형