OldBlueWater/BlueWater/Assets/02.Scripts/Arrow.cs
NTG_Lenovo 86065e52a9 #10 Testing long range ai (arrow attack system)
Additional commit content
1. Modified ObjectPool Function(OnReleaseArrow and naming).
2. Modified hitBox tag in aiPrefab.
3. Modified Physics layer.
4. Modified TargetInfo variable from TargetTransform variable in FieldOfView script.
5. Added GetCurrentHp() in IAiStat script.
2023-08-09 16:44:09 +09:00

159 lines
5.2 KiB
C#

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Pool;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
public class Arrow : MonoBehaviour
{
#region Property and variable
[Tooltip("발사 이후 자동으로 사라지는데 까지 걸리는 시간")]
[Range(0f, 10f)]
[SerializeField] private float autoDestroyTime;
[Tooltip("화살이 날아가는 속도")]
[SerializeField] private float arrowSpeed = 15f;
private float g = Mathf.Abs(Physics.gravity.y);
private Vector3 targetPos;
private AttackerType attackerType;
private float inaccuracy;
private Transform attackerTransform;
private AiStat attackerStat;
private Rigidbody arrowRigidbody;
private IObjectPool<Arrow> managedArrowPool;
#endregion
#region Unity built-in function
private void Awake()
{
arrowRigidbody = Utils.GetComponentAndAssert<Rigidbody>(transform);
}
private void OnTriggerEnter(Collider other)
{
print(other.gameObject.name);
if (other.gameObject.layer == LayerMask.NameToLayer("Ground") ||
other.gameObject.layer == LayerMask.NameToLayer("Water"))
{
DestroyObject();
}
else if (other.gameObject.layer == LayerMask.NameToLayer("HitBox"))
{
switch (attackerType)
{
case AttackerType.NONE:
break;
case AttackerType.PLAYER:
if (!other.gameObject.CompareTag("Enemy"))
{
return;
}
break;
case AttackerType.PIRATE:
if (!other.gameObject.CompareTag("Enemy"))
{
return;
}
break;
case AttackerType.ENEMY:
if (!other.gameObject.CompareTag("Player") || !other.gameObject.CompareTag("Pirate"))
{
return;
}
break;
default:
throw new ArgumentOutOfRangeException();
}
var iDamageable = other.transform.parent.GetComponent<IDamageable>();
print(iDamageable);
iDamageable.TakeDamage(attackerStat, iDamageable.AiStat);
DestroyObject();
}
}
#endregion
#region Custom function
public IEnumerator Shoot()
{
var time = 0f;
var inaccuracyOffset = new Vector3(
UnityEngine.Random.Range(-inaccuracy, inaccuracy),
UnityEngine.Random.Range(-inaccuracy, inaccuracy),
UnityEngine.Random.Range(-inaccuracy, inaccuracy)
);
var inaccurateTargetPos = targetPos + inaccuracyOffset;
transform.rotation = Quaternion.LookRotation(inaccurateTargetPos);
transform.rotation *= Quaternion.Euler(0f, -90f, 0f);
while (time < autoDestroyTime)
{
var myPos = transform.position;
var toTargetFlat = new Vector3(inaccurateTargetPos.x - myPos.x, 0, inaccurateTargetPos.z - myPos.z);
var horizontalDistance = toTargetFlat.magnitude;
var timeToTarget = horizontalDistance / arrowSpeed;
var yOffset = targetPos.y - myPos.y;
var initialVerticalSpeed = (yOffset + (0.5f * g * timeToTarget * timeToTarget)) / timeToTarget;
var launchVelocity = toTargetFlat.normalized * arrowSpeed + Vector3.up * initialVerticalSpeed;
arrowRigidbody.velocity = launchVelocity;
transform.rotation = Quaternion.LookRotation(arrowRigidbody.velocity);
transform.rotation *= Quaternion.Euler(0f, -90f, 0f);
yield return null;
}
if (gameObject.activeSelf)
{
DestroyObject();
}
}
public void SetShootingArrow(Vector3 shootPos, Vector3 targetPosition, AiStat attackerAiStat, AttackerType type, float inaccuracyValue)
{
transform.position = shootPos;
targetPos = targetPosition;
attackerStat = attackerAiStat;
attackerType = type;
inaccuracy = inaccuracyValue;
}
#endregion
#region ObjectPool function
private void DestroyObject() => managedArrowPool.Release(this);
public void SetManagedPool(IObjectPool<Arrow> pool) => managedArrowPool = pool;
#endregion
#region Custom function
public void ReleaseArrowSetting()
{
StopAllCoroutines();
gameObject.SetActive(false);
arrowRigidbody.velocity = Vector3.zero;
arrowRigidbody.angularVelocity = Vector3.zero;
}
#endregion
}
}