혼자라면 절대 불가능할 과제의 양을 협업을 통해 달성하고, 개벌적으로 추가하고 싶은 게임 기능들을 구현했다.
매칭 성공 시, 팀원의 이름 표시 / 실패 시 실패 표시 (종료 시 끝! 나타나는 것처럼)
카드 뒤집기에서 실제로 카드가 뒤집어지는 모습 연출하기
스테이지 선택과 현재 해금한 스테이지가 구분 가능한 시작 화면 만들기, 플레이 중 해당 스테이지의 최단 기록 띄워주기
한 번씩 뒤집은 카드는 색을 다르게 표시하기 (옅은 회색 등)
결과에 매칭 시도 횟수 표시
매칭 성공 시, 팀원의 이름 표시 / 실패 시 실패 표시
뒤집은 두 카드가 같을(다를) 경우, 두 카드 위에 카드가 의미하는 팀원의 이름(실패)를 일정 시간 팝업하는 기능이다.

성공, 실패 시 나타나는 텍스트를 프리팹으로 지정하고, 생성 시 페이드 아웃 애니메이션(스크립트로 작성)과 함께 일정 시간 후 사라진다.

IsMatched 함수(카드의 일치여부 판단 함수)를 이용해 구현한다.
아래는 이에 필요한 GM코드다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class gameManager : MonoBehaviour
{
[SerializeField]
GameObject MatchText;
public void IsMatched()
{
string firstCardImage = firstCard.transform.Find("front").GetComponent<SpriteRenderer>().sprite.name;
string secondCardImage = secondCard.transform.Find("front").GetComponent<SpriteRenderer>().sprite.name;
if (firstCardImage == secondCardImage)
{
MakeMatchText(firstCard.transform.Find("front").GetComponent<SpriteRenderer>().sprite.name);
}
else
{
MakeMatchText("실패");
}
}
void MakeMatchText(string text)
{
string name = SelectName(text);
GameObject firstCardText = Instantiate(MatchText, firstCard.transform.position, Quaternion.identity);
GameObject secondCardText = Instantiate(MatchText, secondCard.transform.position, Quaternion.identity);
firstCardText.transform.Find("Text").gameObject.GetComponent<Text>().text = name;
secondCardText.transform.Find("Text").gameObject.GetComponent<Text>().text = name;
}
string SelectName(string spriteName)
{
string name;
switch (spriteName)
{
case "member0":
name = "A";
break;
case "member4":
name = "A";
break;
case "member1":
name = "B";
break;
case "member5":
name = "B";
break;
case "member2":
name = "C";
break;
case "member6":
name = "C";
break;
case "member3":
name = "D";
break;
case "member7":
name = "D";
break;
case "실패":
name = "실패";
break;
default:
name = "카드없음";
break;
}
return name;
}
예를 들어 설명한다.
MatchText 게임오브젝트를 선언한다. 이때 [Serialized]를 통해 변수를 직렬화한다.
[Serialized]한 변수는 Inspector창에서 변수 할당이 가능하지만, 타 스크립트에서 접근이 불가능해진다. 이 기능으로 인해 해당 변수의 스크립트 내 보호가 이루어진다.
뒤집은 두 카드의 앞면 이미지명이 "member0"으로 일치하면, "member0"을 문자열 매개변수로 가지는 MakeMatchText함수를 실행한다. 불일치 시 "실패"문자열 매개변수로 MakeMatchText를 실행한다.
MakeMatchText실행 시, "member0"를 매개변수로 한 SelectName이 다시한번 실행되고, member0 => A라는 데이터를 가진 name변수가 return한다.
첫번째, 두번째 카드의 위치에 MatchText프리팹을 생성하고, 각각의 프리팹을 firstCardText, secondCardText 변수로 초기화한다.
firstCardText의 하위 오브젝트 Text에 A(name변수 데이터)를 할당한다.
위 과정을 통해 뒤집힌 두 카드의 일치 여부에 따른 MatchText의 팝업이 이루어진다.
MatchText의 애니메이션과 소멸을 구현한 스크립트는 다음과 같다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class MatchText : MonoBehaviour
{
[SerializeField]
float MoveSpeed; // 글자 올라가는 속도
[SerializeField]
float MoveMaxPosY; // 올라가는 Y 한계값
[SerializeField]
float PosY; // 카드 기준 Y값
float CheckMovePos = 0;
Text Text;
void Awake()
{
Text = transform.Find("Text").GetComponent<Text>();
transform.position += Vector3.up * PosY;
}
void Update() // 위치, 투명도, 오브젝트 파괴 조건
{
transform.position += Vector3.up * MoveSpeed * Time.deltaTime;
CheckMovePos += Vector3.up.y * MoveSpeed * Time.deltaTime;
Text.color = new Color(Text.color.r, Text.color.g, Text.color.b, 1.0f - (CheckMovePos /MoveMaxPosY ));
if (CheckMovePos > MoveMaxPosY)
{
Destroy(gameObject);
}
}
}
[Serialized]를 이용하면 속성 뷰에 다음과 같이 스크립트 내 변수가 표시된다.

카드 뒤집기에서 실제로 카드가 뒤집어지는 모습 연출하기

IsSelect 파라미터는 Trigger조건으로 설정한다.
카드 클릭시 애니매이션 코드는 다음과 같다.
public void OpenCard()
{
if (gameManager.I.IsStartAniOff == true) // 카드의 초기 애니메이션이 끝나기 전까지
// 카드 조작 방지를 위한 보호코드
{
GetComponent<Animator>().SetTrigger("IsSelect"); // 애니메이션 생성
}
}
Animator의 Transition 조건의 bool과 trigger은 어떤 차이가 있을까?
bool이 true가 될때 Transition조건이 참이 되어 애니메이션이 전환된다고 가정한다.
전환되어 작동하는 애니메이션의 loop설정이 어떻게 돼 있든 상관하지 않고 애니메이션이 끝나도 bool값은 true로 변하지 않고, 오브젝트는 전환된 애니메이션 상태 그대로 유지된다.
위 코드와 같이 IsSelect로 설정된 trigger로 애니메이션이 시작되면, 해당 애니메이션은 한번만 실행되고 오브젝트는 이전 애니메이션 상태로 되돌아온다.
+ 한번 뒤집힌 카드는 어둡게 표현하기
딱 한줄의 코드로 완성한다.
GM의 OpenCard에서 firstCardImage != secondCardImage일 경우 실행되는 card 스크립트의 CloseCard함수에서 긴으한다.
다음의 card 스크립트의 해당 코드다.
public void CloseCard()
{
Invoke("CloseCardInvoke", 0.5f);
}
public void CloseCardInvoke()
{
// gameManager.I.countDownGO.SetActive(false); couroutine함수가 섞인 다른 기능이다. 생략
transform.Find("front").gameObject.SetActive(false);
transform.Find("back").gameObject.SetActive(true);
transform.Find("back").gameObject.GetComponent<SpriteRenderer>().color = Color.gray; // 이 코드
}
0.5초 뒤 카드가 되돌아가고, 되돌아간 카드의 back이미지는 gray로 바뀐다.
잠깐 동안 '그럼 회색 카드를 또 뒤집으면 어떻게 되지?' 라고 생각했다.
되돌아간 카드의 back이미지가 gray로 바뀌는 건 다시한번 그대로 실행되니까 해결된 문제였다.
아 다른 조원이 구현한 기능도 모두 기록하려는 것은 좋은 의도고 당연한 행동이지만, 내가 직접 손대지 않은 기록이다 보니, 구현에는 물론 시간이 들지 않았지만, 글로 옮기려니 시간도 배로 들고 머리도 배로 아프다. 죽을맛인데 이거
'UNITY' 카테고리의 다른 글
| UNITY_20230811[팀 프로젝트_4] (0) | 2023.08.11 |
|---|---|
| UNITY_20230810[팀 프로젝트_3] (0) | 2023.08.10 |
| UNITY_20230808[팀 프로젝트_1] (0) | 2023.08.08 |
| UNITY_20230802[카드 짝 맞추기] (0) | 2023.08.03 |
| UNITY_20230728[고양이밥줘서내쫓기] (0) | 2023.08.01 |