[Unity] Project. fall_4

Lingtea_luv·2025년 4월 30일

Project

목록 보기
13/38
post-thumbnail

Project. fall


4/30 작업 내역

  1. 인게임, 게임 종료, 게임 클리어 UI 기능 구현
  2. 게임 시작 Scene 제작, 기능 담당 매니저 스크립트 작성
  3. 환경 설정 - 볼륨, 밝기 조절 기능 구현
  4. 플레이어 잡기, 벽타기 기능 구현
  5. 카메라 줌인,아웃 기능 추가

UI

InGame

인게임 내에서 플레이 시간과 물까지 남은 거리를 표시할 수 있도록 스크립트를 작성하고 이를 각각의 UI에 컴포넌트로 넣어 필드를 인스펙터로 연결했다.

public class HeightCalculate : MonoBehaviour
{
    [SerializeField] private TextMeshProUGUI heightText;
    [SerializeField] private Transform playerTrans;
    [SerializeField] private Transform waterTrans;
    
    private void Update()
    {
        float height = playerTrans.position.y - waterTrans.position.y;
        heightText.text = $"Height : {height:00.0}m";
    }
}

TextMeshPro를 사용할 경우 TextMeshProUGUI 클래스로 인스펙터에서 연결하는 것이 가능하다. Update()에서 할당한 변수 height.text로 매 프레임 변동되는 높이가 출력되도록 만들었다.

GameOver

플레이어가 물에 닿아 게임오버가 될 경우 화면이 Fade-Out되면서 게임오버 UI가 출력되도록 구현했다.

public class FadeOutPanel : MonoBehaviour
{
    [SerializeField] private Image fadeOutPanel;
    [SerializeField] private TextMeshProUGUI gameOverText;
    [SerializeField] private TextMeshProUGUI restartBtnText;
    [SerializeField] private TextMeshProUGUI exitBtnText;
    
    [SerializeField] private float fadeDuration = 1f;
    
    private void Start()
    {
        gameObject.SetActive(false);
    }
    
    // 외부에서 호출이 가능하도록 public으로 설정
    public void GameOver()
    {
        StartCoroutine(FadeIn());
    }

	// 화면이 암전되면서 GameOver UI가 출력되도록 코루틴으로 구현
    private IEnumerator FadeIn()
    {
        Color fadeColor = fadeOutPanel.color;
        fadeColor.a = 0;
        fadeOutPanel.color = fadeColor;

        Color textColor = gameOverText.color;
        textColor.a = 0;
        gameOverText.color = textColor;
        
        Color btnColor = restartBtnText.color;
        btnColor.a = 0;
        restartBtnText.color = btnColor;
        
        float timer = 0f;
        
        // 배경이 비치도록 이미지의 알파값을 0.95로 설정
        while (timer < fadeDuration * 0.95f)
        {
            timer += Time.deltaTime;
            fadeColor.a = Mathf.Clamp01(timer / fadeDuration);
            fadeOutPanel.color = fadeColor;
            textColor.a = Mathf.Clamp01(timer * 0.95f / fadeDuration);
            gameOverText.color = textColor;
            btnColor.a = Mathf.Clamp01(timer * 0.95f / fadeDuration);
            restartBtnText.color = btnColor;
            exitBtnText.color = btnColor;
            yield return null;
        }
    }
}

GameClear

결승선을 통과하여 게임을 통과한 경우 SceneManager 을 통해 씬 전환을 할 수 있도록 하고, UI 요소를 ClearScene에 추가하였다.

public class SceneManager : MonoBehaviour 
{
    private static SceneManager instance;
    public static SceneManager Inst 
    {
        get 
        {
            if (instance == null) 
            {
                instance = FindObjectOfType<SceneManager>();

                if (instance == null) 
                {
                    GameObject obj = new GameObject(nameof(SceneManager));
                    instance = obj.AddComponent<SceneManager>();
                    DontDestroyOnLoad(obj);
                }
            }
            return instance;
        }
    }
  
    private void Awake() 
    {
        if (instance == null) 
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else if (instance != this) 
        {
            Destroy(gameObject);
        }
    
    public void LoadScene(string sceneName) 
    {
        UnityEngine.SceneManagement.SceneManager.LoadScene(sceneName);
    }

    public void LoadMainScene() 
    {
        LoadScene("TestScene");
    }

    public void LoadIngameScene() 
    {
        LoadScene("Ingame");
    }
}

SceneManager는 싱글톤을 활용하여 구현했고, LoadScene 관련 메서드를 public으로 선언하여 전역에서 씬 전환이 가능하도록 했다.

Camera

위 아래 카메라 이동을 추가하니 너무 어지러워서 좌우 이동만 남긴 뒤, 카메라의 위치를 살짝 조정하여 플레이어 머리 뒤에 위치하도록 구현했다.
줌인, 줌아웃의 경우 z필드를 추가하여 마우스 휠로 조작될 수 있도록 소스코드 추가 예정.

public class CameraControllerLSW : MonoBehaviour
{
    [SerializeField] Transform target;      // 따라갈 플레이어
    [SerializeField] Vector3 offset = new Vector3(0f, 2f, -5f); // 카메라 초기 위치
    [SerializeField][Range(5, 20)] float rotateSpeed = 5f;     // 마우스 회전 속도 초기값
    [SerializeField][Range(5, 20)] float followSpeed = 10f;      // 플레이어 따라가는 속도 초기값
    private float curRotationX = 10f;     // 현재 X축위치 초기화
    private float curRotationY = 0f;     // 현재 Y축위치 초기화
    
    private void Update()
    {
        CameraMoveInput();
    }

    // 플레이어가 움직이고 나서 카메라로 확인해야 해서 LateUpdate에서 구현
    private void LateUpdate()
    {
        CameraMove();
    }

    // 카메라 위치 입력
    private void CameraMoveInput()
    {
        // 마우스 커서의 위치로 카메라 회전
        float mouseMoveX = Input.GetAxis("Mouse X");
        float mouseMoveY = Input.GetAxis("Mouse Y");
        
        curRotationY += mouseMoveX * rotateSpeed;
        curRotationX -= mouseMoveY * rotateSpeed;
    }
    // 카메라 움직임
    private void CameraMove()
    {
        // 플레이어 위치 + 오프셋 (카메라 X, Y축)
        // X축 이동 마우스 방향으로 카메라 쳐다보게
        Quaternion rotation = Quaternion.Euler(0, curRotationY, 0);
        Vector3 movePosition = target.position + rotation * offset;
        // 부드럽게 이동 (Lerp 사용)
        transform.position = Vector3.Lerp(transform.position, movePosition, followSpeed * Time.deltaTime);
        // 항상 카메라 방향이 위에서 플레이어로
        transform.LookAt(target.position + Vector3.up * 2f); 
    }
}
profile
뚠뚠뚠뚠

0개의 댓글