OldBlueWater/BlueWater/Assets/02.Scripts/Arrow.cs

159 lines
5.2 KiB
C#
Raw Normal View History

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
}
}