#24 화살타워 추가

This commit is contained in:
NTG_Lenovo 2023-09-20 12:30:58 +09:00
parent 5f20d3d57a
commit c56898125c
4 changed files with 105 additions and 57 deletions

View File

@ -73505,7 +73505,7 @@ GameObject:
m_Icon: {fileID: 0} m_Icon: {fileID: 0}
m_NavMeshLayer: 0 m_NavMeshLayer: 0
m_StaticEditorFlags: 0 m_StaticEditorFlags: 0
m_IsActive: 1 m_IsActive: 0
--- !u!4 &187351605 --- !u!4 &187351605
Transform: Transform:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -709237,7 +709237,7 @@ Transform:
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1871370245} m_GameObject: {fileID: 1871370245}
serializedVersion: 2 serializedVersion: 2
m_LocalRotation: {x: 0.67640686, y: -0.0000002980232, z: 0.0000002980232, w: 0.7365283} m_LocalRotation: {x: 0.6764068, y: -0, z: -0, w: 0.7365283}
m_LocalPosition: {x: -0.0000002384187, y: 120, z: -10.000001} m_LocalPosition: {x: -0.0000002384187, y: 120, z: -10.000001}
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0

View File

@ -2,8 +2,8 @@
using System.Collections; using System.Collections;
using Sirenix.OdinInspector; using Sirenix.OdinInspector;
using UnityEngine; using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Pool; using UnityEngine.Pool;
using Random = UnityEngine.Random;
// ReSharper disable once CheckNamespace // ReSharper disable once CheckNamespace
namespace BlueWaterProject namespace BlueWaterProject
@ -14,6 +14,9 @@ namespace BlueWaterProject
[Title("Tower Stat")] [Title("Tower Stat")]
[SerializeField] private bool isDrawGizmosInFieldOfView = true; [SerializeField] private bool isDrawGizmosInFieldOfView = true;
[SerializeField] private bool isPredictAttack = true;
[OnValueChanged(nameof(SetLayer))]
[SerializeField] private EAiType aiType; [SerializeField] private EAiType aiType;
[SerializeField] private float maxHp; [SerializeField] private float maxHp;
[SerializeField] private float currentHp; [SerializeField] private float currentHp;
@ -25,8 +28,9 @@ namespace BlueWaterProject
[Title("실시간 타겟 정보")] [Title("실시간 타겟 정보")]
[SerializeField] private LayerMask targetLayer; [SerializeField] private LayerMask targetLayer;
[SerializeField] private LayerMask arrowLayer;
[SerializeField] private Collider[] colliderWithinRange; [SerializeField] private Collider[] colliderWithinRange;
[SerializeField] private Transform targetTransform; [SerializeField] private Collider targetCollider;
[Title("화살 오브젝트 관리")] [Title("화살 오브젝트 관리")]
[Tooltip("화살 오브젝트 풀링할 최대 갯수")] [Tooltip("화살 오브젝트 풀링할 최대 갯수")]
@ -49,16 +53,15 @@ namespace BlueWaterProject
Gizmos.color = Color.blue; Gizmos.color = Color.blue;
Gizmos.DrawWireSphere(transform.position, atkRange); Gizmos.DrawWireSphere(transform.position, atkRange);
if (!targetTransform) return; if (!targetCollider) return;
Gizmos.color = Color.red; Gizmos.color = Color.red;
Gizmos.DrawLine(transform.position, targetTransform.position); Gizmos.DrawLine(shootLocation.position, targetCollider.bounds.center);
} }
private void Awake() private void Awake()
{ {
InitComponent(); InitComponent();
SetLayer();
} }
private void Start() private void Start()
@ -80,7 +83,7 @@ namespace BlueWaterProject
// 건물 파괴 // 건물 파괴
if (changeHp == 0f) if (changeHp == 0f)
{ {
Destroy(gameObject); Die();
// RemoveIslandInfo(); // RemoveIslandInfo();
} }
} }
@ -111,73 +114,113 @@ namespace BlueWaterProject
colliderWithinRange = new Collider[TARGET_MAX_SIZE]; colliderWithinRange = new Collider[TARGET_MAX_SIZE];
} }
private void SetLayer() private void SetLayer()
{ {
switch (aiType) switch (aiType)
{ {
case EAiType.NONE: case EAiType.NONE:
print("aiType == NONE error"); targetLayer = 0;
break; break;
case EAiType.PLAYER: case EAiType.PLAYER:
case EAiType.PIRATE: case EAiType.PIRATE:
targetLayer |= LayerMask.GetMask("Enemy"); targetLayer = LayerMask.GetMask("Enemy");
break; break;
case EAiType.ENEMY: case EAiType.ENEMY:
targetLayer |= LayerMask.GetMask("Player") | LayerMask.GetMask("Pirate"); targetLayer = LayerMask.GetMask("Player") | LayerMask.GetMask("Pirate");
break; break;
default: default:
targetLayer = 0;
arrowLayer = 0;
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
} }
arrowLayer = targetLayer | LayerMask.GetMask("Ground") | LayerMask.GetMask("Water") |
LayerMask.GetMask("Props");
} }
private IEnumerator Attack() private IEnumerator Attack()
{ {
while (true) while (true)
{ {
FindNearestTargetInRange(transform.position, atkRange); FindNearestTargetInRange(atkRange);
if (!targetTransform) yield return new WaitForSeconds(atkCooldown); if (!targetCollider)
{
yield return new WaitForSeconds(atkCooldown);
continue;
}
var arrow = arrowPool.Get(); var arrow = arrowPool.Get();
var targetPos = isPredictAttack ? PredictTargetPosition(shootLocation, targetCollider, arrow.GetArrowSpeed()) : targetCollider.bounds.center;
arrow.SetShootingArrow(shootLocation.position, transform.position, arrow.SetShootingArrow(shootLocation.position, transform.position,
targetTransform.position, aiType, atk, shieldPenetrationRate, inaccuracy, false); targetPos, aiType, atk, shieldPenetrationRate, inaccuracy, false);
arrow.ShootArrowCoroutine(); arrow.ShootArrowCoroutine();
yield return new WaitForSeconds(atkCooldown);
} }
} }
private void FindNearestTargetInRange(Vector3 centerPos, float range) private void FindNearestTargetInRange(float range)
{ {
Array.Clear(colliderWithinRange, 0, TARGET_MAX_SIZE); Array.Clear(colliderWithinRange, 0, TARGET_MAX_SIZE);
var maxColliderCount = Physics.OverlapSphereNonAlloc(centerPos, range, colliderWithinRange, var maxColliderCount = Physics.OverlapSphereNonAlloc(transform.position, range, colliderWithinRange,
targetLayer, QueryTriggerInteraction.Collide); targetLayer, QueryTriggerInteraction.Collide);
if (maxColliderCount <= 0) if (maxColliderCount <= 0)
{ {
SetTargetTransform(null); SetTargetCollider(null);
return; return;
} }
var nearestDistance = Mathf.Infinity; var nearestDistance = Mathf.Infinity;
Transform nearestTargetTransform = null; Collider nearestTargetTransform = null;
for (var i = 0; i < maxColliderCount; i++) for (var i = 0; i < maxColliderCount; i++)
{ {
var distanceToTarget = Vector3.Distance(transform.position, colliderWithinRange[i].transform.position); var distanceToTarget = Vector3.Distance(shootLocation.position, colliderWithinRange[i].bounds.center);
if (!IsRaycastHitTarget(shootLocation.position, colliderWithinRange[i]) || distanceToTarget >= nearestDistance) continue;
if (distanceToTarget >= nearestDistance) continue; if (distanceToTarget >= nearestDistance) continue;
nearestDistance = distanceToTarget; nearestDistance = distanceToTarget;
nearestTargetTransform = colliderWithinRange[i].transform; nearestTargetTransform = colliderWithinRange[i];
} }
SetTargetTransform(nearestTargetTransform); SetTargetCollider(nearestTargetTransform);
}
private bool IsRaycastHitTarget(Vector3 startPos, Collider target)
{
var direction = ((target.bounds.center) - (startPos)).normalized;
var raycastHitTarget = Physics.Raycast(startPos, direction, out var hit, atkRange, arrowLayer, QueryTriggerInteraction.Collide);
return raycastHitTarget && target == hit.collider;
}
private Vector3 PredictTargetPosition(Transform shooter, Collider target, float arrowSpeed)
{
var targetVelocity = target.GetComponent<NavMeshAgent>().velocity;
var targetPos = target.bounds.center;
var directionToTarget = targetPos - shooter.position;
var distanceToTarget = directionToTarget.magnitude;
var timeToImpact = distanceToTarget / arrowSpeed;
var predictedPosition = targetPos + targetVelocity * timeToImpact;
return predictedPosition;
}
private void Die()
{
StopAllCoroutines();
Destroy(gameObject);
} }
private void SetCurrentHp(float value) => currentHp = value; private void SetCurrentHp(float value) => currentHp = value;
private void SetTargetTransform(Transform value) => targetTransform = value; private void SetTargetCollider(Collider value) => targetCollider = value;
#endregion #endregion

View File

@ -222,6 +222,8 @@ namespace BlueWaterProject
gameObject.SetActive(false); gameObject.SetActive(false);
} }
public float GetArrowSpeed() => arrowSpeed;
#endregion #endregion
} }
} }

View File

@ -42,8 +42,8 @@ GameObject:
- component: {fileID: 9031747955947254101} - component: {fileID: 9031747955947254101}
- component: {fileID: 8726458248037506361} - component: {fileID: 8726458248037506361}
- component: {fileID: 8190100621632311398} - component: {fileID: 8190100621632311398}
- component: {fileID: 9087576015726480415}
- component: {fileID: 3766443407819787020} - component: {fileID: 3766443407819787020}
- component: {fileID: 9087576015726480415}
m_Layer: 16 m_Layer: 16
m_Name: ArrowTower m_Name: ArrowTower
m_TagString: Tower m_TagString: Tower
@ -117,34 +117,6 @@ MeshRenderer:
m_SortingLayer: 0 m_SortingLayer: 0
m_SortingOrder: 0 m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0} m_AdditionalVertexStreams: {fileID: 0}
--- !u!114 &9087576015726480415
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8848616787261608530}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bd421891d0204bc5a748862f0ac9c0f1, type: 3}
m_Name:
m_EditorClassIdentifier:
isDrawGizmosInFieldOfView: 1
aiType: 0
maxHp: 500
currentHp: 0
atk: 20
atkRange: 30
atkCooldown: 2
shieldPenetrationRate: 50
inaccuracy: 0
colliderWithinRange: []
targetTransform: {fileID: 0}
arrowMaxSize: 100
arrowsPoolLocation: {fileID: 0}
targetLayer:
serializedVersion: 2
m_Bits: 0
--- !u!65 &3766443407819787020 --- !u!65 &3766443407819787020
BoxCollider: BoxCollider:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -164,5 +136,36 @@ BoxCollider:
m_ProvidesContacts: 0 m_ProvidesContacts: 0
m_Enabled: 1 m_Enabled: 1
serializedVersion: 3 serializedVersion: 3
m_Size: {x: 4.0214233, y: 4.0214243, z: 8.281539} m_Size: {x: 2.930729, y: 3.065148, z: 3.854234}
m_Center: {x: 0, y: 0.00000011920932, z: 2.6434815} m_Center: {x: 0.07538414, y: -0.21270323, z: 0.4423293}
--- !u!114 &9087576015726480415
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8848616787261608530}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bd421891d0204bc5a748862f0ac9c0f1, type: 3}
m_Name:
m_EditorClassIdentifier:
isDrawGizmosInFieldOfView: 1
isPredictAttack: 1
aiType: 2
maxHp: 500
currentHp: 0
atk: 20
atkRange: 30
atkCooldown: 1
shieldPenetrationRate: 50
inaccuracy: 0
targetLayer:
serializedVersion: 2
m_Bits: 768
arrowLayer:
serializedVersion: 2
m_Bits: 66328
colliderWithinRange: []
targetCollider: {fileID: 0}
arrowMaxSize: 100