

// RoomManager
using System.Collections;
using System.Collections.Generic;
using Unity.Cinemachine;
using UnityEngine;
public class RoomManager : MonoBehaviour
{
[Header("오브젝트 직렬화")]
[SerializeField] private GameObject monsterPrefab;
[SerializeField] private Transform[] spawnPoints;
[SerializeField] private GameObject door;
[Header("몬스터 스탯 설정")]
[SerializeField] private int spawnCount = 1;
[SerializeField] private float moveSpeed = 8f;
[SerializeField] private float damage = 5f;
[SerializeField] private float hp = 20f;
[SerializeField] private Vector3 monsterScale = Vector3.one;
[Header("시네머신 카메라 연결")]
[SerializeField] private CinemachineCamera spawnCam; // 몬스터 쪽 카메라
[SerializeField] private CinemachineCamera doorCam; // 문 열리는거 찍는 카메라
private List<GameObject> _activeMonsters = new List<GameObject>();
private bool _isCleared = false;
private bool _isSpawned = false;
public void StartRoomEvent()
{
StartCoroutine(Co_RoomSequence());
}
// 연출
private IEnumerator Co_RoomSequence()
{
// 몬스터 스폰 위치 카메라
if (spawnCam != null) spawnCam.Priority = 20; // CM_Player보다 높게 설정
yield return new WaitForSeconds(1.5f); // 카메라가 날아가는 시간 대기
// 몬스터 스폰
SpawnMonsters();
yield return new WaitForSeconds(1.0f); // 스폰된 모습 1초간 보기
// 카메라 다시 플레이어 쪽
if (spawnCam != null) spawnCam.Priority = 0;
yield return new WaitForSeconds(1.5f); // 돌아오는 시간 대기
// 몬스터 다 죽일 때 까지 게임 플레이
while (true)
{
if (CheckAllDead()) break;
yield return new WaitForSeconds(0.5f);
}
// 문 열리는거 찍음
if (doorCam != null) doorCam.Priority = 20;
yield return new WaitForSeconds(1.5f); // 날아가는 시간 대기
// 문 열림
OpenDoor();
yield return new WaitForSeconds(1.0f); // 열리는 시간 대기
// 다시 플레이어 카메라
if (doorCam != null) doorCam.Priority = 0;
}
private void SpawnMonsters()
{
for (int i = 0; i < spawnCount; i++)
{
Transform spawnPos = spawnPoints[i % spawnPoints.Length];
GameObject newMonster = Instantiate(monsterPrefab, spawnPos.position, spawnPos.rotation);
MonsterAI ai = newMonster.GetComponent<MonsterAI>();
if (ai != null)
{
ai.Initialize(moveSpeed, damage, hp, monsterScale);
}
_activeMonsters.Add(newMonster);
}
_isSpawned = true;
}
private bool CheckAllDead()
{
if (!_isSpawned) return false;
foreach (GameObject monster in _activeMonsters)
{
if (monster != null) return false; // 살아있는 놈 있다면 다시
}
return true; // 다 죽었음
}
private void OpenDoor()
{
if (door != null) door.SetActive(false);
_isCleared = true;
}
}
// 콜리더를 이용해서 RoomEvent 작동 로직
public class CloseDoor : MonoBehaviour
{
[SerializeField] private GameObject doorToClose;
[SerializeField] private RoomManager roomManager;
private void OnTriggerEnter(Collider other)
{
// 플레이어랑 닿으면
if (other.CompareTag("Player"))
{
// 문 닫음
if (doorToClose != null)
{
doorToClose.SetActive(true);
}
// 연출 시작
if (roomManager != null)
{
roomManager.StartRoomEvent();
}
// 투명 벽 끔
gameObject.SetActive(false);
}
}
}

// AimController.cs
using Unity.Cinemachine;
using UnityEngine;
public class AimController : MonoBehaviour
{
[SerializeField] private CinemachineCamera cmAim;
void Update()
{
// 쉬프트를 누르면 줌인
if (Input.GetKeyDown(KeyCode.LeftShift))
{
cmAim.Priority = 20;
}
// 쉬프트를 떼면 다시 원래 카메라
else if (Input.GetKeyUp(KeyCode.LeftShift))
{
cmAim.Priority = 0;
}
}
}
// combat.cs 플레이어의 공격 로직
using Unity.Cinemachine;
using UnityEngine;
public class Combat : MonoBehaviour
{
[SerializeField] private Transform _firePosition; // 생성 위치, 회전
[SerializeField] private float _fireInterval = 0.2f;
[SerializeField] private float _hp = 50f;
private bool _isAlive = true;
private float _fireCooldown;
private CinemachineImpulseSource _impulseSource;
public bool IsAlive { get => _isAlive; }
void Start()
{
_fireCooldown = _fireInterval;
_impulseSource = GetComponent<CinemachineImpulseSource>();
}
void Update()
{
if (_fireCooldown > 0)
{
_fireCooldown -= Time.deltaTime;
}
if (_fireCooldown > 0) return;
if (Input.GetAxis("Fire1") > 0f)
{
// 총알 생성
GameObject bullet = PoolManager.Instance.Get();
bullet.transform.position = _firePosition.position;
bullet.transform.rotation = _firePosition.rotation;
bullet.GetComponent<BulletController>().Fire();
// 플레이어 공격력으로 보정
//bullet.GetComponent<BulletController>().Init(30f);
_fireCooldown = _fireInterval;
if (_impulseSource != null)
{
Debug.Log("반동");
_impulseSource.GenerateImpulse();
}
}
}