블럭 생산 튜토리얼부터 튜토리얼 끝까지 만들어 볼 것이다.
블럭 생성 튜토리얼, 대포 생성 튜토리얼, 적 저치 튜토리얼, 튜토리얼 종료
블럭 생성 튜토리얼

InputController
[SerializeField] CanvasGroup blockGroup; // 블럭 생산 UI
public void ResourceTutorial() // 자원 생산자 생성 튜토리얼 시작
{
StartCoroutine(UIFade(resourceGroup,1, true));
PlaneSetting(new Vector3(0, 0.5f, -0.5001f), Quaternion.Euler(0,0,0));
}
public void SeletePanel(bool state) // 생성 튜토리얼 블럭 생성창 // 튜토리얼 단계
{
if(resourceCoroutine != null)
{
StopCoroutine(resourceCoroutine);
}
if(myState == TutorialState.BLOCK)
{
seletePanel.GetComponent<RectTransform>().anchoredPosition = new Vector3(-250, 0, 0);
}
resourceCoroutine = StartCoroutine(UIFade(seletePanel,0.5f, state));
}
private void PlaneSetting(Vector3 pos, Quaternion rot) // 선택 면 생성 설정
{
if(currentSeletePanel != null)
{
Destroy(currentSeletePanel);
}
currentSeletePanel = Instantiate(seletePlane, pos, rot);
}
public void BlockTutorial() // 자원 생산이후 블럭 튜토리얼 시작
{
// 제거
if(resourceCoroutine != null)
{
StopCoroutine(resourceCoroutine);
}
resourceCoroutine = StartCoroutine(UIFade(seletePanel, 0.1f, false));
myState = TutorialState.BLOCK;
currentSeletePanel.SetActive(false);
StartCoroutine(UIFade(resourceGroup, 1.5f, false));
// 생성
PlaneSetting(new Vector3(0,0.5f,0.5001f), Quaternion.Euler(0, 180, 0));
StartCoroutine(UIFade(blockGroup, 3, true));
}
blockGroup으로 블럭 생성 튜토리얼에서 사용할 텍스트를 사용한다.
PlaneSetting 함수부터 살펴보면 파라미터로 위치와 회전값을 지녀, 다양한 포지션에서 생성할 수 있게한다. ResourceTutorial과 BlcokTutorial에서 각기 다른 위치와 회전값을 주어 강조면을 생성한다.
SeletePanel에서 현재 튜토리얼의 상황을 인지하고 seletePanel의 위치를 옮겨 생성한다.
BlockTutorial에서 이전 튜토리얼의 흔적을 제거하고, 새로운 생성 위치와 생성 블럭을 표시해준다.
InputController
void LeftClick() // 블럭을 좌클릭 하면 생성할 블럭의 종류 UI를 표시한다.
{
if(Input.GetMouseButtonDown(0) && !isSeleting)
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); // 카메라로 부터 클릭한 월드좌표까지 광선
if (Physics.Raycast(ray, out hit, Mathf.Infinity, LayerMask.GetMask("Cube"))) // 광선에 맞은 충돌체를 담는다.
{
if (TutorialManager.Instance.myState == TutorialManager.TutorialState.RESOURCE) // 자원 생산 튜토리얼 단계일 때
{
if (hit.normal != new Vector3(0, 0, -1) || hit.transform.GetComponent<Block>().myCaster != this) // 플레이어 큐브 뒤쪽을 클릭하지 않았을 때
{
return;
}
}
else if (TutorialManager.Instance.myState == TutorialManager.TutorialState.BLOCK) // 블럭 튜토리얼 단계일 때
{
if (hit.normal != new Vector3(0, 0, 1) || hit.transform.GetComponent<Block>().myCaster != this) // 플레이어 큐브 뒤쪽을 클릭하지 않았을 때
{
return;
}
}
if (hit.transform.GetComponent<Block>().myCaster == this)
{
UIManager.Instance.ShowSeleteBlock(Input.mousePosition); // 큐브 선택창 생성
isSeleting = true;
seletePlane.InsPlane(hit);
if (GameManager.Instance.myState == GameManager.GameState.TUTORIAL) // 자원 생산 튜토리얼 단계일 때
{
TutorialManager.Instance.SeletePanel(true);
}
// cubeCreator.InsCube(hit.normal, hit.transform, this); // 큐브 생성하기
}
camera_M.ChengeTarget();
Debug.Log("큐브 클릭");
cubeShader.CubeOutLine(hit.transform.gameObject);
previewManager.PreviewObject(hit);
}
}
else if(Input.GetMouseButtonDown(0)) // 선택중일 때, 다른 자신의 큐브 클릭 처리
{
// if (TutorialManager.Instance.myState == TutorialManager.TutorialState.RESOURCE) // 자원 생산 튜토리얼 단계일 때
if(GameManager.Instance.myState == GameManager.GameState.TUTORIAL)
{
return;
}
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); // 카메라로 부터 클릭한 월드좌표까지 광선
if (Physics.Raycast(ray, out hit2 , Mathf.Infinity, LayerMask.GetMask("Cube"))) // 광선에 맞은 충돌체를 담는다.
{
hit = hit2;
if (hit.transform.GetComponent<Block>().myCaster == this) // 자신의 큐브를 선택했을 때 선택 면 재위치
{
seletePlane.DeletePlane();
seletePlane.InsPlane(hit);
}
else // 다른 큐브를 선택했을 때 선택못하게하기
{
CancelSelete();
UIManager.Instance.InActiveSeleteBlock();
}
camera_M.ChengeTarget(); // 타겟 변경
cubeShader.CubeOutLine(hit.transform.gameObject); // 외곽선 처리
previewManager.PreviewObject(hit); // 미리보기 처리
}
}
}
public void seleteBlock(int num)
{
RaycastHit currentHit = hit;
if(currentHit.transform == null)
{
return;
}
if(isSeleting)
{
if (TutorialManager.Instance.myState == TutorialManager.TutorialState.RESOURCE && (num == 1 || num == 3)) // 자원 생산 튜토리얼 단계일 때
{
Debug.Log("선택중 패스");
return;
}
else if (TutorialManager.Instance.myState == TutorialManager.TutorialState.RESOURCE && num == 2) // 자원 생산 튜토리얼 단계일 때
{
TutorialManager.Instance.BlockTutorial();
}
else if (TutorialManager.Instance.myState == TutorialManager.TutorialState.BLOCK && (num == 2 || num == 3)) // 블럭 생산 튜토리얼 단계일 때
{
return;
}
else if (TutorialManager.Instance.myState == TutorialManager.TutorialState.BLOCK && num == 1) // 블럭 생산 튜토리얼 단계일 때
{
TutorialManager.Instance.CannonTutorial();
}
isSeleting = false;
switch (num)
{
case 1:
Debug.Log(currentHit.normal + " " + currentHit.transform);
cubeCreator.InsCube(currentHit.normal, currentHit.transform, this); // 큐브 생성하기
break;
case 2:
cubeCreator.Conversion(currentHit.normal, currentHit.transform, this); // 큐브 생성하기
break;
case 3:
cubeCreator.CreateCannon(currentHit.normal, currentHit.transform, this); // 큐브 생성하기
break;
default: break;
}
UIManager.Instance.InActiveSeleteBlock();
seletePlane.DeletePlane();
}
}
public void CancelSelete()
{
// if(TutorialManager.Instance.myState == TutorialManager.TutorialState.RESOURCE)
// {
// return;
// }
if(GameManager.Instance.myState == GameManager.GameState.TUTORIAL)
{
TutorialManager.Instance.SeletePanel(false);
}
isSeleting = false;
seletePlane.DeletePlane();
}
LeftClick 함수에서는 블럭 생성 튜토리얼일 때는 또 특정 위치 이외에 클릭을 무시한다. 이외의 여러 if문에서 Resource 상태의 튜토리얼이 나닌 GameManager 튜토리얼 상태를 확인하여 튜토리얼 일때로 범위를 늘린다.
seleteBlock 함수에서는 튜토리얼 상태일 때의 생성할 수 있는 블럭을 제외한 생성을 불가시킨다.
CancelSelete 함수에서 카메라 회전시 선택이 해제되는 기능을 구현했다.
UIManager
public void InActiveSeleteBlock()
{
// if (TutorialManager.Instance.myState == TutorialManager.TutorialState.RESOURCE) // 자원 생산 튜토리얼 단계일 때
// {
// return;
// }
// seleteBlock.SetActive(false);
seleteBlock.Finish();
}
선택 해제시 블럭 생성 선택 UI또한 내려가도록 다시 수정해주었다.
완성본

자원 생산 튜토리얼을 만드는데 가장 오래거렸지만 그 시스템을 활용해서 Block을 만드니까 이번껀 만들기 수월했다.
대포 생성 튜토리얼
TutorialManager
[SerializeField] CanvasGroup cannonGroup; // 대포 생산 UI
private Coroutine[] canvasCoroutine = new Coroutine[3]; // 텍스트 캔버스 코루틴
private void Update()
{
if(myState == TutorialState.CAMERAMOVE)
{
cameraMoveBar.fillAmount = totalCameraMove / maxCameraMove;
cameraScrollBar.fillAmount = totalCameraScroll / maxCameraScroll;
if(totalCameraMove >= maxCameraMove && totalCameraScroll >= maxCameraScroll)
{
ResourceTutorial();
}
}
}
public void TutorialStart() // start 버튼이후 플레이 시작
{
tutorialText.SetActive(true);
GameManager.Instance.GameStart(); // 튜토리얼 시작
canvasCoroutine[0] = StartCoroutine(UIFade(cameraGroup,3,true));
}
public void ResourceTutorial() // 자원 생산자 생성 튜토리얼 시작
{
myState = TutorialState.RESOURCE;
if (canvasCoroutine[0] != null)
{
StopCoroutine(canvasCoroutine[0]);
}
StartCoroutine(UIFade(cameraGroup, 1, false));
~~~~~~~~~~~생략~~~~~~~
}
public void SeletePanel(bool state) // 생성 튜토리얼 블럭 생성창 // 튜토리얼 단계
{
if(resourceCoroutine != null)
{
StopCoroutine(resourceCoroutine);
}
if(myState == TutorialState.BLOCK)
{
seletePanel.GetComponent<RectTransform>().anchoredPosition = new Vector3(-250, 0, 0);
}
else if(myState == TutorialState.CANNON)
{
seletePanel.GetComponent<RectTransform>().anchoredPosition = new Vector3(250, 0, 0);
}
resourceCoroutine = StartCoroutine(UIFade(seletePanel, 0.5f, state));
}
public void BlockTutorial() // 자원 생산이후 블럭 튜토리얼 시작
{
// 제거
if(resourceCoroutine != null)
{
StopCoroutine(resourceCoroutine);
}
resourceCoroutine = StartCoroutine(UIFade(seletePanel, 0.1f, false));
if (canvasCoroutine[1] != null)
{
StopCoroutine(canvasCoroutine[1]);
}
StartCoroutine(UIFade(resourceGroup, 1.5f, false));
currentSeletePanel.SetActive(false);
// 생성
myState = TutorialState.BLOCK;
PlaneSetting(new Vector3(0,0.5f,0.5001f), Quaternion.Euler(0, 180, 0));
canvasCoroutine[2] = StartCoroutine(UIFade(blockGroup, 3, true));
}
public void CannonTutorial()
{
myState = TutorialState.CANNON;
// 제거
if (resourceCoroutine != null)
{
StopCoroutine(resourceCoroutine);
}
resourceCoroutine = StartCoroutine(UIFade(seletePanel, 0.1f, false));
currentSeletePanel.SetActive(false);
if (canvasCoroutine[2] != null)
{
StopCoroutine(canvasCoroutine[2]);
}
StartCoroutine(UIFade(blockGroup, 1, false));
// 생성
Debug.Log("대포 튜토리얼 시작");
StartCoroutine(UIFade(cannonGroup, 3, true));
PlaneSetting(new Vector3(0, 0.5f, 1.5001f), Quaternion.Euler(0, 180, 0));
}
public void FinalTutorial() // 적을 처치하는 마지막 튜토리얼 시작
{
}
CannonTutorial 함수는 앞선 함수들과 흡사한 코드를 지닌다.
추가로 작성한 코드는 CanvasGroup의 Fade를 관리하기 위해 코루틴 배열을 만들어 관리한다.
InputController
void LeftClick() // 블럭을 좌클릭 하면 생성할 블럭의 종류 UI를 표시한다.
{
if(Input.GetMouseButtonDown(0) && !isSeleting)
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); // 카메라로 부터 클릭한 월드좌표까지 광선
if (Physics.Raycast(ray, out hit, Mathf.Infinity, LayerMask.GetMask("Cube"))) // 광선에 맞은 충돌체를 담는다.
{
if (TutorialManager.Instance.myState == TutorialManager.TutorialState.RESOURCE) // 자원 생산 튜토리얼 단계일 때
{
if (hit.normal != new Vector3(0, 0, -1) || hit.transform.GetComponent<Block>().myCaster != this) // 플레이어 큐브 뒤쪽을 클릭하지 않았을 때
{
return;
}
}
else if (TutorialManager.Instance.myState == TutorialManager.TutorialState.BLOCK) // 블럭 튜토리얼 단계일 때
{
if (hit.normal != new Vector3(0, 0, 1) || hit.transform.GetComponent<Block>().myCaster != this) // 플레이어 큐브 뒤쪽을 클릭하지 않았을 때
{
return;
}
}
else if (TutorialManager.Instance.myState == TutorialManager.TutorialState.CANNON) // 블럭 튜토리얼 단계일 때
{
if (hit.normal != new Vector3(0, 0, 1) || hit.transform.GetComponent<Block>().myCaster != this) // 플레이어 큐브 뒤쪽을 클릭하지 않았을 때
{
return;
}
}
~~~~~~~~~~중략~~~~~~~~~~
}
}
~~~~~~~~~~중략~~~~~~~
}
public void seleteBlock(int num)
{
RaycastHit currentHit = hit;
if(currentHit.transform == null)
{
return;
}
if(isSeleting)
{
if (TutorialManager.Instance.myState == TutorialManager.TutorialState.RESOURCE && (num == 1 || num == 3)) // 자원 생산 튜토리얼 단계일 때
{
Debug.Log("선택중 패스");
return;
}
else if (TutorialManager.Instance.myState == TutorialManager.TutorialState.RESOURCE && num == 2) // 자원 생산 튜토리얼 단계일 때
{
TutorialManager.Instance.BlockTutorial();
}
else if (TutorialManager.Instance.myState == TutorialManager.TutorialState.BLOCK && (num == 2 || num == 3)) // 블럭 생산 튜토리얼 단계일 때
{
return;
}
else if (TutorialManager.Instance.myState == TutorialManager.TutorialState.BLOCK && num == 1) // 블럭 생산 튜토리얼 단계일 때
{
TutorialManager.Instance.CannonTutorial();
}
else if (TutorialManager.Instance.myState == TutorialManager.TutorialState.CANNON && (num == 1 || num == 2)) // 블럭 생산 튜토리얼 단계일 때
{
return;
}
else if (TutorialManager.Instance.myState == TutorialManager.TutorialState.CANNON && num == 3) // 블럭 생산 튜토리얼 단계일 때
{
TutorialManager.Instance.FinalTutorial();
}
isSeleting = false;
~~~~~~~~~~~~중략~~~~~~~~~~
}
}
앞서 만들었던 것처럼, 생성위치를 지정하고, 생성블럭을 정한다. 대포 생성시 FinaleTutorial 함수를 호출한다.
적 처치 튜토리얼
[SerializeField] Text seletePanelText; // 생성창 선택UI 텍스트
private Coroutine[] canvasCoroutine = new Coroutine[5]; // 텍스트 캔버스 코루틴
[SerializeField] Text dialogText; // 대사 문자 텍스트
[SerializeField] List<string> sentences = new List<string>(); // 대사 문자
private Coroutine dialogCoroutine; // 대사 출력 코루틴
public enum TutorialState // 튜토리얼의 단계 (할수 있는 입력이 늘어난다.)
{
CAMERAMOVE = 0, // 카메라 조작 단계
RESOURCE = 1, // 생산자 생성 단계
BLOCK = 2, // 블럭 생성 단계
CANNON = 3, // 대포 생성 단계
FINAL = 4, // 적 처치 단계
}
public void ResourceTutorial() // 자원 생산자 생성 튜토리얼 시작
{
myState = TutorialState.RESOURCE;
if (canvasCoroutine[0] != null)
{
StopCoroutine(canvasCoroutine[0]);
}
StartCoroutine(UIFade(cameraGroup, 1, false));
dialogCoroutine = StartCoroutine(TypeSentence(sentences[0]));
canvasCoroutine[1] = StartCoroutine(UIFade(resourceGroup,1, true));
PlaneSetting(new Vector3(0, 0.5f, -0.5001f), Quaternion.Euler(0,0,0));
}
public void SeletePanel(bool state) // 생성 튜토리얼 블럭 생성창 // 튜토리얼 단계
{
if(resourceCoroutine != null)
{
StopCoroutine(resourceCoroutine);
}
if(myState == TutorialState.BLOCK)
{
seletePanelText.text = "Click or Q";
seletePanel.GetComponent<RectTransform>().anchoredPosition = new Vector3(-250, 0, 0);
}
else if(myState == TutorialState.CANNON)
{
seletePanelText.text = "Click or E";
seletePanel.GetComponent<RectTransform>().anchoredPosition = new Vector3(250, 0, 0);
}
resourceCoroutine = StartCoroutine(UIFade(seletePanel, 0.5f, state));
}
public void BlockTutorial() // 자원 생산이후 블럭 튜토리얼 시작
{
~~~~~~~~ 중략~~~~~~~~
if(dialogCoroutine != null)
{
StopCoroutine(dialogCoroutine);
}
dialogCoroutine = StartCoroutine(TypeSentence(sentences[1]));
currentSeletePlane.SetActive(false);
~~~~~~~~~ 중략 ~~~~~~~~~~~~
}
public void CannonTutorial()
{
~~~~~~~~~~~~~중략 ~~~~~~~~~~~~~
if (dialogCoroutine != null)
{
StopCoroutine(dialogCoroutine);
}
dialogCoroutine = StartCoroutine(TypeSentence(sentences[2]));
~~~~~~~~~~~~ 중략~~~~~~~~~~~~~~
}
public void FinalTutorial() // 적을 처치하는 마지막 튜토리얼 시작
{
myState = TutorialState.FINAL;
// 제거
if (resourceCoroutine != null)
{
StopCoroutine(resourceCoroutine);
}
resourceCoroutine = StartCoroutine(UIFade(seletePanel, 0.1f, false));
currentSeletePlane.SetActive(false);
if (canvasCoroutine[3] != null)
{
StopCoroutine(canvasCoroutine[3]);
}
StartCoroutine(UIFade(cannonGroup, 1, false));
if (dialogCoroutine != null)
{
StopCoroutine(dialogCoroutine);
}
dialogCoroutine = StartCoroutine(TypeSentence(sentences[3]));
}
IEnumerator TypeSentence(string sentence) // 대사를 출력하는 함수
{
dialogText.text = "";
foreach(char c in sentence)
{
dialogText.text += c;
yield return new WaitForSeconds(0.05f);
}
}
먼저 TutorialState에 Final을 추가해주고, 사용한다. FinalTutorial 함수에서 시작한다.
추가로 만든 기능은 대사 기능으로 현재 튜토리얼 상태에 따라 추가적인 대사가 출력된다. TypeSentence 코루틴 함수를 통해서 한 글자씩 출력되며, 코루틴 관리또한 해주었다.
SeletePanel에서 seletePanel의 text를 수정하게끔 해주었다.
InputController
void LeftClick() // 블럭을 좌클릭 하면 생성할 블럭의 종류 UI를 표시한다.
{
if(Input.GetMouseButtonDown(0) && !isSeleting)
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); // 카메라로 부터 클릭한 월드좌표까지 광선
if (Physics.Raycast(ray, out hit, Mathf.Infinity, LayerMask.GetMask("Cube"))) // 광선에 맞은 충돌체를 담는다.
{
~~~~~~~~~~~~중략~~~~~~~~~~~~~
if (hit.transform.GetComponent<Block>().myCaster == this)
{
UIManager.Instance.ShowSeleteBlock(Input.mousePosition); // 큐브 선택창 생성
isSeleting = true;
seletePlane.InsPlane(hit);
if (GameManager.Instance.myState == GameManager.GameState.TUTORIAL && TutorialManager.Instance.myState < TutorialManager.TutorialState.FINAL) // 자원 생산 튜토리얼 단계일 때
{
TutorialManager.Instance.SeletePanel(true);
}
// cubeCreator.InsCube(hit.normal, hit.transform, this); // 큐브 생성하기
}
~~~~~~~~~~~~중략~~~~~~~~~~~~~~~
}
}
else if(Input.GetMouseButtonDown(0)) // 선택중일 때, 다른 자신의 큐브 클릭 처리
{
// if (TutorialManager.Instance.myState == TutorialManager.TutorialState.RESOURCE) // 자원 생산 튜토리얼 단계일 때
if(GameManager.Instance.myState == GameManager.GameState.TUTORIAL && TutorialManager.Instance.myState < TutorialManager.TutorialState.FINAL)
{
return;
}
~~~~~~~~~~~~~~~~중략~~~~~~~~~~~~~~~
}
}
}
public void CancelSelete()
{
// if(TutorialManager.Instance.myState == TutorialManager.TutorialState.RESOURCE)
// {
// return;
// }
if(GameManager.Instance.myState == GameManager.GameState.TUTORIAL && TutorialManager.Instance.myState < TutorialManager.TutorialState.FINAL)
{
TutorialManager.Instance.SeletePanel(false);
}
isSeleting = false;
seletePlane.DeletePlane();
}
Final 상태에서는 자유롭게 플레이 할수있게, >= ~~~Final과 같이 if문을 변경해주었다.
완성본

각 튜토리얼 마다 대사가 나온다.
대포 튜토리얼이 끝나면 대부분의 행동이 가능해진다.
튜토리얼 종료 및 전체적인 시스템
먼저 튜토리얼에서의 Enemy Data를 새로 만들어서 사용할 것이다.

공격을 아예 할수 없으며 행동 쿨타임이 긴 튜토리얼 전용 데이터이다.
ID는 100으로 설정해주었다.
GameManager
public void GameStart() // 게임이 본격적으로 시작되는 단계
{
if(TutorialManager.Instance.isTutorial) // 튜토리얼 중일 때
{
myState = GameState.TUTORIAL;
enemyStage = 0;
gameStart?.Invoke();
return;
}
myState = GameState.START;
gameStart?.Invoke();
}
때문에 튜토리얼이 시자되면 enemStage를 0으로 바꿔 적의 데이터셋을 해준다.
TutorialManager
public void TutorialFinish() // 모든 튜토리얼을 맞쳤을 때
{
if(dialogCoroutine != null)
{
StopCoroutine(dialogCoroutine);
}
dialogText.text = "";
tutorialText.SetActive(false);
isTutorial = false;
}
대사를 종료하고, 튜토리얼 상태를 종료한다.
GameManager
public void CoreDestroyed(Caster DestroyedCaster)
{
if(myState != GameState.TUTORIAL)
{
myState = GameState.FINISH;
}
if(DestroyedCaster is EnemyAI)
{
winner = Winner.PLAYER;
Debug.Log("플레이어 승리");
}
else if(DestroyedCaster is InputController)
{
winner = Winner.ENEMY;
Debug.Log("플레이어 패배");
}
gameFinish?.Invoke();
Time.timeScale = 0f;
}
public void MainScene()
{
if(myState == GameState.TUTORIAL) // 현재 튜토리얼 상태일 때
{
myState = GameState.STANDBY;
TutorialManager.Instance.TutorialFinish();
}
enemyLevel = 1;
enemyStage = 1;
reGame?.Invoke();
gameInit?.Invoke();
myState = GameState.STANDBY;
winner = Winner.NONE;
enemyStage = 1;
mainScene?.Invoke();
Time.timeScale = 1f;
}
코어가 파괴되었을 때, 튜토리얼 상태라면 상태를 변경하지 않고, 메인으로 향했을 때, 튜토리얼 상태라면 TutorialFinish 함수를 호출한다.
UIManager
void playStart() // 게임시작 시 UI
{
if(GameManager.Instance.myState == GameManager.GameState.TUTORIAL) // 튜토리얼 상태일때
{
startButton.SetActive(false);
}
enemyLevels.SetActive(false);
playButton.SetActive(false);
resourceValue_T.gameObject.SetActive(true);
levelStage_T.text = "Level : " + GameManager.Instance.enemyLevel_E.ToString() + "\nStage : " + GameManager.Instance.enemyStage.ToString();
if(GameManager.Instance.myState != GameManager.GameState.TUTORIAL)
{
levelStage_T.gameObject.SetActive(true);
}
}
void FinishUI()
{
finishPanel.SetActive(true);
// seleteBlock.SetActive(false);
InputController.Instance.CancelSelete();
if (GameManager.Instance.winner == GameManager.Winner.ENEMY)
{
enemyWin_t.SetActive(true);
retryButton.SetActive(true);
}
else if(GameManager.Instance.winner == GameManager.Winner.PLAYER)
{
playerWin_t.SetActive(true);
if (GameManager.Instance.enemyStage < 5 && GameManager.Instance.myState != GameManager.GameState.TUTORIAL)
{
nextButton.SetActive(true);
}
}
}
playStart 함수에서 튜토리얼 상태일 떄는 스테이지와 레벨이 보이지 않도록 한다.
FinishUI 함수에서 튜토리얼 상태일 때는 Next 버튼을 숨겨 메인으로만 향하게 한다.
최종 완성본

'GameDev > Cubidom' 카테고리의 다른 글
| Cubidom - 디테일 추가 및 버그 수정 2 (0) | 2026.04.30 |
|---|---|
| Cubidom - 디테일 추가 및 버그 수정 1 (0) | 2026.04.29 |
| Cubidom - FTUE 만들기 2 (0) | 2026.04.27 |
| Cubidom - FTUE 만들기 1 (0) | 2026.04.26 |
| Cubidom - 전체적인 디자인 추가 (0) | 2026.04.25 |