OneShotOneKill/Assets/Script/InGame/Projectile/Projectile.cs

95 lines
2.6 KiB
C#
Raw Normal View History

2026-01-11 23:53:38 +00:00
using UnityEngine;
public class Projectile : MonoBehaviour
{
2026-01-12 03:05:09 +00:00
public float m_Speed = 12f;
public int m_MaxBounce = 3;
public float radius = 0.1f;
2026-01-11 23:53:38 +00:00
Vector2 dir;
2026-01-12 03:05:09 +00:00
Vector2 prevPos;
2026-01-11 23:53:38 +00:00
int bounceCount;
2026-01-12 03:23:48 +00:00
#region
ProjectileMgr owner;
public void SetOwner(ProjectileMgr mgr) { owner = mgr; }
void Kill() { owner.Return(this); }
#endregion
2026-01-12 03:05:09 +00:00
2026-01-11 23:53:38 +00:00
public void Set()
{
dir = transform.up.normalized;
2026-01-12 03:05:09 +00:00
bounceCount = m_MaxBounce;
2026-01-11 23:53:38 +00:00
}
void Update()
{
2026-01-12 03:05:09 +00:00
prevPos = transform.position;
2026-01-11 23:53:38 +00:00
2026-01-12 03:05:09 +00:00
float moveDist = m_Speed * Time.deltaTime;
transform.position += (Vector3)(dir * moveDist);
}
2026-01-11 23:53:38 +00:00
2026-01-12 03:05:09 +00:00
private void OnTriggerEnter2D(Collider2D collision)
{
if (bounceCount <= 0)
2026-01-11 23:53:38 +00:00
{
2026-01-12 03:23:48 +00:00
Kill();
2026-01-12 03:05:09 +00:00
return;
2026-01-11 23:53:38 +00:00
}
2026-01-12 03:05:09 +00:00
Vector2 currentPos = transform.position;
Vector2 moveVec = currentPos - prevPos;
float distance = moveVec.magnitude;
Vector2 moveDir = distance > 0 ? moveVec / distance : dir;
// CircleCast로 정확한 충돌 지점(centroid)과 법선 탐색
RaycastHit2D[] hits = Physics2D.CircleCastAll(prevPos, radius, moveDir, distance);
RaycastHit2D hit = new RaycastHit2D();
bool found = false;
foreach (var h in hits)
2026-01-11 23:53:38 +00:00
{
2026-01-12 03:05:09 +00:00
if (h.collider == collision)
{
// 자기 자신(시작 위치에서 걸리는 경우) 제외 로직이 필요할 수 있으나,
// distance > 0 체크 등으로 보완. 여기서는 가장 먼저 닿는 지점을 찾음.
hit = h;
found = true;
break;
}
2026-01-11 23:53:38 +00:00
}
2026-01-12 03:05:09 +00:00
Vector2 normal;
Vector2 targetPos;
2026-01-11 23:53:38 +00:00
2026-01-12 03:05:09 +00:00
if (found)
2026-01-11 23:53:38 +00:00
{
2026-01-12 03:05:09 +00:00
normal = hit.normal;
// CircleCast의 centroid는 충돌 시의 원의 중심 위치입니다.
targetPos = hit.centroid;
}
else
{
// fallback: ClosestPoint
Vector2 closestRef = collision.ClosestPoint(prevPos);
normal = (prevPos - closestRef).normalized;
if (normal == Vector2.zero)
{
normal = (prevPos - (Vector2)collision.bounds.center).normalized;
}
targetPos = closestRef + normal * radius;
2026-01-11 23:53:38 +00:00
}
2026-01-12 03:05:09 +00:00
// 반사
2026-01-11 23:53:38 +00:00
dir = Vector2.Reflect(dir, normal).normalized;
2026-01-12 03:05:09 +00:00
bounceCount--;
2026-01-11 23:53:38 +00:00
2026-01-12 03:05:09 +00:00
// 회전
2026-01-11 23:53:38 +00:00
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg - 90f;
transform.rotation = Quaternion.Euler(0, 0, angle);
2026-01-12 03:05:09 +00:00
// 위치 보정
transform.position = targetPos;
2026-01-11 23:53:38 +00:00
}
}