대포가 현재 한 방향으로 일직선에 있는 물체를 향해서만 공격을 하기 때문에, 더 전략적이지 못하게 되는 것을 느꼈다.
이번엔 대포가 자신의 감지 범위 내에 있는 상대의 코어를 자동으로 공격방향으로 하여 공격할 수 있게끔 만들것이다.

대포 충돌체 감지 기능
가장 먼저 작성 해야하는 것은 대포가 감지하는 크기와 거리를 만드는 작업이다.
Cannon
[SerializeField] GameObject debugCube;
public Vector3 standardDir;
IEnumerator FireBall()
{
while(true)
{
yield return new WaitForSeconds(attackDelay);
Vector3 center = transform.position + standardDir * 5;
Vector3 halfExtent = new Vector3(3, 3, 5);
Quaternion orientation = Quaternion.Euler(standardDir.y* 90,standardDir.x * 90,0);
Collider[] hits = Physics.OverlapBox(center,halfExtent, orientation, LayerMask.GetMask("Cube"));
GameObject prefab = Instantiate(debugCube);
prefab.transform.position = center;
prefab.transform.rotation = orientation;
prefab.transform.localScale = new Vector3(3,3,5) * 2;
foreach (Collider collider in hits)
{
Debug.Log(collider.name + "시전자 : " + gameObject.name);
}
Instantiate(cannonBall, cannonBallPos.position, cannonRotation.rotation);
}
}
Physics.OverlapBox를 통해서 큐브를 감지하게 했으며, 방향과 큐브의 중심같은 경우 standardDir를 사용해서 만들었다.
Cube 레이어를 가진 여러 충돌체를 hits에 넣고, foreach로 검사를 진행하는 코드이다. (추후 확장)

큐브의 방향은 현재 대포의 기준 방향을 활용해서 수식을 만들어 작성했다.
디버깅은 debugCube라는 게임오브젝트로 게임에서 임시적으로 보이게하여 진행하였다. (추후 삭제예정)
CubeCreator
public void CreateCannon(Vector3 dir, Transform cube, Caster caster)
{
if (CheckFace(dir, cube)) return;
if (!CheckCost(cannonCost,caster)) return;
Vector3 InsPosition = cube.position;
float addRotation;
switch (dir.y)
{
case -1: addRotation = 180; break;
default: addRotation = 0; break;
}
Quaternion InsRotation = Quaternion.Euler(dir.z * 90 + addRotation, 0, dir.x * -90);
GameObject prefab = Instantiate(cannonPre, InsPosition, InsRotation);
prefab.GetComponent<Cannon>().standardDir = dir;
DefinePos(dir, cube, prefab, prefab.GetComponent<Cannon>());
ConnectingCube(prefab, cube);
CasterCheck(prefab, caster);
}
대포를 생성할 때, 대포의 생성기준 위치를 standardDir에 넣었다.


대포 타겟 바라보기
타겟 인지범위를 만들었으니, 이제 그 타겟을 대포가 바라보게끔 만들어 줘야 한다.
Cannon - FireBall의 foreach부분 부터
foreach (Collider collider in hits)
{
Cube cube = collider.GetComponent<Cube>();
float bestDistance = 100;
if (cube != null && myCaster != cube.myCaster) // 대상이 큐브이고, 자신과 시전자가 다르다면
{
float distance = (cube.transform.position - transform.position).magnitude;
if(bestDistance > distance)
{
bestDistance = distance;
target = cube;
}
Debug.Log(collider.name + " 거리 : " + distance);
}
}
float addRotation;
switch (standardDir.y)
{
case -1: addRotation = 180; break;
default: addRotation = 0; break;
}
Quaternion InsRotation = Quaternion.Euler(standardDir.z * 90 + addRotation, 0, standardDir.x * -90);
Debug.Log("insRotation : " + InsRotation.eulerAngles);
transform.rotation = Quaternion.LookRotation(target.transform.position - transform.position);
transform.rotation *= InsRotation;
Debug.Log(target + " " + transform.rotation);
Debug.DrawLine(transform.position, target.transform.position, Color.red,5);
Instantiate(cannonBall, cannonBallPos.position, cannonRotation.rotation);
감지 범위내에 들어온 여러 충돌체들을 검사한다. 먼저 Cube라는 컴포넌트를 가지고 있는지, 검사를 하게 된다.
이후 자신(대포)과 다른 시전자의 큐브인지도 확인한다. 이렇게 하면 상대방의 큐브만 타겟으로 판단할 수 있게된다.
두번째 if문에서는 현재 자신과 타겟까지의 거리를 측정한다. 모든 감지된 타겟과의 거리중 가장 짧은 타겟을 공격할 타겟으로 가진다.
아랫줄 코드는 직접적인 대포의 회전값을 구하는 코드이다.
먼저 CubeCreator에서 만들었던 코드처럼 현재 대포의 기존 회전값을 구한다. 이후 LookRotation을 통해서 타겟을 바라볼 방향을 구한 뒤, 기존 회전값을 보정하는 형태로 만들었다.
여담으로 회전값을 구하는 코드에 시간을 굉장히 할애하였다. 처음에는 부모오브젝트의 자식의 자식 오브젝트를 회전하려고 했다. 부모오브젝트를 기존 회전값이 존재하기 때문에 InverseTransformDirection을 사용해서, 부모 오브젝트를 기준하에, 회전 방향을 구하려고 했는데, 너무 어려워서 다음에 Quaternion에 대해서 공부하기로 하고 부모를 통째로 회전시키는 방법을 채택했다.

대포 에임 코드 수정
사실 다 만들줄 알았는데, 플레이어 코어에서 상대 코어방향에 있는 대포만 잘 작동하고, 그 외의 방향에서 혹은 상대 대포가 플레이어의 코어를 타겟으로 하지는 않았다.
그 이유를 오랫동안 생각해 봤는데 상대쪽에서 플레이어쪽을 바라보는 대포의 기본 회전값은 pitch가 -90으로 되어있다. 그리고 타겟을 바라볼때, 현재 위치에서 타겟 위치를 빼는데 이때, 월드 공간상 더 앞에 있다 보니(적 코어의 z : 10, 플레이어의 코어의 z : 0) InsRotation을 이미 바라보고 있는 방향에서 다시 더하다 보니, 아예 반대 방향으로 바라보게끔 된것이다.

Cannon 수정 코드
foreach (Collider collider in hits)
{
Cube cube = collider.GetComponent<Cube>();
float bestDistance = 100;
if (cube != null && myCaster != cube.myCaster) // 대상이 큐브이고, 자신과 시전자가 다르다면
{
float distance = (cube.transform.position - transform.position).magnitude;
if (bestDistance > distance)
{
bestDistance = distance;
target = cube;
}
Debug.Log(collider.name + " 거리 : " + distance);
}
}
if (target != null)
{
Debug.Log(transform.rotation.eulerAngles);
transform.rotation = Quaternion.LookRotation(target.transform.position - transform.position, -transform.forward);
Debug.Log(transform.rotation.eulerAngles);
transform.rotation *= Quaternion.Euler(90, 0, 0);
Debug.Log(transform.rotation.eulerAngles);
Debug.Log(gameObject.name + target.name + " " + transform.rotation);
Debug.DrawLine(transform.position, target.transform.position, Color.red, 5);
Instantiate(cannonBall, cannonBallPos.position, cannonRotation.rotation);
}
먼저 target이 있는지 확인하는 코드를 넣어준다.
이 코드가 회전하는 방식은 일반 대포 생성회전 방식과 다르게 LookRotation 으로 기본 방향을 맞추는데 이때, 위로 바라보는 방향을 -transform.forward로 하여, -z축이 위쪽을 향하도록 한다.

이후 x축을 -90만큼 돌려 기존 원래 대포가 위를 바라보는 점을 상쇄한다.

'GameDev > Cubidom' 카테고리의 다른 글
| Cubidom 일시 정지 만들기 (0) | 2026.03.29 |
|---|---|
| Cubidom 대포알 제거, 카메라 제어 보완 (0) | 2026.03.28 |
| Cubidom 스테이지 시스템 (0) | 2026.03.26 |
| Cubidom Enemy, 카메라,UI 버그 수정 (0) | 2026.03.25 |
| Cubidom 메인화면으로 이동 (0) | 2026.03.24 |