OldBlueWater/BlueWater/Assets/02.Scripts/Arrow.cs
NTG_Lenovo 8bd4a3f3ca #7 Add FieldOfView script in aiPrefab
Additional commit content
- Add arrow prefab, script, objectPool system
- fixed 02.Main_TG Scene
- testing fieldOfView
2023-08-03 17:00:14 +09:00

118 lines
3.6 KiB
C#

using System.Collections;
using UnityEngine;
using UnityEngine.Pool;
using Random = UnityEngine.Random;
// ReSharper disable once CheckNamespace
namespace BlueWaterProject
{
public class Arrow : MonoBehaviour
{
#region Property and variable
[Tooltip("화살 발사 시작할 때의 속도")]
[SerializeField] private float initialVelocity;
[Tooltip("화살이 타겟에 도달하는 오차 범위(부정확함)")]
[Range(0f, 1f)]
[SerializeField] private float inaccuracy;
[Tooltip("발사 이후 자동으로 사라지는데 까지 걸리는 시간")]
[Range(0f, 10f)]
[SerializeField] private float autoDestroyTime;
private Vector3 targetPos;
private AiStat attackerStat;
private LayerMask targetLayer;
private IObjectPool<Arrow> managedArrowPool;
private Rigidbody arrowRigidbody;
#endregion
#region Unity built-in function
private void Awake()
{
arrowRigidbody = Utils.GetComponentAndAssert<Rigidbody>(transform);
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.layer != targetLayer) return;
var iDamageable = other.GetComponent<IDamageable>();
iDamageable.TakeDamage(attackerStat, iDamageable.AiStat);
}
#endregion
#region Custom function
public IEnumerator Shoot()
{
// TODO : 화살 발사 기능 구현
var time = 0f;
while (time < autoDestroyTime)
{
time += Time.deltaTime;
var toTarget = targetPos - transform.position;
var angle = CalcLaunchAngle(toTarget);
angle += Random.Range(-inaccuracy, inaccuracy);
var velocity = Quaternion.Euler(0, 0, angle) * Vector3.right * initialVelocity;
arrowRigidbody.velocity = velocity;
yield return null;
}
DestroyObject();
}
private float CalcLaunchAngle(Vector3 toTarget)
{
var distance = Vector3.Distance(toTarget, Vector3.zero);
var heightDifference = toTarget.y;
var gravity = Physics.gravity.magnitude;
var velocitySqr = initialVelocity * initialVelocity;
var underSqrt = (velocitySqr * velocitySqr) - (gravity * ((gravity * distance * distance) + (2 * heightDifference * velocitySqr)));
if (underSqrt >= 0)
{
var angle1 = Mathf.Atan((velocitySqr + Mathf.Sqrt(underSqrt)) / (gravity * distance));
var angle2 = Mathf.Atan((velocitySqr - Mathf.Sqrt(underSqrt)) / (gravity * distance));
return Mathf.Min(angle1, angle2) * Mathf.Rad2Deg;
}
else
{
return 45f;
}
}
public void SetShootingArrow(Vector3 targetPosition, AiStat attacker, int targetLayerMask)
{
targetPos = targetPosition;
attackerStat = attacker;
targetLayer = targetLayerMask;
}
//public void SetAiStat(AiStat attacker) => attackerStat = attacker;
//public void SetTargetLayer(int targetLayerMask) => targetLayer = targetLayerMask;
#endregion
#region ObjectPool function
private void DestroyObject() => managedArrowPool.Release(this);
public void SetManagedPool(IObjectPool<Arrow> pool) => managedArrowPool = pool;
#endregion
}
}