Unity Version : 2021.3.5f1
나중에 모델과 이펙트까지 붙이면 될 것 같다.
적에게 피해를 입히는 방법은 어떤식으로 구현하면 좋을지 생각해봐야 할 듯
추가적으로 이 방법은 범위에 들어온 적 1기만 공격할 수 있지만
여러명을 공격하는 포탑에는 적용시킬 수 없을 듯하다. (Physics.OverlapSphere 사용을 생각 중)
사용한 방법은
콜라이더를 이용하여 주변에 적을 식별(layer로 필터)하고 타겟팅합니다.
물체와 자신과의 거리를 계산하여 특정 거리 이상으로 멀어지면 타겟팅을 해제하고 다시 대기모드로 변경합니다.
![](https://lycos7560.com/wp-content/uploads/image-739.png)
구현하면서 나온 문제는 중심거리는 멀어져서 타겟팅이 해제되지만 충돌범위에 속하여 오류가 발생합니다.
-> 해결 방법은 포탑의 탐색길이(파랑)와 타겟팅된 물체의 콜라이더 길이(노랑)의 합보다 중심거리가(빨강) 길면 해결됩니다.
뒤 생각없이 구현한 포탑 코드
using System.Collections; using System.Collections.Generic; using UnityEngine; public enum eTurretState { Nono = -1, idle, attack } public class turret : MonoBehaviour { [SerializeField] public GameObject m_TurretTarget; [SerializeField] private eTurretState m_eTurretState = eTurretState.Nono; [SerializeField] public float m_AttackRange; [SerializeField] public float m_TurnSpeed; [SerializeField] private float m_AttackSpeed; [SerializeField] private float m_AttackCoolDown; public GameObject testHead; public GameObject RangeSqhere; private void OnTriggerEnter(Collider other) { if (other.gameObject.layer == 20) { this.m_TurretTarget = other.gameObject; // 터렛의 공격 대상 오브젝트에 추가 // 공격 범위 콜라이더를 OFF; SphereColliderActive(false); StartCoroutine(this.TargettingCoroutine()); this.m_eTurretState = eTurretState.attack; } } /// <summary> /// 터렛의 적을 식별하는 콜라이더의 크기를 변경합니다. /// </summary> /// <param name="state"></param> private void SphereColliderActive(bool state) { if (state) { this.RangeSqhere.transform.localScale = new Vector3(this.m_AttackRange * 2, 0.0001f, this.m_AttackRange * 2); } else { this.RangeSqhere.transform.localScale = new Vector3(0.001f, 0.0001f, 0.001f); } } /// <summary> /// 터렛이 지속적으로 적을 타겟팅하는 코르틴 /// </summary> /// <returns></returns> private IEnumerator TargettingCoroutine() { while (true) { // 만약 터렛의 타겟이 Null이거나 터렛과 if (m_TurretTarget == null || this.m_TurretTarget.gameObject.layer != 20 || Vector3.Distance(this.m_TurretTarget.transform.position, this.transform.position) > this.m_AttackRange + 2.0f) { this.m_eTurretState = eTurretState.idle; SphereColliderActive(true); break; } else { this.testHead.transform.rotation = Quaternion.Lerp(this.testHead.transform.rotation, Quaternion.LookRotation(this.m_TurretTarget.transform.position - this.transform.position), Time.deltaTime * this.m_TurnSpeed); } yield return null; } } public void SearchEnemy() { } public void AttackEnemy() { Debug.Log("Attack"); //m_TurretTarget.GetComponent<TestEnemy>().BeDamaged(this.Damage); } private void Start() { // 샘플 this.RangeSqhere.transform.localScale = new Vector3(this.m_AttackRange * 2, 0.0001f, this.m_AttackRange * 2); } private void Update() { if (this.m_AttackCoolDown > 0f) { this.m_AttackCoolDown -= Time.deltaTime; } if (m_eTurretState == eTurretState.attack && this.m_AttackCoolDown <= 0f && this.m_TurretTarget != null) { this.m_AttackCoolDown = this.m_AttackSpeed; AttackEnemy(); } } }
![](https://lycos7560.com/wp-content/uploads/image-740.png)
![](https://lycos7560.com/wp-content/uploads/image-741.png)
![](https://lycos7560.com/wp-content/uploads/image-742.png)