#24 화살타워 추가
This commit is contained in:
parent
5f20d3d57a
commit
c56898125c
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -222,6 +222,8 @@ namespace BlueWaterProject
|
|||||||
gameObject.SetActive(false);
|
gameObject.SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float GetArrowSpeed() => arrowSpeed;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user