티스토리 뷰

반응형

이번 게임은 유명한 모바일 게임 Hill Climb Racing 입니다.😊

옛날에 즐겨 했었던 기억에 만들어보았습니다.

 

 

 

 

 


 

맵 

맵은 Sprite Shape로 만들어서 프리팹으로 생성하였습니다.

차량도 프리팹으로 생성하였습니다.

 

 

 

 

 

 

차량

차량의 하위 오브젝트에 바퀴 두개가 있는데, Wheel Joint2D 컴포넌트를 추가하여 사용합니다.

컴포넌트의 Connected Rigidbody 는 차량의 리지드 바디를 할당합니다.

Suspension을 조정하여 차량이 빠르고 가벼운 느낌으로 바꿀 수 있습니다.

또한 차량의 리지드바디와 두 바퀴의 리지드바디의 요소들을 조정하여 원하는 무게와 속도로 조정할 수 있습니다.

 

 

 

 

 

엔진/브레이크 버튼을 누르면 위의 인스펙터에서 Use Motor를 이용해서 차량이 움직이도록 할 것입니다.

아래 코드는 차량 오브젝트의 코드입니다.

 private void Update() {
        //PC : movement = Input.GetAxis("Horizontal");
        //엔진 버튼 누를 시
        if(GameManager.Instance.GasBtnPressed) {
            movement += 0.009f;
            if(movement > 1f)
                movement = 1f;
        }

        //브레이크 버튼 누를 시
        else if(GameManager.Instance.BrakeBtnPressed) {
            movement -= 0.009f;
            if(movement < -1f)
                movement = -1f;
        }

        //아무 버튼도 누르지 않을 시
        else if(!GameManager.Instance.GasBtnPressed && !GameManager.Instance.BrakeBtnPressed) {
            movement = 0;
        }
        moveSpeed = movement * speed;

        GameManager.Instance.FuelConsume();  //연료 소모에 따라 여러가지를 갱신
    }


    private void FixedUpdate() {
        transform.position = new Vector3(Mathf.Clamp(transform.position.x, StartPos.x, transform.position.x), transform.position.y);

        if(moveSpeed.Equals(0) || fuel <= 0) {   //버튼을 누르지 않거나 연료가 없을 경우 차를 멈춤
            frontTire.useMotor = false;
            backTire.useMotor = false;
        }
        else {
            frontTire.useMotor = true;
            backTire.useMotor = true;
            JointMotor2D motor = new JointMotor2D();
            motor.motorSpeed = moveSpeed;
            motor.maxMotorTorque = 10000;
            frontTire.motor = motor;
            backTire.motor = motor;
        }

        //게임 오버 시에 차량 속도 0으로
        if(GameManager.Instance.isDie && moveStop) {
            GetComponent<Rigidbody2D>().velocity = new Vector2(0, 0);
        }

        //움직이는 만큼 계속해서 연료 소비
        fuel -= fuelConsumption * Mathf.Abs(movement) * Time.fixedDeltaTime;
    }

 

 

 

 

 

 

 

 

운전자

차량에 타고 있는 사람의 머리 오브젝트에는 Hinge Joint2D 를 사용하여 흔들림을 표현하였습니다.

그리고 머리 위에 오브젝트를 하나 만들어서 콜라이더를 추가하였습니다.

차가 뒤집어졌을 때, 맵과 닿는지를 확인하기 위함 입니다.

스크립트를 하나 만들어서 OnTriggerEnter2D 함수를 이용하여 맵과 닿는지를 확인하고 게임 오버 여부를 결정합니다.

 

 

 

 

 

 

 

카메라

다음은 카메라 세팅입니다.

카메라는 계속해서 차량을 따라다니도록 해야합니다. 

그래서 게임 내내, 차량과 카메라의 위치 차이만큼 차량에 더한 것을 카메라의 위치로 지정합니다. 

카메라 오브젝트의 코드는 다음과 같습니다.

using UnityEngine;

public class CameraController : MonoBehaviour {
    public Transform vehiclePos;
    private Vector3 offset;

    //게임 시작 시에 차량 위치와 카메라 세팅
    public void SetUp() {
        vehiclePos.position = new Vector3(Camera.main.ViewportToWorldPoint(new Vector3(0, 0)).x + 3f, vehiclePos.position.y, 0);
        CarController carController = vehiclePos.gameObject.GetComponent<CarController>();
        carController.StartPos = vehiclePos.position;
        offset = transform.position - vehiclePos.position;
    }

    private void Update() {
        //카메라가 차량을 따라다님
        transform.position = vehiclePos.position + offset;
    }
}

 

 

 

 

 

 

연료

다음은 GameManager 오브젝트를 만들고 스크립트를 추가합니다.

일단, UI에서 차량이 움직일수록 연료 게이지가 줄어들도록 합니다.

이는 Image에서 Image type 을 filled로 지정하고 fillAmout 값을 조정하면 됩니다.

 

위에서 봤던 차량 스크립트에서 계속해서 GameManager의 FuelConsume 함수를 호출하는 것을 볼 수 있습니다.

//연료 소비 함수
    public void FuelConsume() {
        fuelGauge.fillAmount = carController.Fuel;  //움직일수록 연료 게이지를 줄어들게한다.
        if(fuelGauge.fillAmount <= 0.6f) {  //연료 게이지 색깔 조정
            fuelGauge.color = new Color(1, fuelGauge.fillAmount * 0.8f * 2f, 0, 1);  //게이지가 줄어들수록 그라데이션 효과
            
            if(fuelGauge.fillAmount <= 0.3f) {  //연료 부족 경고 애니메이션
                fuelWarning.SetActive(true);
                if(fuelGauge.fillAmount == 0f)  //연료가 다 떨어져서 게임 오버
                    StartGameOver();
            }
        }
        else {
            fuelGauge.color = new Color((1f - fuelGauge.fillAmount) * 2f, 1, 0, 1);  
            fuelWarning.SetActive(false);
        }
    }

움직일수록 fillAmout 값이 줄어들고, 그라데이션 효과도 넣었습니다.

연료가 일정 수 보다 낮아지면 연료가 부족하다는 경고 애니메이션을 재생합니다.

연료가 다 떨어지면 게임 오버가 됩니다.

 

 

연료는 맵 중간 중간에 위치하여 연료를 획득하면, 게이지가 다시 꽉차게 합니다.

연료도 콜라이더 컴포넌트를 가지고 있고, 스크립트의 OnTrigger2D를 통해 차량과 충돌할 경우로 획득을 구분합니다.

 

 

 

 

 

 

 

 

 

게임 내내 맵 중간중간에 계속해서 코인이 위치합니다.

코인도 콜라이더가 있고, 코인과 차량이 충돌할 경우를 OnTrigger2D 함수에서 획득으로 구분합니다.

돈은 PlayerPrefs로 저장/로드를 통해 데이터로 관리합니다. 

이 돈으로 메인메뉴에서 원하는 맵과 차량을 살 수 있습니다.

 

 

 

 

 

 

 

게임오버

연료가 다 떨어질경우 / 차량이 뒤집어져 머리가 맵에 닿을 경우

이 두가지 경우에 게임오버가 됩니다. 게임오버가 되면 게임오버 UI가 나타나고,

해당 게임에서 얻었던 코인의 수, 도달한 거리와 함께 게임오버 당시의 차량 모습이 캡쳐되어 나타납니다.

 

 

 

GameManager 스크립트의 GameOver 코루틴 함수에서 이를 작성했습니다.

다음 코드가 그 부분입니다.

//게임 오버 시 차량의 모습을 스크린샷하여 UI 이미지로 보여줌
yield return new WaitForEndOfFrame();
Texture2D text = new Texture2D(Screen.width / 5, Screen.height / 3, TextureFormat.RGB24, false);
textureImg = new Texture2D(Screen.width / 5, Screen.height / 3);
text.ReadPixels(new Rect(-Screen.width / 2, Screen.height / 3 + 15f, Screen.width, Screen.height), 0, 0);
text.Apply();
textureImg = text;
spriteImg = Sprite.Create(textureImg, new Rect(0, 0, textureImg.width, textureImg.height), new Vector2(0, 0));
captureImg.sprite = spriteImg;

 

 

 

 

 

 

 

 

 

메인메뉴

메인메뉴에는 스크롤 뷰로 맵(스테이지)/차량을 나타냅니다.

여러가지 종류의 맵과 차량이있고, 아직 구입을 하지 못한 것은 잠금이 되어있습니다.

잠금 여부 또한 데이터로 관리됩니다.

 

써있는 맵/차량의 액수 만큼 지불하여 구매할 수 있습니다.

맵과 차량을 잠금해제되있는 것으로 적절히 선택한 후에 시작 버튼을 눌러야 게임을 시작할 수 있습니다.

여기서 선택하고 시작된 게임(넘어간 다음 씬)에서 선택되었던 맵과 차량을 프리팹으로 생성합니다. 

 

 

 

 

 


 

 

GitHub

자세한 내용은 GitHub의 코드를 참고하여주세요.

https://github.com/choijoohee213/HillClimbRacing

 

choijoohee213/HillClimbRacing

Made Hill Climb Racing With Unity. Contribute to choijoohee213/HillClimbRacing development by creating an account on GitHub.

github.com

 

 

 

 

게임 실행 영상

유튜브 실행 영상입니다.

 

 

 

 

 

 

 

읽어주셔서 감사합니다. 🥰

반응형
댓글
반응형
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday