
Additional commit content - Add arrow prefab, script, objectPool system - fixed 02.Main_TG Scene - testing fieldOfView
118 lines
3.6 KiB
C#
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
|
|
}
|
|
} |