https://github.com/Kimhyogyeom/ProjectA
GitHub - Kimhyogyeom/ProjectA: Unity-MOBA-Prototype
Unity-MOBA-Prototype. Contribute to Kimhyogyeom/ProjectA development by creating an account on GitHub.
github.com
https://github.com/Kimhyogyeom/ProjectB
GitHub - Kimhyogyeom/ProjectB: Drill-inspired Project
Drill-inspired Project. Contribute to Kimhyogyeom/ProjectB development by creating an account on GitHub.
github.com
안녕하세요.
오랜만에 글을 올리는 것 같습니다.
과제도 하고, 면접 준비도 하고, 일도 급격히 기획이 변경되다 보니 정말 정신없는 나날이었네요😂
이번 포트폴리오 영상 제작을 마지막으로 ProjectB를 마무리하려 합니다.
오늘 업데이트 한 내용은 Fever와 관련된 내용입니다.
가장 먼저 Fever모드로 전환될 때 사용될 버튼을 만들어 주었습니다.
이후 Fever 모드 버튼과 연동된 UI 및 게임 오브젝트 상태를 관리하는 역할을 맡을
FeverButtonController 스크립트를 만들어 주었습니다.
using System.Collections;
using UnityEngine;
using UnityEngine.UI; // Image 쓰려면 필요
public class FeverButtonController : MonoBehaviour
{
[Header("UI")]
[SerializeField] private Button _feverButton;
[SerializeField] private Image _feverImage;
[Header("Object")]
[SerializeField] private GameObject _basicObject;
[SerializeField] private GameObject _feverObject;
[Header("Component")]
[SerializeField] private GroundMoveDown _groundMoveDown;
private bool _isCharging = true; // fillAmount 차오르는 중인지 여부
private float _chargeSpeed = 0.05f;
private AudioClip _feverClip;
private AudioClip _playClip;
void Awake()
{
_feverButton.onClick.AddListener(OnClickFeverButton);
}
void Start()
{
_feverClip = SoundManager.Instance._soundDatabase._feverBgm;
_playClip = SoundManager.Instance._soundDatabase._playBgm;
}
void Update()
{
if (_isCharging && _feverImage.fillAmount < 1f)
{
_feverImage.fillAmount += _chargeSpeed * Time.deltaTime;
}
// 게이지가 가득 차면 버튼 활성화
if (_feverImage.fillAmount >= 1f)
{
_feverButton.interactable = true;
}
}
private void OnClickFeverButton()
{
StartCoroutine(FeverCoroutine());
}
IEnumerator FeverCoroutine()
{
SoundManager.Instance.PlayBGM(_feverClip, 0.5f);
_feverImage.fillAmount = 0;
_feverButton.interactable = false;
_isCharging = false; // 충전 멈춤
_groundMoveDown._downSpeed = 2;
_basicObject.SetActive(false);
_feverObject.SetActive(true);
yield return new WaitForSeconds(11.0f);
SoundManager.Instance.PlayBGM(_playClip);
_groundMoveDown._downSpeed = 0.4f;
_basicObject.SetActive(true);
_feverObject.SetActive(false);
// 다시 충전 시작
_isCharging = true;
}
}
핵심 로직은 다음과 같습니다.
Update()에서 게이지가 충전되게 해 주었으며
버튼의 클릭 여부는 interactable = true/false로 해 주었습니다.
void Update()
{
if (_isCharging && _feverImage.fillAmount < 1f)
{
_feverImage.fillAmount += _chargeSpeed * Time.deltaTime;
}
// 게이지가 가득 차면 버튼 활성화
if (_feverImage.fillAmount >= 1f)
{
_feverButton.interactable = true;
}
}
이후 Fever 버튼이 클릭되면 코루틴으로 Fever Mode를 실행되게 해주었습니다.
Fever 모드일 때 필요한 제어 로직들을 먼저 실행해주었으며
WaitForSeconds를 통해 일정 시간 지연 후 원래 상태로 돌아오게 해 주었습니다.
private void OnClickFeverButton()
{
StartCoroutine(FeverCoroutine());
}
IEnumerator FeverCoroutine()
{
SoundManager.Instance.PlayBGM(_feverClip, 0.5f);
_feverImage.fillAmount = 0;
_feverButton.interactable = false;
_isCharging = false; // 충전 멈춤
_groundMoveDown._downSpeed = 2;
_basicObject.SetActive(false);
_feverObject.SetActive(true);
yield return new WaitForSeconds(11.0f);
SoundManager.Instance.PlayBGM(_playClip);
_groundMoveDown._downSpeed = 0.4f;
_basicObject.SetActive(true);
_feverObject.SetActive(false);
// 다시 충전 시작
_isCharging = true;
}
다음은 FeverMode 일 때 시각적인 효과를 줄 드릴입니다.
이것도 Fixelart를 이용해 만들어 주었습니다😎
Fever Mode가 발동되면, 애니메이션을 통해 드릴이 생기는 연출 효과를 줘봤습니다.
다음은 Fever 스크립트를 만들어 주어 대미지를 입히는 효과를 주었습니다.
Fever Mode 상태일 때는
매 프레임 아래 방향으로 레이를 발사하여 충돌 처리가 됐을 때
Gun, Drone과 같은 대미지 로직을 수행하게 해 주었습니다.
using UnityEngine;
public class Fever : MonoBehaviour
{
[SerializeField] private float rayDistance = 10f; // 레이 길이
private int _feverDamage = 99999;
void Update()
{
// 아래 방향으로 Ray
RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.down, rayDistance);
// Scene 뷰에서 확인 (Play 모드에서만)
Debug.DrawRay(transform.position, Vector2.down * rayDistance, Color.red);
if (hit.collider != null)
{
if (hit.collider.CompareTag("BreakGround"))
{
hit.collider.GetComponent<BreakGroundController>()?.TakeDamage(_feverDamage);
// 데미지 텍스트 표시
DamageTextSpawner spawner = FindObjectOfType<DamageTextSpawner>();
spawner.ShowDamage(_feverDamage, transform.position);
}
}
}
// 에디터에서 항상 보이게 (Play 전에도 Scene 뷰에 표시됨)
private void OnDrawGizmos()
{
Gizmos.color = Color.green;
Gizmos.DrawRay(transform.position, Vector2.down * rayDistance);
}
}
다음은 Fever 버튼을 클릭할 때 순간적으로 렉이 걸리는 현상이 있었는데요
기존 Decompress on Load 타입으로 기본이 되어있었는데
재생 시 CPU에 부담은 거의 없고 즉시 재생이 가능하지만!
메모리 사용량이 매우 큰 단점이 있다고 하더라고요.
반대로 Compressed in Memory는
메모리에 압축 상태로 유지하며 재생 시 실시간 디코딩이 가능하며 메모리 절약이 가능하지만!
재생 시 CPU로 디코딩이 약간 필요하다고 합니다.
Load Type메모리 사용 CPU 부담재생 지연용도
| Decompress on Load |
높음 |
낮음 |
없음 |
짧은 효과음, UI |
| Compressed in Memory |
중간 |
중간 |
약간 |
중간 길이 효과음 |
| Streaming |
낮음 |
낮음 |
있음 |
긴 배경 음악 |
개인적으로 이해한 요약을 하자면!
Decompress on Load를 사용할 때는 짧은 효과음이나
반복 재생이 잦고 즉시 반응해야 하는 사운드 같은 경우 사용을 하게 되며
PC나 콘솔처럼 메모리가 비교적(?) 넉넉한 환경에 적합하며
모바일 저사양 환경 같은 경우는 메모리 부족이 매우 위험하기에, 사용하지 않을 것을 권장한다고 이해했습니다.
"지식 + 1"
다음 ProjectC는 어떠한 장르의 게임을 해볼까 생각 중에 있는데요
다양한 사이트를 통해서 인기 및 시장 동향을 파악해 보는 중에 있습니다.
https://www.upup.com/rank/ios/1-2-172-24-2?time=1758513600000&device=1&timetype=
Best All Games games for iPhone on App Store in the United States - UPUP
www.upup.com
블로그는
ProjectC로 다시 업로드를 진행하도록 하겠습니다.
모두 오늘 하루도 행복하게 잘 마무리하시고
좋은 일들 가득하셨으면 좋겠습니다.
감사합니다!