목차
퀴즈 게임 만들기
25.02.21
Card가 Flip하지 않던 버그 해결
- 문제 원인 : Animation 상태가 지속되어 Rotation이 바뀔 수 없었던 것 --> 만든 Animation이 Transform에 영향을 주면 다른 Animation에 영향을 줄 수 있다.
- 해결 방법 : Animator의 'Apply Root Motion'을 체크하면 만든 애니메이션은 동작하지만 실제 Transform은 움직이지 않도록 고정시켜준다.
Popup Panel 만들기
: 만들었던 'Shop Panel'의 틀이 여러 곳에서 동일하게 사용되기 때문에 이를 여러 곳에서 사용할 수 있도록
--> 이름을 'Popup Panel'로 수정
>> 빈 게임 오브젝트로 'Panel' 생성
: 만들어둔 Background, Image 등등 전부 아래로 내려가고 위로 올라오는 Animation을 만들 것이기 때문에 전부 묶어주기
--> 전체적인 PosY를 Panel로 관리하도록 수정 및 Canvas Group 추가
--> Anchor는 Alt + Shift
>> Canvas Group으로 관리함에 따라 전체적으로 위치 조정
>> PopupPanelController.cs 생성
: 미리 만들어뒀던 SettingsPanelController.cs, ShopPanelController.cs, StagePanelController.cs 삭제
>> Popup Panel Controller.cs 추가 및 바인딩
>> Close Button의 OnClick()에 함수 바인딩
>> Popup Panel Prefab화 후, Prefab Variant 생성
: Hierarchy에서 Popup Panel 제거
--> Prefab Variant 생성, 이름은 'Setting Popup Panel'
※ Setting Panel의 우측 상단에 희미하게 틈이 생기는 것 수정
: Popup Panel의 Source Image를 None으로 설정하면 해결
--> Popup Panel을 수정해야 다른 Panel들도 한꺼번에 해결된다.
Settings Popup Panel 만들기
>> MainPanel에 Canvas와 Setting Popup Panel 바인딩
>> Settings Button의 OnClick()에 함수 바인딩
활동
>> Setting Popup Panel UI 만들기
: 아래 사진과 같이 만들기
>> Title Text (TMP)의 Color 변경
: (195, 198, 207, 255)
>> 빈 게임 오브젝트 'Settings' 생성
: Texts와 Buttons를 가로로 Layout --> Grid Layout Group으로 할 수 있지 않을까?
>> 'Settings'의 자식으로 빈 게임 오브젝트 'Texts'와 'Buttons' 생성
--> Vertical Layout Group의 Child Alignment는 Upper Left든 Middle Center든 상관없는 듯하다
>> 'Texts'의 자식으로 'SFX Text (TMP)'와 'BGM Text (TMP)' 생성
: Text로 생성
--> BGM Text도 Text 내용 제외하고 동일
>> 'Buttons'의 자식으로 'SFX Button'와 'BGM Button' 생성
: Button으로 생성, 자식의 Text를 삭제하고 자식으로 Image 추가 --> 이름은 각각 'SFX Handle', 'BGM Handle'
- Source Image 추가하고 Set Native Size
- Button의 OnClick()에 함수 바인딩
- BGM Button도 설정은 대부분 동일하고 함수만 다르게 바인딩
- SFX Handle, BGM Handle
>> 'Evaluate Button' 생성
: Button으로 생성
>> 빈 게임 오브젝트로 'Logo' 생성
>> 'Logo'의 자식으로 'Logo Image', 'Version Text (TMP)', 'Mocapot Image', 'Mocapot Text (TMP)' 생성
--> Version Text의 Color는 (118, 118, 118, 255)
>> 추후 수정사항
- 만든 Buttons의 Animation이 제대로 작동하도록 --> Toggle은 잘 움직이는데 Color가 정한 값이 아니라 마음대로 변하는 버그 존재
- Button의 기능 추가
※ Play 했을 때, Panel이 끝까지 올라가지 않는 버그 수정
>> 버그가 발생한 모습
>> 해결 방법
: Anchor의 MaxY를 Panel이 나타나고자 하는 위치까지 내려주고 Top을 0으로 설정
Shop Popup Panel 만들기
※ 상점의 Button들이 같은 Layout이 반복되기 때문에 하나를 Prefab으로 만들어서 전체적으로 사용 가능
>> Popup Panel의 Prefab Variant를 'Shop Popup Panel'라는 이름으로 생성
>> ShopPopupPanelController.cs 생성
: 'Shop Popup Panel'에 추가
>> Shop Button의 OnClick()에 함수 바인딩
>> MainPanelController.cs에 Shop Popup Panel Prefab 바인딩
>> Scroll View 생성
- 좌우로 스크롤은 하지 않을 것이기 때문에 Scroll Rect에서 Horizontal 체크 해제
- 설정창을 닫는 버튼과 Title Text는 스크롤에 영향이 없도록 Top을 300으로 설정
- Source Image를 None으로 설정
- Color의 Alpha값을 255로 변경
--> Anchor는 Alt + Shift
--> 구현할 때는 Color를 바꿔서 보기 좋게 만들면 편하다
※ Viewport의 Mask가 화면을 벗어난 부분을 가려준다.
※ Content는 Scroll View에서 보여줄 요소들이 배치된 영역
: Content의 자식으로 있는 것들을 관리한다. --> Content의 Height가 화면보다 짧으면 스크롤이 활성화되지 않는다.
>> Content의 자식으로 'Shop Item Button' 추가
>> 'Shop Item Button'의 Text를 수정
: 이름을 'Title Text (TMP)'로 수정하고 나머지 설정 --> 이후 복붙하여 'Price Text (TMP)'도 설정
--> Anchor는 Alt + Shift
--> 다시 Title Text와 Price Text 위치 조정함
>> 만든 'Shop Item Button'을 Prefab화 후, Hierarchy에서 삭제
: 만든 Prefab을 Content의 자식으로 추가
>> Content에 Vertical Layout Group 추가 후, Control Child Size의 Width 체크
: 자식 Object의 Width도 같이 조정할 수 있도록 체크
>> Sprite의 형태가 안 늘어나도록 Sprite Editor로 Slice하고 적용하기
: 'example_button_gray_bg-normal'
※ Image Resource의 용량을 줄이는 법
: 실제 Image의 크기대로 만드는 것이 아니라 모양을 유지할 수 있을 정도의 사이즈로 작게 만듦
--> 어차피 잘라서 Unity에서 늘리면 되기 때문에
>> Content에 'Content Size Filtter' 추가 후, Vertical Fit 설정
: Content의 Height를 자식 Object의 개수와 크기에 따라 자동으로 맞춰준다. (코드로도 늘릴 수 있다.)
--> Padding 및 Spacing 조정
>> ScrollBar의 디자인 변경
- ScriollBar Vertical의 Color는 Scroll Bar 외의 빈 공간의 색
- Handle의 Color는 Scroll Bar의 색
1. 'scrollbar_bg'를 Sprite Editor로 자르기
2. Scrollbar Vertical의 Source Image, Color, Image Type, PosX 변경
: Color는 (242, 242, 242, 255)로 설정
3. Handle의 Source Image, Color, Image Type 변경
: Color는 임의로 (140, 140, 140, 255)로 설정
>> 'Shop Item Button' Prefab에 'Hot Icon Image' 추가
: Image로 생성 --> 모든 버튼이 Hot 상품은 아니므로 Active를 체크 해제
--> Anchor는 Alt + Shift
>> Shop Popup Panel UI 제작
: 아래 사진과 같이 제작
--> 'Shop Item Button' Prefab을 Content의 자식으로 추가 및 복붙
--> Button마다 사진에 맞게 Color나 Title Text, Price Text 등을 모두 변경
>> 만든 버튼마다 OnClick()에 함수 바인딩
: index는 각각 맞게 0부터 8까지 설정 --> 한꺼번에 선택해서 추가하고 index만 바꾸면 편함
>> 'ShopPopupPanelController.cs'에 Shop Item Button(8) 바인딩
: 구매 복원 버튼은 IOS 환경에서만 필요하기 때문에
Level Popup Panel 만들기
>> Popup Panel의 Prefab Variant를 'Level Popup Panel'라는 이름으로 생성
>> Scroll View 생성
--> Anchor는 Alt + Shift
>> Content에 'Grid Layout Group' 추가
- Button의 Width, Height를 Grid Layout Group의 Cell Size에서 수정 가능
- Constraint : Column의 개수를 3개로 고정
>> Content의 자식으로 'Level Item Button' 추가
: Button으로 생성
최종 코드
>> MainPanelController.cs
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class MainPanelController : MonoBehaviour
{
[SerializeField] private TMP_Text heartText; // 남은 하트 수
[SerializeField] private TMP_Text stageText; // 현재 스테이지
[SerializeField] private Transform canvasTransform; // Canvas의 위치
[SerializeField] private GameObject settingsPopupPanelPrefab;
[SerializeField] private GameObject shopPopupPanelPrefab;
/// <summary>
/// Play Button을 눌렀을 때 호출되는 Method
/// </summary>
public void OnClickPlayButton()
{
GameManager.Instance.StartGame();
}
#region Main Menu 버튼 클릭 함수
/// <summary>
/// Shop 아이콘 터치 시, 호출되는 Method
/// </summary>
public void OnClickShopButton()
{
Instantiate(shopPopupPanelPrefab, canvasTransform);
}
/// <summary>
/// Stage 아이콘 터치 시, 호출되는 Method
/// </summary>
public void OnClickStageButton()
{
}
/// <summary>
/// Leaderboard 아이콘 터치 시, 호출되는 Method
/// </summary>
public void OnClickLeaderboardButton()
{
}
/// <summary>
/// Settings 아이콘 터치 시, 호출되는 Method
/// </summary>
public void OnClickSettingsButton()
{
Instantiate(settingsPopupPanelPrefab, canvasTransform); // Canvas의 자식 오브젝트로 생성되도록
}
#endregion
}
>> PopupPanelController.cs
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
public class PopupPanelController : MonoBehaviour
{
[SerializeField] private TMP_Text titleText; // 화면 상단의 Title Text
[SerializeField] private GameObject panelObject; // 팝업창 오브젝트
private Image _backgroundImage;
private void Awake()
{
_backgroundImage = GetComponent<Image>();
var color = _backgroundImage.color; // color는 Property기 때문에 바로 접근하여 수정 불가능하다
color.a = 0;
_backgroundImage.color = color;
panelObject.GetComponent<CanvasGroup>().alpha = 0;
}
private void Start()
{
ShowPopupPanel();
}
/// <summary>
/// 타이틀 텍스트에 타이틀 지정 함수
/// </summary>
/// <param name="title">타이틀</param>
public void SetTitleText(string title)
{
titleText.text = title;
}
/// <summary>
/// 닫기 버튼을 클릭했을 때 실행되는 함수
/// </summary>
public void OnClickCloseButton()
{
HidePopupPanel();
}
private void ShowPopupPanel()
{
// 초기화
_backgroundImage.DOFade(0, 0);
panelObject.GetComponent<CanvasGroup>().DOFade(0, 0);
panelObject.GetComponent<RectTransform>().DOAnchorPosY(-500f, 0);
_backgroundImage.DOFade(1f, 0.2f);
panelObject.GetComponent<CanvasGroup>().DOFade(1f, 0.2f);
panelObject.GetComponent<RectTransform>().DOAnchorPosY(0, 0.2f);
}
private void HidePopupPanel()
{
_backgroundImage.DOFade(1f, 0);
panelObject.GetComponent<CanvasGroup>().DOFade(1f, 0);
panelObject.GetComponent<RectTransform>().DOAnchorPosY(0, 0);
_backgroundImage.DOFade(0, 0.2f);
panelObject.GetComponent<CanvasGroup>().DOFade(0, 0.2f);
panelObject.GetComponent<RectTransform>().DOAnchorPosY(-500f, 0.2f)
.OnComplete(() => Destroy(gameObject));
}
}
>> ShopPopupPanelController.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(PopupPanelController))]
public class ShopPopupPanelController : MonoBehaviour
{
[SerializeField] private GameObject restorePurchaseButtonObject;
private void Start()
{
GetComponent<PopupPanelController>().SetTitleText("SHOP");
#if UNITY_IOS // IOS일 때만 적용되고 아니라면 아래 코드가 제거된다.
restorePurchaseButtonObject.SetActive(true);
#else
restorePurchaseButtonObject.SetActive(false);
#endif
}
public void OnClickShopItemButton(int index)
{
switch (index)
{
case 0: // TODO: 하트 60개 + 광고 제거
break;
case 1: // TODO: 광고 보고 하트 3개 받기
break;
case 2: // TODO: 광고 제거
break;
case 3: // TODO: 하트 20개
break;
case 4: // TODO: 하트 60개
break;
case 5: // TODO: 하트 150개
break;
case 6: // TODO: 하트 320개
break;
case 7: // TODO: 하트 450개
break;
case 8: // TODO: 구매 복원 (아이폰만 필요)
break;
}
}
}
>> SettingPopupPanelController.cs
: 스스로 제작 중
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
[RequireComponent(typeof(PopupPanelController))]
public class SettingPopupPanelController : MonoBehaviour
{
// BGM, SFX Button Animation
[SerializeField] private Image sfxButton;
[SerializeField] private Image bgmButton;
[SerializeField] private RectTransform sfxToggle;
[SerializeField] private RectTransform bgmToggle;
private bool onSFX = true;
private bool onBGM = true;
private void Start()
{
GetComponent<PopupPanelController>().SetTitleText("SETTINGS");
}
public void OnClickSFXButton()
{
if (onSFX)
{
onSFX = false;
// 초기화
//sfxButton.DOColor(new Color(242, 68, 149, 255), 0);
//sfxToggle.DOAnchorPosX(35f, 0);
sfxButton.DOColor(new Color(195, 198, 207, 255), 0.2f);
sfxToggle.DOAnchorPosX(-35f, 0.2f);
}
else
{
onSFX = true;
sfxButton.DOColor(new Color(242, 68, 149, 255), 0.2f);
sfxToggle.DOAnchorPosX(35f, 0.2f);
}
}
public void OnClickBGMButton()
{
if (onBGM)
{
onBGM = false;
// 초기화
//bgmButton.DOColor(new Color(242, 68, 149, 255), 0);
//bgmToggle.DOAnchorPosX(35f, 0);
bgmButton.DOColor(new Color(195, 198, 207, 255), 0.2f);
bgmToggle.DOAnchorPosX(-35f, 0.2f);
}
else
{
onBGM = true;
bgmButton.DOColor(new Color(242, 68, 149, 255), 0.2f);
bgmToggle.DOAnchorPosX(35f, 0.2f);
}
}
}
'Development > C#' 카테고리의 다른 글
멋쟁이사자처럼부트캠프 Unity 게임 개발 3기 62일차 (0) | 2025.02.25 |
---|---|
멋쟁이사자처럼부트캠프 Unity 게임 개발 3기 61일차 (0) | 2025.02.25 |
멋쟁이사자처럼부트캠프 Unity 게임 개발 3기 59일차 (1) | 2025.02.20 |
멋쟁이사자처럼부트캠프 Unity 게임 개발 3기 58일차 (0) | 2025.02.19 |
멋쟁이사자처럼부트캠프 Unity 게임 개발 3기 57일차 (0) | 2025.02.18 |