캐릭터 선택
개요
Fighting Template은 Quantum 내부 자체에서 다음을 위해 캐릭터 선택 모드를 구현하고 있습니다:
- 캐릭터 선택에서 게임 플레이로의 전환을 단순화하며 그리고
- 완전히 결정론적인 방식으로 캐릭터 선택 규칙을 적용합니다.
주의: 이 접근 방식은 규칙 기반 캐릭터 선택(예: MOBA, 히어로 기반 슈팅 등)이 있는 모든 게임에 사용할 수 있습니다. 또한 라운드 종료 시 맵 선택 투표에 맞게 조정할 수 있습니다.
캐릭터 선택
캐릭터 선택의 시각적 피드백과 규칙 집합은 별도로 구현됩니다. 전자는 유니티에서 하고 후자는 퀀텀에서 구현합니다. 이 페이지에서는 캐릭터 선택 설정의 다양한 측면과 서로 간의 관계를 살펴봅니다.
유니티
Unity의 게임 씬에는 캐릭터 선택의 다음 부분이 포함됩니다:
- 선택 UI
- 캐릭터 선택 엔티티 프로토타입 그리고
- 플레이어가 선택하는 선택 결정을 반영하는 시각적 피드백용 콜백.
이런 모든 요소들은 CharacterSelect
객체 하위의 씬에서 찾아볼 수 있습니다(Side Bar and UI Camera > Camera > Foreground UI Canvas > CharacterSelect
).
선택 UI
캐릭터 프로필 사진을 사용하여 플레이어에게 캐릭터 선택 항목을 제공합니다. 컴포넌트는 다음과 같습니다.
- 원형 마스크
- 사용할 수 있는 캐릭터의 사각형 그림
- 현재 선택 항목을 강조 표시하는 컬러 원
선택 UI는 완전히 수동적입니다. 이 선택 순서와 이 선택 가능한 캐릭터는 캐릭터 선택 프로토타입에 의해 구동되며 선택 강조 표시는 캐릭터 선택 콜백 객체의 CharacterSelectCallback
스크립트에 의해 처리됩니다.
캐릭터 선택 프로토타입
유니티의 캐릭터 선택 UI P1 및 P2는 순수하게 시각적이며 Quantum의 CharacterSelectSystem
에 있는 기본 로직에 영향을 미치지 않습니다. CharacterSelectSystem
에 필요한 정보는 각각 캐릭터 선택 프로토타입 P1과 P2가 보관합니다.
캐릭터 선택 프로토타입은 다음 두 가지 컴포넌트만으로 구성됩니다.
Entity Prototype
그리고,CharacterSelect
컴포넌트
Entity Prototype
컴포넌트는 모든 유형의 엔티티 프로토타입에 필요한 반면, CharacterSelect
컴포넌트는 선택 가능한 전투기에 대한 정보와 선택 상호작용에 관련된 시청각 피드백을 보관하도록 특별히 설계되었습니다.
노트: 캐릭터 선택 프로토타입은 Quantum에서 게임 상태를 유지하는 데만 사용되는 엔티티를 만드는 데 사용되므로 유니티에서는 시각적 표현이 필요하지 않으므로 엔티티 뷰가 연결되어 있지 않습니다.
편집기에서 구성할 수 있는 필드들은 다음과 같습니다:
Fighter Index
: PlayerRef를 사용하여 해당 캐릭터 선택 프로토타입을 제어할 수 있습니다. Fighting Template에서 인덱스 0과 1은 각각 플레이어 1과 2에 매핑됩니다. PlayerRefs를 플레이어에게 할당하는 방법에 대한 자세한 내용은 설명서 > 플레이어를 참조하세요.Fighter Choices
: 이 필드에는 FighterDataAsset 목록이 있습니다. 각 FighterDataAsset는 선택 가능한 캐릭터를 나타냅니다. 주의: 나열된 순서는 Quantum의 CharacterSelectSystem에서 사용하는 선택 순서입니다. 선택 UI가 분리되었으므로 선택 UI의 캐릭터 프로파일과 캐릭터 선택 컴포넌트의 전투기 데이터 에셋의 순서를 수동으로 일치시켜야 합니다!Toggle Left / Right SFX
: 선택 영역을 왼쪽/오른쪽으로 이동할 때 SFX가 트리거되었습니다.Select SFX
: 플레이어가 캐릭터 선택을 확인하면 SFX가 트리거됩니다.
다른 모든 필드는 Quantum 시뮬레이션에서 CharacterSelectSystem에 의해 설정 및 조작됩니다.
선택의 시각화
CharacterSelectCallback
스크립트는 모든 플레이어 선택의 시각화 피드백을 처리합니다. Quantum 이벤트 및 콜백 (미) 구독과의 인터페이스를 처리하는 단순 유틸리티 부모 클래스인 SubscriptionBehaviour
를 기본 클래스로 상속합니다.
UI 요소 설정
CharacterSelectCallback
스크립트가 작동하려면 런타임에 조작할 수 있는 UI 요소를 알아야 합니다.
먼저 CharacterSelectSet
의 양을 설정해야 합니다. Fighting Template에서는 기본적으로 2명의 플레이어에게 사용되므로 2로 설정됩니다. 각 CharacterSelectSet
는 선택 가능한 캐릭터 사진이 배치되는 객체인 메인 객체와 캐릭터 사진 옆에 패널 형태로 배치된 강조 표시 원인 선택 컴포넌트 목록을 가져옵니다.
주의: 캐릭터 그림 강조 표시 패널은 캐릭터 선택 컴포넌트의 파이터 선택과 동일하게 정렬되어야 합니다!
마지막으로, CharacterSelectCallback
에는 선택이 진행되는 동안 표시되는 Main Header 및 Spectating Text에 대한 참조가 필요합니다.
- Main Header는 두 플레이어가 최종 선택을 마칠 때까지 제시됩니다.
- Spectating Text는 로컬 플레이어가 캐릭터 선택을 확인한 후 원격 플레이어가 자신의 캐릭터를 확인하기를 기다리는 동안 표시됩니다.
로직
CharacterSelectCallback
의 경우 CallbackUpdateView
콜백을 등록하고 리슨 합니다. 이 특정 콜백은 시뮬레이션(Quantum)이 뷰(유니티)로 제어 권한을 넘겨줄 때마다 트리거 됩니다. 이때 스크립트는 Quantum의 최신 검증된 프레임을 가져옵니다. 그런 다음 이 프레임을 사용하여 컴포넌트를 필터링하고 결과 수집을 반복하고 정보를 폴링 할 수 있습니다.
주의: 프레임 상태에서 poll 을 할 수 있습니다. 그러나 쓰기 는 허용되지 않습니다. 이는 불확실하며 시뮬레이션 비동기화가 발생할 수 있습니다.
그런 다음 프레임에서 폴링된 정보를 기반으로 CharacterSelectCallback
스크립트는 필요한 UI 요소를 활성화하거나 비활성화할 수 있습니다.
C#
protected override void SubscriptionDispatch(CallbackUpdateView result){
var frame = result.Game.Frames.Verified;
var charSelect = frame.Filter<CharacterSelect>();
bool isSelecting = false;
bool isSpectating = false;
while (charSelect.Next(out var e, out var cs)) {
var obj = characterSelectSets[cs.fighterIndex];
obj.mainObject.SetActive(cs.isSelecting);
for (int i = 0; i < obj.selectionComponents.Length; i++){
obj.selectionComponents[i].SetActive(cs.highlightedCharacterIndex == i && frame.Number % 10 < 5);
}
if (cs.isSelecting != true) continue;
if (result.Game.PlayerIsLocal(cs.playerRef)){
isSelecting = true;
} else {
isSpectating = true;
}
}
mainHeader.SetActive(isSelecting);
spectatingText.SetActive(isSpectating && !isSelecting);
}
Quantum
Quantum 측면에서는 캐릭터 선택 프로세스가 CharacterSelectSystem
에서 수행됩니다.
- 플레이어들은 사용 가능한 플레이어 목록에 추가됩니다.
- 목록의 처음 두 플레이어는 캐릭터를 선택할 수 있으며
- 패자는 목록에서 다음으로 사용 가능한 플레이어로 대체됩니다.
플레이어 할당
플레이어의 RuntimePlayer
데이터 수신은 ISignalOnPlayerDataSet
의 트리거가 발생됩니다.
C#
public void OnPlayerDataSet(Frame f, PlayerRef player){
var list = f.ResolveList(f.Global->playerOrderList);
list.Add(player);
var filter = f.Filter<CharacterSelect>();
while (filter.NextUnsafe(out var e, out var cs)) {
if (cs->isSelecting == true) continue;
list.Remove(player);
cs->playerRef = player;
cs->highlightedCharacterIndex = 0;
cs->isSelecting = true;
cs->lastInput = InputFlag.NONE;
break;
}
}
CharacterSelectSystem
은 시그널을 실행하고 이를 트리거 한 플레이어를 프레임에 있는 글로벌 목록 playerOrderList
에 추가합니다. 사용 가능한 공간이 있으면 CharacterSelect
컴포넌트에 대한 제어 권한이 할당되어 다음 경기에 참여할 캐릭터를 선택할 수 있습니다. 사용할 수 없는 경우 차례를 기다려야 합니다. Winner Stays 섹션을 참조하십시오.
선택 유효성 검사
CharacterSelectionSystem
은 Quantum 측의 캐릭터 선택 규칙을 적용합니다.
시스템은 먼저 선택 인덱스에 따라 목록에서 선택한 캐릭터를 루핑하여 유효한 공간에서 선택했는지 확인합니다.
C#
if ((inputFlag & InputFlag.Left) != 0) {
cs->highlightedCharacterIndex--;
if (cs->highlightedCharacterIndex < 0)
cs->highlightedCharacterIndex = cs->fighterChoices.Length - 1;
f.Events.PlayAudioEffect(FPVector2.Left, cs->toggleLeftSFX);
} else if ((inputFlag & InputFlag.Right) != 0){
cs->highlightedCharacterIndex++;
if (cs->highlightedCharacterIndex >= cs->fighterChoices.Length)
cs->highlightedCharacterIndex = 0;
f.Events.PlayAudioEffect(FPVector2.Left, cs->toggleRightSFX);
}
캐릭터마다 의상이 여러 개입니다. 캐릭터에 적용될 의상 변형은 캐릭터 선택을 확인하는 데 사용되는 액션 버튼에 따라 달라집니다.
C#
if ((inputFlag & InputFlag.LP) != 0) {
SelectionMade(f, cs, 0);
} else if ((inputFlag & InputFlag.LK) != 0) {
SelectionMade(f, cs, 1);
} else if ((inputFlag & InputFlag.HP) != 0) {
SelectionMade(f, cs, 2);
} else if ((inputFlag & InputFlag.HK) != 0) {
SelectionMade(f, cs, 3);
}
SelectionMade()
메소드는 뷰 업데이트를 위한 확인 이벤트를 트리거 시키고 ISignalOnFighterSelected
시그널(FighterSystem
에 의해 구현됨)을 생성시켜줍니다. ISignalOnFighterSelected
는 선택한 캐릭터를 인스턴스화 해 주며 설정(위치, 회전, 동일한 쌍둥이인 경우 의상 교환 등) 하고 f.Global->ready
을 설정하여 두 플레이어 모두 선택을 마치고 설정이 완료되었다는 것을 반영합니다.
Winner Stays
Fighting Template은 아케이드 스타일 “Winner Stays” 매치를 구현합니다. 즉, 패자는 제어권을 포기하고 관중/대기 목록의 다음 참가자는 크라운을 향해 슛을 합니다. 플레이어를 선발하는 순서는 경기에 참가한 순서와 f.Global->playerOrderList
에 추가된 순서로 정해집니다 - CharacterSelectSystem
의 OnPlayerDataSet
메소드를 참고하세요.
이 프로세스는 NextMatchState
에셋에서 처리됩니다. 먼저 CharacterSelectSystem.RemoveFighter
를 호출하여 게임에서 진 선수를 제거합니다. 이렇게 하면 해당 파이터의 CharacerSelect
컴포넌트도 재설정되어 새 플레이어가 자신의 캐릭터를 선택할 수 있습니다. 마지막으로 남은 파이터의ResetRoundState.ResetFighters
로 재설정합니다.
새로운 플레이어가 캐릭터를 선택하자마자 다음 경기가 시작됩니다.
새로운 선택가능한 개릭터 추가
새 선택 가능한 캐릭터를 추가하려면 다음 단계를 수행하십시오.
CharacterSelect
컴포넌트의 DSL 정의 -array<asset_ref<FighterData>>[4] fighterChoices
에서 파이터 선택 배열의 크기를 늘립니다;- 캐릭터 선택 P1 및 P2 프로토타입의
CharacterSelect
컴포넌트에 있는fighterChoices
필드에 캐릭터의FighterData
에셋을 추가합니다. - 선택 UI에 캐릭터 초상화를 추가합니다.
- P1 및 P2용 선택 UI의 캐릭터 순서가
CharacterSelect
컴포넌트의fighterChoices
배열에 있는FighterData
에셋의 순서와 일치하는지 확인합니다.