5주차 숙제 게임개발
Run & Jump - 프로토타입 설명
1.마우스를 누르면 캐릭터 머리 위에 파워 게이지가 표시됨
2.마우스를 놓으면 놓은 방향으로 캐릭터가 빙글빙글 돌아가며 발판들을 넘어감
3.이미 한번 착지한 발판은 점수 x , 발판을 처음 밟을때만 점수 증가
구현 해야될것
1.각종 플레이어의 플레이를 방해할 장애물 추가 필요(화면을 날라다니는 오브젝트,발판 위의 가시 등등)
2.날라오는 블럭들이 지금 완전 랜덤 범위라서, 규격화가 필요함 ( 블럭이 겹쳐서 나오면 캐릭터가 피할 곳이 없음)
오늘 구현한것
1.게임에서 Player들이 획득하는 아이템(Coin)추가
2.Player의 게임플레이를 방해할 Spikes(가시) 추가 , 가시에 닿게되면 캐릭터가 죽음(Dead) 처리 됨
3.밑에 버그 수정
버그 수정
1. 자기 발 밑에 바닥이 있는 상태로 아래를 향해 발사하면 캐릭터
착지하지 못한 판정이 되서 조작이 불가함
Player.cs
private void PlayerStop()
{
isJump = false;
isJumping = false;
rigid.velocity = Vector2.zero;
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Block"))
{
PlayerStop();
anim.SetBool("isJump", false);
}
if (collision.gameObject.CompareTag("Spike"))
{
Debug.Log("Player 가시 닿음");
isdead = true;
anim.SetBool("isDead", true);
PlayerStop();
}
}
Player.cs 있는 CollisonEnter2D 메서드 내의 "Block"태그 의 PlayerStop() 메서드가 동작해야되는데
Block 위에서만 발사 하면 CollisonEnter2D가 동작을 하지 않는것이다. 그렇다고 Stay함수를 쓰면 로직이 꼬이기 시작하였다.
Player.cs
void Update()
{
if (!isdead)
{
anim.SetBool("isRun", false);
if (!isJump && !isJumping)
{
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
{
transform.position += Vector3.right * speed * Time.deltaTime;
renderer.flipX = true;
anim.SetBool("isRun", true);
}
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
transform.position += Vector3.left * speed * Time.deltaTime;
renderer.flipX = false;
anim.SetBool("isRun", true);
}
if (Input.GetMouseButton(0) || Input.GetKeyDown(KeyCode.Space))
{
isJump = true;
JumpArrow.JumpArrowPrint(transform.position);
JumpPower.JumpPowerPrint(transform.position);
anim.SetBool("isRun", false);
}
}
if (isJump && !isJumping)
{
if (Input.GetMouseButtonUp(0) || Input.GetKeyUp(KeyCode.Space))
{
isJumping = true;
anim.SetBool("isJump", true);
Vector2 PlayerPos = transform.position;
Vector2 dir = JumpArrow.GetJumpingDir() - PlayerPos;
dir.Normalize();
float power = JumpPower.GetJumpingPower();
Debug.Log("발사 방향" + dir);
Debug.Log("발사 파워" + power);
rigid.AddForce(dir * power, ForceMode2D.Impulse);
JumpArrow.JumpArrowOff();
JumpPower.JumpPowerOff();
//제자리 구르기 or 밑에 방향으로 발사 시에
//블럭이 있으면 멈추지 않는 현상을
//콜리더를 껏다가 바로 켜는형식으로 변경
collider.enabled = false;
Invoke("ColliderON", 0.05f);
}
}
}
}
Player 오브젝트 객체가 발사하여 날라갈때 , Player의 Collider를 껏다 켜는걸로 해결하였다.
발사해서 공중에 날라갈떄 Collider를 껏다가 0.05f 후에 Collider를 다시 켜서 충돌처리를 하게 하였다.
Collider를 껏다 다시 켜니 위에 있던 CollisonEnter2D가 동작이 되어서 정상적으로 처리 되었다.
2.재시작(Scene 재로드)를 하면 GameManager의 오브젝트들이 Mssing되어버림
GameManager.cs
[SerializeField] GameObject block;
[SerializeField] Text scoreTxt;
[SerializeField] Text levelTxt;
[SerializeField] float blockSummonCoolTime = 2.0f;
[SerializeField] bool isstop = false;
int totalscore = 0;
int curLevel = 0;
private void UI_Load()
{
// 씬 전환 시 매번 호출하여 최신 오브젝트 참조를 설정합니다.
if (scoreTxt == null)
{
GameObject scoreObj = GameObject.Find("UI_Score");
if (scoreObj != null)
{
scoreTxt = scoreObj.GetComponent<Text>();
}
}
if (levelTxt == null)
{
GameObject levelObj = GameObject.Find("UI_Level");
if (levelObj != null)
{
levelTxt = levelObj.GetComponent<Text>();
}
}
}
private void OnEnable()
{
UnityEngine.SceneManagement.SceneManager.sceneLoaded += OnSceneLoaded;
}
private void OnDisable()
{
UnityEngine.SceneManagement.SceneManager.sceneLoaded -= OnSceneLoaded;
}
private void OnSceneLoaded(UnityEngine.SceneManagement.Scene scene, UnityEngine.SceneManagement.LoadSceneMode mode)
{
// 씬이 로드된 후 UI 로드
UI_Load();
}
GameManager를 싱글톤으로 구성하고 DontDestroyOnLoad()를 이용하여 Scene 파괴를 막았는데 오브젝트가 Missing이 되었다.
원인 :
1.Scene은 Load씨에 하이어라키에 있는 오브젝트들은 전부 제거된다.
2.DontDestroyOnLoad() 실행 시, GameManager는 파괴되지 않더라도 다른 오브젝트들이 터졌다가 다시 생성되는것이기에 Missing이 됨
3.Inspector에서 참조한 경우 자동으로 참조하지 못하기에 직접 스크립트에서 참조 해줄수 있게 해줘야함
private void UI_Load()
{
// 씬 전환 시 매번 호출하여 최신 오브젝트 참조를 설정합니다.
if (scoreTxt == null)
{
GameObject scoreObj = GameObject.Find("UI_Score");
if (scoreObj != null)
{
scoreTxt = scoreObj.GetComponent<Text>();
}
}
if (levelTxt == null)
{
GameObject levelObj = GameObject.Find("UI_Level");
if (levelObj != null)
{
levelTxt = levelObj.GetComponent<Text>();
}
}
}
해당 코드를 통해서 null 인경우 새 GameObject를 만들고 하이어라키에 존재하는 오브젝트를 찾아 초기화 해준뒤
Text 컴포넌트를 추가해주었다.
하지만 위에 코드만으로는 Scene 로드 할떄마다 오브젝트를 원하는 타이밍에 넣어 줄 수가 없었다.
** Awake vs OnEnable vs Start **
게임 오브젝트가 활성화된 상태로 씬에 처음 로드되면:
- Awake called: 오브젝트가 씬에 로드되면서 호출됨.
- OnEnable called: 오브젝트가 활성화되면서 호출됨.
- Start called: Awake가 끝나고 오브젝트가 활성화된 상태이므로 Start가 호출됨.
만약 오브젝트를 비활성화했다가 다시 활성화하면:
- OnDisable called: 오브젝트가 비활성화될 때 호출됨.
- OnEnable called: 오브젝트가 다시 활성화될 때 호출됨.
따라서 Awake는 오브젝트의 초기 설정을 위한 함수로, 활성화 여부에 관계없이 한 번만 호출되는 반면, OnEnable은 활성화될 때마다 호출됩니다.
새로운 씬이 로드되어도 이 오브젝트는 파괴되지 않으므로, Awake와 Start 함수가 다시 호출되지 않습니다.
이 내용대로 동작 하는 경우면 GameManager는 계속 살아있기에 Awake()와 Start()는 호출이 되지 않기에
OnEnable(),OnDisable() 함수를 활용해야한다.
OnEnable(),OnDisable()을 활용하여 게임매니저가 활성화/비활성화 될때마다
Scene을 Load할때 동작하는 Event 함수를 만들어서 동작하였다.
'내일배움캠프_Unity_6기 > TIL(Today I Learend)' 카테고리의 다른 글
TIL : 2024-08-27(화) (0) | 2024.08.27 |
---|---|
TIL : 2024-08-26(월) (0) | 2024.08.26 |
TIL :: 2024-08-22(목) (0) | 2024.08.22 |
TIL : 2024-08-21(수) (0) | 2024.08.21 |
TIL : 2024-08-20(화) ::C# Linq.OrderBy() 정렬 알고리즘 ,랜덤으로 원소 섞기(셔플기능) , 광고붙이기(UnityAD) (0) | 2024.08.20 |