오늘은 속도 관련되서 관련된 정보를 여기저기 찾아보며 해결한 날

무적 아이템을 먹었을 때 망치가 나와서 휘두르는 애니메이션을 재생할 수 있도록 변경해주었다


// 무적 망치 연출이 들어가 있는 게임 오브젝트
public GameObject hammerObject;

private IEnumerator Invincibility(float duration)
    {
        isInvincible = true;
        // 게임 오브젝트 켜기
        if (hammerObject != null)
        {
            hammerObject.SetActive(true);
        }
        Debug.Log("무적 시작");

        // 지속 시간 동안 대기
        yield return new WaitForSeconds(duration);

        isInvincible = false;
        // 게임 오브젝트 끄기
        if (hammerObject != null)
        {
            hammerObject.SetActive(false);
        }
        Debug.Log("무적 종료");
    }

아이템 랜덤 스폰 방식

아이템이 랜덤으로 스폰할 수 있도록 코드도 짜봤다

	public GameObject[] itemPrefabs;
    public float spawnInterval = 2f;

    // 스폰 위치 설정
    public float spawnX = 10f;
    public float minY = -2f;
    public float maxY = 2f;

    // 이동 속도
    public float itemMoveSpeed = 3f;

    private void Start()
    {
        InvokeRepeating(nameof(SpawnItem), 1f, spawnInterval);
    }

    private void SpawnItem()
    {
        Vector3 spawnPos = new Vector3(spawnX, Random.Range(minY, maxY), 0f);
        GameObject item = Instantiate(GetRandomItem(), spawnPos, Quaternion.identity);
        item.AddComponent<ObstacleMover>().speed = itemMoveSpeed;
    }

    private GameObject GetRandomItem()
    {
        int index = Random.Range(0, itemPrefabs.Length);
        return itemPrefabs[index];
    }

프리팹화 한 아이템들을 먼저 설정해 준 다음 딜레이를 얼마나 줄 건지 spawnInterval 을 변경하여 조절할 수 있고 설정된 아이템들을 랜덤하게 소환해준다

추가로

	// 겹침 방지 설정
    public LayerMask obstacleLayer;
    
    // 해당 위치에 장애물이 있는지 검사
    Collider2D[] hits = Physics2D.OverlapCircleAll(spawnPos, 0.5f, obstacleLayer);

    // 겹치면 스폰 취소
    if (hits.Length > 0)
    {
        Debug.Log("장애물과 겹쳐서 스폰 취소");
        return;
    }

아이템이 생성될 때 그 자리에 장애물이 있다면 생성을 취소하게끔 하여 장애물과 겹쳐서 스폰되서 아이템을 못 먹는 상황을 방지

배치 구조

이 구조 말고 랜덤으로 생성되는 장애물에 아이템을 직접 분배해줘 길잡이도 해주고 배치도 깔끔하게 나오는 방법도 생각

프리팹스화 되어있는 장애물에 아이템을 추가해줘 배치구조를 다양하게 가져갈 수 있다


아이템을 중복으로 먹었을 때 지속시간이 갱신이 안되는 트러블 발견

찾아보니 코루틴은 실행중일 때는 멈춰주지 않는 이상 실행하던 함수를 그대로 실행한다고 하더라

그래서 코루틴 시작할 때 코루틴을 멈춰주는 코드를 추가함으로서 해결

 if (invincibleCoroutine != null)
StopCoroutine(invincibleCoroutine);
invincibleCoroutine = StartCoroutine(Invincibility(3.4f));

예시로 가져온 게임에 사용되고 있는 코드


질주 아이템

아이템을 먹었을 때 속도가 증가된다

속도가 적용되고 있는 물체들에게 적용하면 됨

배경이 움직이는 구조니깐 스피드 매니저를 만들어서 관리를 해보자

public class GameSpeedManager : MonoBehaviour
{
    public static GameSpeedManager Instance;

    public float elapsedTime = 0f;
    public float maxTime = 30f; // 최대 속도 도달 시간
    public float baseSpeed = 5f;
    public float targetSpeed = 10f;

    private void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
            return;
        }

        Instance = this;
        DontDestroyOnLoad(gameObject);
    }

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

    public float GetCurrentSpeed()
    {
        float t = Mathf.Clamp01(elapsedTime / maxTime);
        return Mathf.Lerp(baseSpeed, targetSpeed, t);
    }

    public void ResetSpeed()
    {
        elapsedTime = 0f;
    }
}

먼저 스피드 매니저 단일화 시켜주고 속도 증가는 Lerp를 이용해 baseSpeed를 시작으로 targetSpeed까지 부드럽게 증가되게끔 적용

게임이 다시 시작될 때 지나간 시간을 초기화 (방어적인 코딩이 이런거 아닐까?)

public class ObstacleMover : MonoBehaviour
{
    // 질주 아이템 먹었을 때 필요한 값
    public static float globalSpeedMultiplier = 1f;

    void Update()
    {
        if (GameSpeedManager.Instance == null) return;

        float currentSpeed = GameSpeedManager.Instance.GetCurrentSpeed();
        transform.Translate(Vector2.left * currentSpeed * globalSpeedMultiplier * Time.deltaTime);
        if (transform.position.x < -50f)
            Destroy(gameObject);
        
    }
}

static으로 마을회관을 만들었으니 물체 이동시키는 코드에 적용

0개의 댓글