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 managedArrowPool; #endregion #region Unity built-in function private void Awake() { arrowRigidbody = Utils.GetComponentAndAssert(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(); 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 pool) => managedArrowPool = pool; #endregion #region Custom function public void ReleaseArrowSetting() { StopAllCoroutines(); gameObject.SetActive(false); arrowRigidbody.velocity = Vector3.zero; arrowRigidbody.angularVelocity = Vector3.zero; } #endregion } }