카테고리 없음

2025.05.12 6주차 월요일

mochoa 2025. 5. 12. 21:05

오늘의 학습 키워드

1. 필수과제 진행

 

코드를 대충 다 마무리 했다.

내가 한 부분인 GameManager

using UnityEngine.SceneManagement;
using UnityEngine;
using System.IO;

public class GameManager : MonoBehaviour
{
    private readonly string dataPath = "Data";
    public int BestScore { get; private set; }

    public static GameManager Instance;

    private bool isGameOver = false;
    private float timeSinceLastDifficultyIncrease = 0f;
    private PlayerController player;

    [Header("난이도 설정")]
    public float difficultyIncreaseInterval = 10f; // 난이도 상승 주기
    public float obstacleSpawnRate = 2f; // 초기 스폰간격 (초)
    public float obstacleSpeed = 5f; // 초기 장애물 속도
    public float playerGodMode = 1f; // 초기 무적 시간 (초)

    [Header("난이도 변화량")]
    public float spawnRateDecrease = 0.1f;
    public float speedIncrease = 0.5f;
    public float playerGodModeDecrease = 0.05f;

    public int coinCount = 0;
    public int score = 0;
    private UIManager uiManager;
    //UI 매니저 생성후 연결해주세요

    public class ScoreData
    {
        public int bestScore;
    }

    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
        }
        else Destroy(gameObject);

        uiManager = FindObjectOfType<UIManager>();
    }

    private void Start()
    {
        player = FindObjectOfType<PlayerController>();
        LoadBestScore();
        uiManager.UpdateScore(0, 0);

        if (player != null)
            player.ActivateGodMode(playerGodMode); // 무적 모드 적용
    }

    private void Update()
    {
        timeSinceLastDifficultyIncrease += Time.deltaTime;

        if (timeSinceLastDifficultyIncrease >= difficultyIncreaseInterval)
        {
            IncreaseDifficulty();
            timeSinceLastDifficultyIncrease = 0f;
        }
    }

    private void IncreaseDifficulty()
    {
        //스폰 간격 줄임. 근데 최소값보장
        obstacleSpawnRate = Mathf.Max(0.5f, obstacleSpawnRate - spawnRateDecrease);
        // 속도는 계속 증가 가능
        obstacleSpeed += speedIncrease;
        // 무적시간은 너무낮아지지않게 최소값보장.
        playerGodMode = Mathf.Max(0.3f, playerGodMode - playerGodModeDecrease);

        if (player != null)
        {
            player.Speed += speedIncrease; // 플레이어 속도도 증가
        }
    }

    public void AddScore(int value)
    {
        if (!isGameOver)
        {
            score += value;
            coinCount++;
            uiManager.UpdateScore(score,coinCount);
        }
    }

    public void GameOver()
    {
        if (isGameOver) return;
        isGameOver = true;
        //게임정지
        SaveBestScore();

        Time.timeScale = 0f;
        PlayerController player = FindObjectOfType<PlayerController>();
        if (player != null)
            player.enabled = false;
        uiManager.SetGameOver();
    }

    public void RestartGame()
    {
        Time.timeScale = 1f;
        SceneLoader.LoadScene(SceneManager.GetActiveScene().name);
    }
    //GameOverPanel UIManager연결해주세요.
    //GameOverUI속 Button에 GameManager.RestartGame() 함수 선택해주세요.
    //re:Ui에서 버튼클릭이벤트 연결해두고 게임매니저메소드 호출하는식으로 변경했습니다.

    public void PauseGame()
    {
        Time.timeScale = 0f;
    }

    public void ResumeGame()
    {
        Time.timeScale = 1f;
    }
    public void SaveBestScore()
    {
        if (score > BestScore)
        {
            BestScore = score;
            ScoreData data = new ScoreData { bestScore = BestScore };

            string json = JsonUtility.ToJson(data, true);
            string fullPath = Path.Combine(Application.dataPath, "Resources/Data.json");
            File.WriteAllText(fullPath, json);

#if UNITY_EDITOR
            UnityEditor.AssetDatabase.Refresh(); // 에디터 상에서 바로 반영됨
#endif
        }
    }
    private void LoadBestScore()
    {
        TextAsset jsonText = Resources.Load<TextAsset>(dataPath);
        if (jsonText != null)
        {
            ScoreData data = JsonUtility.FromJson<ScoreData>(jsonText.text);
            BestScore = data.bestScore;
        }
        else
        {
            Debug.LogWarning("Data.json 파일없음. 기본값 0 사용.");
            BestScore = 0;
        }
    }
}

 

 

오늘은 Data.json을 연결하고 그후에,  로드 , 세이브 까지 작성했다.

 

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : Unit
{
    private bool isGodMode = false;
    private float godModeTimer = 0f;
    private bool isDead = false;

    public float hitDamage = 20f; // 충돌 시 감소할 체력

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Coin"))
        {
            GameManager.Instance.AddScore(10);
            Destroy(other.gameObject);
            return;
        }
        if (isGodMode || isDead) return;

        if (other.CompareTag("Enemy") || other.CompareTag("Obstacle"))
        {
            TakeDamage(hitDamage);
        }
    }

    private void TakeDamage(float amount)
    {
        Hp -= amount;
        if (Hp <= 0)
        {
            isDead = true;
            GameManager.Instance.GameOver();
            return;
        }

        ActivateGodMode(GameManager.Instance.playerGodMode);
    }

    protected override float Hp
    {
        get { return hp; }
        set
        {
            hp = Mathf.Clamp(value, 0, fullHP);
        }
    }

    protected override float JumpForce
    {
        get { return jumpForce; }
        set
        {
            jumpForce = Mathf.Max(0, value);
        }
    }

    public override float Speed
    {
        get { return speed; }
        set
        {
            speed = Mathf.Max(0, value);
        }
    }

    private void Awake()
    {
        base.Awake();
        Hp = 100f;
        JumpForce = 5f;
        Speed = 5f;
    }

    private void Update()
    {
        DecreaseHpByDistance();
        
        //땅에 오브젝트가 닿았는지 확인
        isGrounded = Physics2D.Raycast(transform.position, Vector2.down, groundRayLength, groundLayer);
        
        //점프
        if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
        {
            Jump();
        }

        animCtrl.JumpAnim(isGrounded);
        
        //슬라이드
        PressedShift = Input.GetKey(KeyCode.LeftShift);
        if (PressedShift)
        {
            Slide(PressedShift);
        }

        // 무적 시간 감소
        if (isGodMode)
        {
            godModeTimer -= Time.deltaTime;
            if (godModeTimer <= 0f)
            {
                isGodMode = false;
                GetComponentInChildren<SpriteRenderer>().color = Color.white; // 색 복원
            }
        }
    }

    private void FixedUpdate()
    {
        Move();
    }

    public override void Move()
    {
        tr.Translate(Vector3.right * Speed * Time.fixedDeltaTime, Space.World);
    }

    public override void Jump()
    {
        rb.AddForce(Vector2.up * JumpForce, ForceMode2D.Impulse);
    }

    public override void Slide(bool PressedShift)
    {
        animCtrl.SlideAnim(PressedShift);
    }

    public void ActivateGodMode(float duration)
    {
        isGodMode = true;
        godModeTimer = duration;
        StartCoroutine(FlashWhileInvincible());
    }

    private IEnumerator FlashWhileInvincible()
    {
        SpriteRenderer sr = GetComponentInChildren<SpriteRenderer>();
        while (isGodMode)
        {
            sr.color = new Color(1, 1, 1, 0.5f); // 반투명
            yield return new WaitForSeconds(0.1f);
            sr.color = Color.white;
            yield return new WaitForSeconds(0.1f);
        }
    }
    public override void DecreaseHpByDistance()
    {
        //거리에 따른 체력 감소
        hp -= playerDistance.distance * 0.001f;
    }
}

 

그리고 여기에 있는 부딪혔을때 태그에 따라 반응 하는 코드를 추가로 작성헀다.