
오늘은 속도 관련되서 관련된 정보를 여기저기 찾아보며 해결한 날
무적 아이템을 먹었을 때 망치가 나와서 휘두르는 애니메이션을 재생할 수 있도록 변경해주었다
// 무적 망치 연출이 들어가 있는 게임 오브젝트
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으로 마을회관을 만들었으니 물체 이동시키는 코드에 적용