이번주 목표
1. 마카롱 키우기 완성(폴리싱)
2. FPS 장르 유형 카메라 워킹 공부를 위한 미로 탈출 게임
<중요!!!!>
개발을 하면서 버그를 잡고 가는 것은 정말 중요하다.
버그를 제대로 잡고 가지 않으면, 작았던 버그가 괴물이 될 수 있다..!!!
<Tip>
주석처리 할 때
//[TODO]
같은 처리를 해 두면 나중에 코딩 점검 시 확인이 용이하다.
마카롱 합체
마카롱 프리팹 재구성
마카롱 충돌 체크
마카롱 충돌 처리 제거, 생성
GameScene 코드
더보기
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class GameScene : MonoBehaviour
{
[SerializeField] GameObject m_RespawnObj = null;
[SerializeField] TextMeshProUGUI m_txtScore = null;
[SerializeField] Deadline m_Deadline = null;
[SerializeField] TextMeshProUGUI m_txtGameOver = null;
GameObject m_RespawnMacaron = null;
bool m_MouseClick = false;
bool m_MouseRelease = false;
const float RESPAWN_TIME = 3f;
float m_RespawnTime = RESPAWN_TIME;
[Header("DEBUG")]
[SerializeField] TextMeshProUGUI m_txtMousePos = null;
List<Macaron> m_ListMacaron = new List<Macaron>();
const int RESPAWN_HIGH_LEVEL = 4;
int m_HighLevel = 1;
int m_Score = 0;
const float DEAD_TIME = 2f; //[TODO][DEBUG] 1f로 원상 복구.
float m_DeadlineTime = 0f;
// Start is called before the first frame update
void Start()
{
RespawnMacaron(1, false);
if (null != m_Deadline)
{
m_Deadline.OnOffCollider(false);
}
m_Score = 0;
if(null != m_txtGameOver)
{
m_txtGameOver.gameObject.SetActive(false);
}
}
// Update is called once per frame
void Update()
{
UpdateRespawnMacaron(); //move
UpdateRespawnCheck(); //respawn
UpdateMerging();
UpdateDeadline();
}
void UpdateDeadline()
{
//데드라인 활성 코드.
if(0f < m_DeadlineTime)
{
m_DeadlineTime -= Time.deltaTime;
if(0f > m_DeadlineTime)
{
if(null != m_Deadline)
{
m_Deadline.OnOffCollider(true);
}
m_DeadlineTime = 0f;
}
}
//게임오버 확인 코드.
if(IsGameOver())
{
if(null != m_txtGameOver &&
false == m_txtGameOver.gameObject.activeSelf)
{
m_txtGameOver.gameObject.SetActive(true);
}
}
}
bool IsGameOver()
{
if(null != m_Deadline)
{
return m_Deadline.IsGameOver();
}
return false;
}
void UpdateMerging()
{
if (IsGameOver())
{
return;
}
//병합 후 사라지는 마카롱.
/*for(int i = 0; i < m_ListMacaron.Count; ++i)
{
if (null != m_ListMacaron[i])
{
if (m_ListMacaron[i].GetDestroy())
{
Destroy(m_ListMacaron[i].gameObject);
m_ListMacaron.RemoveAt(i);
break;
}
}
}*/
int safeCnt = 0;
bool isDeleted = true;
while (isDeleted &&
1000 > safeCnt)
{
safeCnt++;
isDeleted = false;
for(int i = 0; i <m_ListMacaron.Count; i++)
{
if(null != m_ListMacaron[i])
{
if (m_ListMacaron[i].GetDestroy())
{
Destroy(m_ListMacaron[i].gameObject);
m_ListMacaron.RemoveAt(i);
isDeleted = true;
break;
}
}
}
}
//머징 후 새로운 마카롱 생성.
for(int i = 0; i < m_ListMacaron.Count; ++i)
{
if(null != m_ListMacaron[i])
{
if (m_ListMacaron[i].GetMerging())
{
Vector3 pos = m_ListMacaron[i].transform.position;
Macaron macaron = RespawnMacaron(m_ListMacaron[i].GetLevel() + 1, true);
if(null != macaron)
{
macaron.transform.position = pos;
macaron.transform.localScale = Vector3.one * 0.1f;
Rigidbody2D rigid = macaron.GetComponent<Rigidbody2D>();
if(null != rigid)
{
rigid.gravityScale = 1f;
}
int addedScore = m_ListMacaron[i].GetLevel() + 1;
//m_Score += addedScore * addedScore;
m_Score += (int)Mathf.Pow(addedScore, 2);
RefreshUI();
}
m_RespawnMacaron = null;
Destroy(m_ListMacaron[i].gameObject);
m_ListMacaron.RemoveAt(i);
break;
}
}
}
}
void RefreshUI()
{
if(null != m_txtScore)
{
m_txtScore.text = m_Score.ToString();
}
}
void UpdateRespawnCheck()
{
if (IsGameOver())
{
return;
}
if (null == m_RespawnMacaron)
{
m_RespawnTime -= Time.deltaTime;
if (0f > m_RespawnTime)
{
RespawnMacaron(GetRespawnLevel(), false);
m_RespawnTime = RESPAWN_TIME;
}
}
}
int GetRespawnLevel()
{
int level = UnityEngine.Random.Range(1, m_HighLevel+1);
if(RESPAWN_HIGH_LEVEL < level)
{
level = RESPAWN_HIGH_LEVEL;
}
return level;
}
void UpdateRespawnMacaron()
{
if(IsGameOver())
{
return;
}
if(null != m_RespawnMacaron)
{
m_MouseClick = false;
m_MouseRelease = false;
if (Input.GetMouseButtonDown(0))
{
m_MouseClick = true;
}
else if(Input.GetMouseButton(0))
{
m_MouseClick = true;
}
if(Input.GetMouseButtonUp(0))
{
m_MouseRelease = true;
}
Vector3 wpos = Vector3.zero;
if(m_MouseClick)
{
if(null != m_txtMousePos)
{
m_txtMousePos.text = $"{Input.mousePosition}";
}
wpos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
if(null != m_RespawnMacaron)
{
wpos.y = m_RespawnMacaron.transform.position.y;
wpos.z = 0f;
m_RespawnMacaron.transform.position = wpos;
}
}
if (m_MouseRelease)
{
if(null != m_RespawnMacaron)
{
Rigidbody2D rigid = m_RespawnMacaron.GetComponent<Rigidbody2D>();
if(null != rigid)
{
rigid.gravityScale = 1f;
}
m_DeadlineTime = DEAD_TIME;
if(null != m_Deadline)
{
m_Deadline.OnOffCollider(false);
}
m_RespawnMacaron = null;
}
}
}
}
Macaron RespawnMacaron(int inLevel, bool isMerging)
{
inLevel = Mathf.Clamp(inLevel, 1, 13);
string macaronName = "Macaron";
if(10 > inLevel)
{
macaronName += "0" + inLevel.ToString();
}
else
{
macaronName += inLevel.ToString();
}
string prefabPath = "Prefabs/" + macaronName;
GameObject prefabObj = Resources.Load(prefabPath) as GameObject;
if(null != prefabObj)
{
GameObject inst = Instantiate(prefabObj);
if (null != inst)
{
inst.transform.parent = m_RespawnObj.transform;
inst.transform.localPosition = Vector3.zero;
if(isMerging)
{
Quaternion qRot = Quaternion.identity;
Vector3 vRot = qRot.eulerAngles;
vRot.z = UnityEngine.Random.Range(0, 360);
qRot.eulerAngles = vRot;
inst.transform.localRotation = qRot;
}
Rigidbody2D rigid = inst.GetComponent<Rigidbody2D>();
if(null != rigid)
{
rigid.gravityScale = 0f;
}
Macaron macaron = inst.GetComponent<Macaron>();
if(null != macaron)
{
macaron.SetLevel(inLevel);
}
m_ListMacaron.Add(macaron);
if (false == isMerging)
{
m_RespawnMacaron = inst;
}
if(inLevel > m_HighLevel)
{
m_HighLevel = inLevel;
}
return macaron;
}
}
return null;
}
}
Macaron 코드
더보기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Macaron : MonoBehaviour
{
int m_Level = 1;
bool m_Merging = false; //이 기준으로 머징할 것. -> 파괴
bool m_Destroy = false; //이 플래그면 파괴.
const float DEFAULT_SCALE = 4f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
UpdateScaling();
//UpdateJingle();
}
void UpdateJingle()
{
Vector3 vRot = transform.localRotation.eulerAngles;
vRot.z = UnityEngine.Random.Range(0, 20) - 10; //0~20 -> -10~10
Quaternion qRot = Quaternion.identity;
qRot.eulerAngles = vRot * Time.deltaTime;
transform.localRotation = qRot;
}
void UpdateScaling()
{
Vector3 scale = transform.localScale;
if (DEFAULT_SCALE > scale.x)
{
scale.x += Time.deltaTime * 10f;
if (DEFAULT_SCALE < scale.x)
{
scale.x = DEFAULT_SCALE;
}
}
if (DEFAULT_SCALE > scale.y)
{
scale.y += Time.deltaTime * 10f;
if (DEFAULT_SCALE < scale.y)
{
scale.y = DEFAULT_SCALE;
}
}
if (DEFAULT_SCALE > scale.z)
{
scale.z += Time.deltaTime * 10f;
if (DEFAULT_SCALE < scale.z)
{
scale.z = DEFAULT_SCALE;
}
}
transform.localScale = scale;
}
//private void OnCollisionEnter(Collision collision) <- 오류
private void OnCollisionEnter2D(Collision2D collision)
{
if (null == collision ||
null == collision.collider)
{
return;
}
if(GetDestroy() ||
GetMerging())
{
return;
}
Macaron macaron = collision.collider.gameObject.GetComponent<Macaron>();
if (null != macaron)
{
if(macaron.GetMerging() ||
macaron.GetDestroy())
{
//pass
}
else if(macaron.GetLevel() == GetLevel())
{
Vector3 pos = macaron.transform.position;
if(transform.position.y >= pos.y)
{
SetMerging(true);
macaron.SetDestroy(true);
}
else
{
macaron.SetMerging(true);
SetDestroy(true);
}
}
}
}
public void SetLevel(int inLevel)
{
m_Level = inLevel;
}
public int GetLevel()
{
return m_Level;
}
public void SetMerging(bool inMerging)
{
m_Merging = inMerging;
}
public bool GetMerging()
{
return m_Merging;
}
public void SetDestroy(bool inDestroy)
{
m_Destroy = inDestroy;
}
public bool GetDestroy()
{
return m_Destroy;
}
}
Deadline 코드
더보기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Deadline : MonoBehaviour
{
BoxCollider2D m_Collider = null;
bool m_GameOver = false;
// Start is called before the first frame update
void Start()
{
m_Collider = GetComponent<BoxCollider2D>();
OnOffCollider(false);
}
public void OnOffCollider(bool inOn)
{
if(null != m_Collider)
{
m_Collider.enabled = inOn;
}
}
// Update is called once per frame
void Update()
{
}
private void OnCollisionEnter2D(Collision2D collision)
{
if(null != collision)
{
Macaron macaron = collision.gameObject.GetComponent<Macaron>();
if(null != macaron)
{
m_GameOver = true;
}
}
}
public bool IsGameOver()
{
return m_GameOver;
}
}
FPS 형식의 미로탈출 게임 기획
미로 컨텐츠 만들기
미로는 2개 이상의 위치가 있고 랜덤한 시작점과 탈출점을 부여
탈출점 도달 시 다음 미로로 도달
1인칭 게임 기반 기술
미로 만들기 재밌당 ㅎ
'공부의 기록 > 유니티 게임프로그래밍 입문' 카테고리의 다른 글
유니티(Unity) 게임프로그래밍 입문 6일차 수업 (1) | 2024.12.15 |
---|---|
유니티(Unity) 게임프로그래밍 입문 4일차 수업 (0) | 2024.12.01 |
유니티(Unity) 게임프로그래밍 입문 3일차 수업 (1) | 2024.11.24 |
유니티(Unity) 게임프로그래밍 입문 2일차 수업 (0) | 2024.11.17 |
유니티(Unity) 게임프로그래밍 입문 1일차 수업 (4) | 2024.11.10 |