107 lines
3.4 KiB
C#
107 lines
3.4 KiB
C#
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// 만능 투사체 (화살, 마법, 돌맹이 공용)
|
|
/// </summary>
|
|
public class Projectile : MonoBehaviour
|
|
{
|
|
[Header("기본 설정")]
|
|
[SerializeField] private float lifetime = 5f; // 수명 (5초 뒤 삭제)
|
|
[SerializeField] private GameObject hitEffectPrefab; // 맞으면 나오는 이펙트 (폭발 등)
|
|
[SerializeField] private bool destroyOnHit = true; // 맞으면 사라짐? (관통 아니면 true)
|
|
|
|
// 내부 변수
|
|
private Vector3 _direction;
|
|
private float _speed;
|
|
private float _damage;
|
|
private bool _isInitialized = false;
|
|
private Rigidbody _rigidbody;
|
|
|
|
private void Awake()
|
|
{
|
|
_rigidbody = GetComponent<Rigidbody>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 몬스터가 발사할 때 호출하는 초기화 함수
|
|
/// </summary>
|
|
/// <param name="direction">날아갈 방향</param>
|
|
/// <param name="speed">속도 (0이면 물리력으로 날아감)</param>
|
|
/// <param name="damage">줄 데미지</param>
|
|
public void Initialize(Vector3 direction, float speed, float damage)
|
|
{
|
|
_direction = direction.normalized;
|
|
_speed = speed;
|
|
_damage = damage;
|
|
_isInitialized = true;
|
|
|
|
// 속도가 있다? -> 화살/마법 (직선 운동)
|
|
if (_rigidbody != null && speed > 0)
|
|
{
|
|
_rigidbody.velocity = _direction * _speed;
|
|
_rigidbody.useGravity = false; // 마법은 보통 중력 무시
|
|
}
|
|
// 속도가 0이다? -> 돌맹이 (외부에서 물리력 가함)
|
|
else if (_rigidbody != null && speed == 0)
|
|
{
|
|
_rigidbody.useGravity = true; // 돌은 중력 받아야 함
|
|
}
|
|
|
|
// 수명 지나면 자동 삭제
|
|
Destroy(gameObject, lifetime);
|
|
}
|
|
|
|
private void FixedUpdate()
|
|
{
|
|
if (!_isInitialized) return;
|
|
|
|
// 리지드바디가 없거나, Kinematic인 경우 (강제 이동 보정)
|
|
if (_rigidbody == null || _rigidbody.isKinematic)
|
|
{
|
|
if (_speed > 0)
|
|
{
|
|
transform.position += _direction * _speed * Time.fixedDeltaTime;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnTriggerEnter(Collider other)
|
|
{
|
|
// 1. 적(몬스터)끼리 맞으면 무시
|
|
if (other.CompareTag("Enemy") || other.gameObject == gameObject) return;
|
|
|
|
// 2. 투사체끼리 충돌 무시
|
|
if (other.GetComponent<Projectile>()) return;
|
|
|
|
// 3. 플레이어 피격 처리
|
|
if (other.CompareTag("Player"))
|
|
{
|
|
// PlayerHealth 혹은 IDamageable 스크립트 찾기
|
|
var playerHealth = other.GetComponent<PlayerHealth>();
|
|
|
|
if (playerHealth != null)
|
|
{
|
|
// 무적 상태 체크 (있다면)
|
|
if (!playerHealth.isInvincible)
|
|
{
|
|
playerHealth.TakeDamage(_damage);
|
|
Debug.Log($"🎯 [적중] 플레이어에게 {_damage} 데미지!");
|
|
}
|
|
}
|
|
}
|
|
|
|
// 4. 벽이나 땅에 닿았을 때도 이펙트
|
|
if (other.CompareTag("Ground") || other.CompareTag("Wall") || other.CompareTag("Player"))
|
|
{
|
|
if (hitEffectPrefab != null)
|
|
{
|
|
Instantiate(hitEffectPrefab, transform.position, Quaternion.identity);
|
|
}
|
|
|
|
if (destroyOnHit)
|
|
{
|
|
Destroy(gameObject);
|
|
}
|
|
}
|
|
}
|
|
} |