유니티 시야각과 추적 미사일로 완성된 지능형 터렛 만들기
게임에서 플레이어를 위협하는 터렛은 단순한 움직임을 넘어 지능적인 판단을 내릴 때 비로소 진정한 위협이 됩니다. 플레이어가 시야각에 들어오고, 장애물에 가려지지 않았을 때만 공격을 시작하는 터렛은 게임의 몰입도를 한층 높여줍니다. 이번 글에서는 기본적인 터렛 기능에 시야각 감지, 시야선 확인, 그리고 추적 미사일 기능까지 추가한, 더욱 정교하고 실감나는 터렛 시스템을 구축하는 방법을 알려드립니다.
1. 지능형 터렛 컨트롤러 스크립트 작성
AdvancedTurretController.cs
라는 이름의 스크립트를 새로 만들고 아래 코드를 입력해 주세요. 이 스크립트는 터렛의 상태를 관리하고, 고급 감지 로직을 처리합니다.
C#
using UnityEngine;
public class AdvancedTurretController : MonoBehaviour
{
[Header("터렛 설정")]
public Transform target; // 터렛이 추적할 대상 (플레이어)
public float detectionRadius = 15f; // 감지 범위
public float fieldOfViewAngle = 60f; // 터렛의 시야각 (전방 60도)
public float rotationSpeed = 5f; // 회전 속도
[Header("발사 설정")]
public GameObject missilePrefab; // 발사할 미사일 프리팹
public Transform firePoint; // 미사일이 생성될 위치
public float fireRate = 2f; // 발사 속도 (초당 2발)
private float nextFireTime;
void Update()
{
if (target == null)
{
FindTargetWithTag("Player");
return;
}
float distanceToTarget = Vector3.Distance(transform.position, target.position);
if (distanceToTarget <= detectionRadius)
{
// 시야각과 시야선(Line of Sight) 체크
if (IsTargetInFieldOfView() && HasClearLineOfSight())
{
AimAtTarget();
if (Time.time >= nextFireTime)
{
ShootMissile();
nextFireTime = Time.time + 1f / fireRate;
}
}
}
}
void FindTargetWithTag(string tag)
{
GameObject player = GameObject.FindWithTag(tag);
if (player != null)
{
target = player.transform;
}
}
void AimAtTarget()
{
Vector3 direction = target.position - transform.position;
direction.y = 0; // 수평 조준만 하도록 Y축 회전 고정
Quaternion lookRotation = Quaternion.LookRotation(direction);
transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * rotationSpeed);
}
void ShootMissile()
{
if (missilePrefab != null && firePoint != null)
{
// 미사일을 생성하고, 미사일 스크립트에 타겟을 전달합니다.
GameObject missileInstance = Instantiate(missilePrefab, firePoint.position, firePoint.rotation);
missileInstance.GetComponent<Missile>().SetTarget(target);
Debug.Log("추적 미사일 발사!");
}
}
// 시야각 안에 플레이어가 있는지 확인합니다.
bool IsTargetInFieldOfView()
{
Vector3 directionToTarget = (target.position - transform.position).normalized;
float angle = Vector3.Angle(transform.forward, directionToTarget);
return angle < fieldOfViewAngle / 2f;
}
// 터렛과 플레이어 사이에 장애물이 있는지 레이캐스트로 확인합니다.
bool HasClearLineOfSight()
{
RaycastHit hit;
if (Physics.Raycast(firePoint.position, (target.position - firePoint.position).normalized, out hit, detectionRadius))
{
// 레이캐스트가 맞힌 오브젝트가 플레이어인지 확인합니다.
return hit.transform == target;
}
return false;
}
void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, detectionRadius);
Gizmos.color = Color.yellow;
Gizmos.DrawLine(transform.position, transform.position + Quaternion.Euler(0, fieldOfViewAngle / 2, 0) * transform.forward * detectionRadius);
Gizmos.DrawLine(transform.position, transform.position + Quaternion.Euler(0, -fieldOfViewAngle / 2, 0) * transform.forward * detectionRadius);
}
}
2. 추적 미사일 스크립트 작성
터렛이 발사하는 미사일의 움직임을 제어하는 스크립트입니다. Missile.cs
라는 이름으로 만드세요.
C#
using UnityEngine;
public class Missile : MonoBehaviour
{
public float speed = 20f;
public float lifeTime = 5f;
public float homingStrength = 1f; // 타겟을 추적하는 힘
private Transform target;
void Start()
{
Destroy(gameObject, lifeTime);
}
void Update()
{
// 타겟이 있다면 타겟 방향으로 부드럽게 회전합니다.
if (target != null)
{
Vector3 directionToTarget = target.position - transform.position;
Quaternion targetRotation = Quaternion.LookRotation(directionToTarget);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * homingStrength);
}
// 미사일이 앞으로 계속 이동합니다.
transform.Translate(Vector3.forward * speed * Time.deltaTime);
}
// 터렛 컨트롤러에서 타겟을 설정하기 위한 함수
public void SetTarget(Transform newTarget)
{
target = newTarget;
}
void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
Debug.Log("플레이어 피격!");
Destroy(gameObject);
}
}
}
3. 유니티 에디터 설정 및 코드 해설
- 터렛 오브젝트 설정: 빈 게임 오브젝트를 만들어
AdvancedTurretController.cs
스크립트를 부착합니다.Detection Radius
,Field of View Angle
등 변수 값을 원하는 대로 설정하세요. - 미사일 프리팹 제작: 미사일 오브젝트에
Missile.cs
스크립트를 부착하고 프리팹으로 만듭니다.Homing Strength
를 조절하여 미사일의 추적 능력을 변경할 수 있습니다. - 코드의 핵심:
IsTargetInFieldOfView()
: **Vector3.Angle
**을 사용해 터렛의 전방과 플레이어 방향 벡터 사이의 각도를 계산합니다. 이 각도가 설정한 시야각의 절반보다 작아야만 터렛이 플레이어를 ‘볼’ 수 있습니다.HasClearLineOfSight()
: **Physics.Raycast
**를 사용해 터렛의 발사 지점(firePoint
)에서 플레이어까지 직선을 쏘아, 중간에 다른 오브젝트가 없는지 확인합니다. 이 덕분에 터렛이 벽 너머의 플레이어를 공격하는 불합리한 상황을 방지합니다.- 추적 미사일:
TurretController
스크립트가 미사일 생성 시SetTarget()
함수로 플레이어 정보를 넘겨줍니다.Missile.cs
의Update()
함수는 이 타겟 정보를 바탕으로 매 프레임마다 미사일의 방향을 부드럽게 틀어 플레이어를 쫓아가게 됩니다.
이 코드는 터렛을 더욱 똑똑하고, 게임의 흐름에 맞는 방식으로 작동하게 합니다. 이 기본 구조를 활용하여 미사일 폭발 효과, 발사 사운드, 터렛의 체력 시스템 등을 추가하여 완성도를 높여보세요.