QTN에 정의 가능한 것들.
- component : 유니티 entity에 컴퍼넌트로 붙여서 값을 넣어서 퀀텀코드로 넘길 수 있음
- 미리정해진키워드 ex) input, global : component와 비슷하게 유니티에서 퀀텀코드로 넘길 변수를 추가 할 수 있는데,
미리 정의 된 키워드를 사용해야하고, frame안에 해당 키워드들을 얻어오는 함수도 미리 정의 되어 있다.
특히 global 키워드는 여러 qtn에 중복으로 선언 되어 있을 수 있고, 빌드하면 codegen의 __global__에 통합 된다.
- enum : 빌드하면 codegen에 추가 되고 단순 enum뿐 아니라 관련 된 세트가 추가 된다.
- synced event
EVENT_TYPE_COUNT가 증가 되고 GetEventType 에 case가 추가 된다.
EventBase 상속받는 XX 클래스가 추가 된다
FrameEvents 클래스에 XX형을 리턴하는 XX이름의 함수가 추가 되고 해당 함수 호출 시 frame의 이벤트 리스트에 add 된다.
- signal XX(int32 value);
ISignal 인터페이스를 상속 받는 ISignalXX 이름의 인터페이스가 생성 된다
Frame클래스에 ISignalXX 배열형의 변수가 선언 되고, XX이름의 함수가 추가 된다.
*런타임 에러
Checksum Error Detected By Server, Simulation Halting.
quantum.code를 리빌드하고 게임 exe 를 다시 빌드해서 테스트 하니 정상 작동.
퀀텀&유니티 통신 목록
—------------------------------------
퀀텀코드
Signal
퀀텀코드->유니티 CALL
Event
OnEntityInstantiated
유니티->퀀텀코드 CALL
[미리 정의 됨]
CallBack + input ( callback 의 구조체파라미터인 미리 정의 된 이름의 input의 변수를 사용자 정의 가능 )
[사용자 정의 가능]
EntityComponent
Command
퀀텀&유니티 통신 상세
—------------------------------------
*OnEntityInstantiated
퀀텀코드->유니티 CALL
entityView.OnEntityInstantiated.AddListener(OnEntityInstantiated);
*event
퀀텀코드->유니티 CALL
[호출 순서]
1.qtn 파일에 event{ string log; } 등록
2.unity 씬에 포함 된 오브젝트의 스크립트가 시작 되는 부분에서 case2 호출.
3.quntum.code 에서 f.events.log(“test”); 호출
ex)
case 1.QuantumCallback.Subscribe(this, (CallbackPollInput callback) => PollInput(callback));
case 2.QuantumEvent.Subscribe<EventLog>(this, EventLog);
*CallBack
유니티->퀀텀코드 CALL
ex)
QuantumCallback.Subscribe<CallbackPollInput>(this, PollInput);
public void PollInput(CallbackPollInput pollInput)
{
pollInput.SetInput(a, DeterministicInputFlags.Repeatable);
}
*Command
유니티->퀀텀코드 CALL
[준비]
1.DeterministicCommand를 상속받는 클래스 생성 후 파라미터로 넘겨받을 변수를 멤버 변수로 선언.
1-1.추상 함수 Serialize 재정의 후 멤버변수 serialize
1-2.실제 동작 할 함수 “Excute” 선언
2.모든 Command를 처리 할 System 클래스 생성 후 SystemSetup에 등록
2-1.update에서 frame.PlayerCommand 얻어온 후 실제 동작 함수 Excute 호출
var command = f.GetPlayerCommand(player->player);
if(command is SHCommand shcommand)
{
shcommand.Excute(f);
}
2-2.유니티에서 호출
QuantumRunner.Default.Game.SendCommand(new SHCommand()
{
shNumber = 3,
});
*Signal
퀀텀코드->퀀텀코드 CALL.
전역적으로 접근 할 수 있는 frame 내부에 함수를 선언 하는 것이다.
[Signal 선언]
.qtn 에 signal FunctionName(parametertype parametername);
[Signal 정의]
quantum.code system 클래스를 정의한 ISignalxx 인터페이스로 상속 받는다.
함수 구현 해 주면 호출시 해당 함수가 호출 된다
[Signal 호출]
f.signal.xx();
<유니티에서 퀀텀 주요 키워드 얻어오기>
EntityRef
GetComponent<EntityView>().EntityRef
Frame
var frame = QuantumRunner.Default.Game.Frames.Predicted;
<퀀텀문법>
*GetPointer
파라미터로 generic 형식에 Quantum.IComponent 형 struct를 넣어주면 entityRef 가 가지고 있는 컴퍼넌트를 리턴 한다. Quantum.IComponent 형 struct를 만들기 위해서는 qtn 파일에 component로 선언 해 주면 된다.
ex)
PlayerData data = f.Unsafe.GetPointer<PlayerData>(entityRef);
*TryGetPointer
GetPointer과 사용 목적이 같다.
ex)
if( f.Unsafe.TryGetPointer<PlayerData>(entityRef, out PlayerData* playerData))
{
}
*QuantumRunner : 유니티에서 Quantum에 접근하기 위한 MonoBehavior을 상속받는 인스턴스.
Session이라는 객체를 가지고 있고 내부의 update에서 Session.Update 돌면 퀀텀코드의 각종 콜백들이 호출 된다. 그중 하나가 “OnGameStart”
사용법
QuantumCallback.Subscribe(this, (CallbackGameStarted callback) => GameStarted(callback));
그런데 정작 필요한 OnGameStart가 호출 됐을 때 퀀텀코드에서 처리 할 함수는 재정의가 안 된다. OnEntityInstantiated는 Signal을 상속 받아서 처리 할 수 있는데 콜백은 안 돼서 아쉽다. command를 쏴서 구현 가능.
퀀텀 dsl component 는 component를 상속받은 struct이다
qtn에 struct를 정의 할 수 있고, struct에 함수를 추가 하고 싶으면 같은 이름의 구조체 하나 만들고 patial키워드 붙인 후 함수 선언 해 주면 된다.
*자료형변환
float time;
FP time;
float To FP
확장함수를 사용해서 time.ToFP(); 해 주면 되고
FP To float
time.AsFloat
*퀀텀 프록시 패턴 사용 예 ( 대리자 )
스킬 쿨타임을 퀀텀코드에서 관리 한다고 했을 때 유니티 UI에서 출력하기 위해 값을 얻어와야 하는데, event를 계속 쏴서 얻어오긴 부담스럽기 때문에 프록시패턴을 이용해서
프록시 클래스를 만들고 그 안에 얻어 올 퀀텀 코드에서의 프로타입컨퍼넌트들을 멤버 변수로 선언 해 준다.
static 으로 자기 자신을 리턴하는 Resolve 함수를 만들고, frame과 entityRef를 이용해서 GetPoint로 값을 가져온 뒤 프록시에 담아서 리턴한다.
callback+command 주의사항
퀀텀에서 정의 한 콜백을 사용 할 때 QuantumCallback.Subscribe 으로 콜백 등록을 하는데, 유니티 실행 후 바로 활성화 되는 게임오브젝트의 Awake에 Subscribe를 한 후, 콜백에서 Command를 했더니 퀀텀에서 받질 못했고 Start에서 Subscribe 하니 받아졌다. 콜백 자체는 호출 되는걸 보면 Command가 전송이 안 되는것같은데 아마 콜백 등록당시에는 QuantumRunner.Default.Game이 비정상 상태이지 않을까 싶다. 각각 로그를 찍어봤을때는 모두 QuantumRunner.Defualt가 null이고, 내부적으로 아직 다른 요소가 Awake에서는 준비가 안 된 상태이지 않을까싶다.
퀀텀코드 포인터주의
Get을 할 때는 상관없지만 Set을 할 때는 포인터를 다른 변수에 넣어두고 그 변수의 값을 셋팅하면 값이 변하지 않는다. 자신 없으면 좀 길더라도 원본에 셋 하도록 한다
GetPointer의 반복버전
var abilityHolders = f.Unsafe.GetComponentBlockIterator<Abilitys>();
foreach (var (e, a) in abilityHolders)
*퀀텀 WokerJob ( 쓰레드 ) 사용
SystemMainThread가 아닌 SystemBase 상속 받아서 작업
<???????????????????????>
?프레임개념?
Frame의 Predicted , Verified 차이
?아이콘 모양 차이는?
같은 프로젝트인데 솔루션에 따라 아이콘이 다르게 보이는 경우가 있다. 아래 c#이 보이는 아이콘의 프로젝트는 속성 보기가 가능하고, 위의 아이콘 프로젝트는 속성 보기가 안 된다.

'서버엔진' 카테고리의 다른 글
| 유니티 넷코드 ( NET CODE ) & 유니티 MLAPI (0) | 2022.07.28 |
|---|---|
| 포톤 퀀텀 (2) | 2022.07.10 |