2025 Unity 6 Challenge

원래는 이대로 끝내려고 했는데, 튜토리얼만 따라가기엔 너무 심심해서 조금 변형해 보았음

기존의 튜토리얼에서 변형시키기

a, d 또는 왼쪽 방향키, 오른쪽 방향키로 직접 횡이동 가능하게 하기

// Player.cs
...
if(Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.LeftArrow)) {
            transform.position += Vector3.left * moveSpeed * Time.deltaTime;
        }
        if(Input.GetKeyDown(KeyCode.D) || Input.GetKeyDown(KeyCode.RightArrow)) {
            transform.position += Vector3.right * moveSpeed * Time.deltaTime;
        }
  • 이렇게 했더니 안됨.. 되게 이상하게 움직임
  • 그래서 다른 방법을 찾아봄
  • https://torotoblog.tistory.com/81
  • 트랜스폼을 직접 바꾸는게 아니고 리지드바디의 속력을 바꿔야 하는 듯
  • Input Manager에서 Axis에 horizontal이 A, D와 왼쪽/오른쪽 방향키를 인식하도록 하고 따라해봄
void Update()
    {
        if(Input.GetKeyDown(KeyCode.Space) && isGrounded){
            playerRigidBody.AddForceY(jumpForce, ForceMode2D.Impulse);
            isGrounded = false;
            playerAnimator.SetInteger("state", 1);
        }
        Vector2 moveInput = new Vector2(Input.GetAxisRaw("Horizontal"));
        moveVelocity = moveInput.normalized * moveSpeed;
        playerRigidBody.MovePosition(playerRigidBody.position + moveVelocity * Time.deltaTime);
    }
  • Vector2.normalized가 뭔가 봤더니, 벡터 값을 정규화 하는데 쓰인다고 함. 이게 없으면 대각선 이동에서 속도가 갑자기 증가함
  • 근데 이렇게 했을 때 캐릭터가 이상하게 뛰는 애니메이션을 취하고 있음
  • 이번에 MovePosition 말고 AddForce를 해보기로 함
void Update()
    {
        if(Input.GetKeyDown(KeyCode.Space) && isGrounded){
            playerRigidBody.AddForceY(jumpForce, ForceMode2D.Impulse);
            isGrounded = false;
            playerAnimator.SetInteger("state", 1);
        }
        playerRigidBody.AddForceX(moveSpeed * Input.GetAxis("Horizontal"), ForceMode2D.Force);
        // force는 지속적으로 힘을 주기 때문에 사용함
        
    }
void Update()
    {
        if(Input.GetKeyDown(KeyCode.Space) && isGrounded){
            playerRigidBody.AddForceY(jumpForce, ForceMode2D.Impulse);
            isGrounded = false;
            playerAnimator.SetInteger("state", 1);
        }
        playerRigidBody.AddForceX(moveForce * Input.GetAxis("Horizontal"), ForceMode2D.Force);
        // TODO : 최대 속도 제한하기
        if(playerRigidBody.linearVelocityX > maxMoveSpeed)
        {
            playerRigidBody.linearVelocityX = maxMoveSpeed;
        }
        else if(playerRigidBody.linearVelocityX < -maxMoveSpeed)
        {
            playerRigidBody.linearVelocityX = -maxMoveSpeed;
        }
        
    }

특정 키를 누르면 칼을 휘두르기

  • 칼 도트 찍기
  • 칼 애니메이션을 드래그&드롭으로 씬에 추가
  • 플레이어의 자식 오브젝트로 두고 위치를 플레이어의 우상단으로 조정
  • Input Manager에서, Fire Axis 추가하고 left shift와 마우스 왼쪽 클릭으로 가능하게 함
  • Player.cs 코드에서, Fire Axis Input이 있을 때 칼 오브젝트를 소환
 			 	if(Input.GetAxis("Fire") > 0) {
            knife.SetActive(true); // 위에 public GameObject knife로 받아옴
        }
	 	public void EndSwing(){
        gameObject.SetActive(false);
    }
  • knife.cs 상단에 Animator를 public으로 받아오게 하고, 나머지는 연결

  • 성공!

칼을 휘둘러야만 배추, 고추, 마늘을 얻을 수 있게 하기

  • 가장 먼저, 칼에 박스 콜라이더를 추가하고 설정해 줌
  • 원래 player.cs에 있던 충돌 감지 부분을 knife로 옮겨줌 (음식 부분만!)
  • 힐 부분을 빼버림 (나중에 힐 감지는 따로 음식 모아서 하게 할거라)
  • 성공!

배추, 고추, 마늘을 모두 얻어 김치를 만들면 생명력을 회복할 수 있게 하기

  • 게임 매니저가 배추, 고추, 마늘의 수집 여부를 파악하게 함
  • 현재 어떤 재료를 수집했는지 체력 바 밑에 보이게 하기 위해, 스프라이트를 미리 씬에 추가함
  • 이후에 금배추를 포함해서 만들면 5초 무적으로 만들 예정임
  • 배추, 고추, 마늘 수집 여부를 bool list로 관리하고, 금배추를 먹은 경우 hasGoldBaechu로 따로 검사할 예정
  • Food.cs에 다음을 작성
public class Food : MonoBehaviour
{
    public int foodIndex;
}
  • Hit과 Heal을 게임 매니저가 관리하도록 변경함
    private bool[] goldenFoodList; // 혹시나 모를 다른 금 음식 추가를 위해..
    ...
    
    
    public void GetFood(int foodIndex, bool isGolden) {
        foodList[foodIndex] = true;
        if(isGolden){
            goldenFoodList[foodIndex] = true;
            goldenFoodObjects[foodIndex].gameObject.SetActive(true);
        } else{ // 금 음식이 있으면 그게 우선적으로 보이게 하려고 했음
            if(!goldenFoodList[foodIndex]){
                foodObjects[foodIndex].gameObject.SetActive(true);
            }
        }
        CheckFood();
    }
 
    void CheckFood() {
        foreach (bool item in foodList)
        {
            if (!item) return; // 하나라도 false가 있으면 return 될 것임
        }
        Heal();
        if (goldenFoodList[(int)Foods.Baechu])
        {
            playerScript.StartInvincible();
        }
        // 음식들 비활성화 하기
        Array.Clear(foodList, 0, foodList.Length); // 논리적
        
        foreach (GameObject items in foodObjects){  // 물리적 (Scene 안에서 보여지는)
            items.SetActive(false);
        }
        foreach (GameObject items in goldenFoodObjects)
        {
            items.SetActive(false);
        }
    }
  • 음식을 얻는 부분과 얻고 나서 체크하는 부분을 나눔
  • 일반 음식 오브젝트 리스트와 금 음식 오브젝트 리스트로 나눠서 소환하게 함

픽셀 애니메이션으로 무적인거 티내기

  • 칼도 그렇고 이 불도 아래의 사이트에서 직접 찍어봤음

https://www.piskelapp.com/p/create/sprite

  • 하이어라키에 추가하고 PPU 조절 후 player 오브젝트 자식으로 둠. 기본값 비활성화로 해둠
  • Player.cs 코드 상에서 invincible을 판단하기 때문에, 코드에서 이펙트 참조하게 함
    public void StartInvincible() {
        isInvincible = true;
        invincibleEffect.SetActive(true);
        Invoke("StopInvincible", 5f);
    }
 
    void StopInvincible() {
        invincibleEffect.SetActive(false);
        isInvincible = false;
    }
  • 성공!

UI 일부 수정하기

  • 죽은 뒤에는 HighScore를 화면 중앙에 표시하도록 변경함
  • 우상단에 조작법을 추가함

배포

  • Files → Build Profiles → Web → Switch Platform
  • Windows → Package Manager → WebGL Publisher 설치
  • 상단에 Publish → WebGL Project → Get Started → Build and Publish → 폴더 선택하면 빌드 끝