Arrow.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. using UnityEngine;
  2. using System.Collections;
  3. public class Arrow : MonoBehaviour
  4. {
  5. [Header("Arrow Settings")]
  6. public float flightSpeed = 20f;
  7. public GameObject arrowModel; // Assign arrow 3D model
  8. private Vector3 targetPosition;
  9. private Character targetCharacter;
  10. private int damage;
  11. private bool isFlying = false;
  12. private bool hasLanded = false;
  13. private Vector3 impactDirection;
  14. private Collider targetCollider;
  15. private Vector3 arrowStartPosition;
  16. public void Initialize(Vector3 startPos, Vector3 hitPoint, Character target, int damageAmount)
  17. {
  18. transform.position = startPos;
  19. arrowStartPosition = startPos;
  20. targetCharacter = target;
  21. targetPosition = hitPoint;
  22. damage = damageAmount;
  23. // Store direction and collider for later
  24. impactDirection = (hitPoint - startPos).normalized;
  25. targetCollider = target.GetComponent<Collider>();
  26. transform.LookAt(targetPosition);
  27. StartCoroutine(FlyToTarget());
  28. }
  29. public void InitializeMiss(Vector3 startPos, Vector3 missPos)
  30. {
  31. transform.position = startPos;
  32. arrowStartPosition = startPos;
  33. targetCharacter = null;
  34. // Raycast down from missPos to find ground
  35. RaycastHit groundHit;
  36. if (Physics.Raycast(missPos + Vector3.up * 10f, Vector3.down, out groundHit, 50f, LayerMask.GetMask("Ground")))
  37. {
  38. targetPosition = groundHit.point;
  39. }
  40. else
  41. {
  42. // No ground found, destroy arrow
  43. Destroy(gameObject);
  44. return;
  45. }
  46. // Point arrow toward miss position on ground
  47. Vector3 direction = (targetPosition - startPos).normalized;
  48. transform.LookAt(targetPosition);
  49. StartCoroutine(FlyToTarget());
  50. }
  51. private IEnumerator FlyToTarget()
  52. {
  53. isFlying = true;
  54. Vector3 startPosition = transform.position;
  55. float journeyLength = Vector3.Distance(startPosition, targetPosition);
  56. float journeyTime = journeyLength / flightSpeed;
  57. float elapsedTime = 0f;
  58. while (elapsedTime < journeyTime && !hasLanded)
  59. {
  60. elapsedTime += Time.deltaTime;
  61. float fractionOfJourney = elapsedTime / journeyTime;
  62. // Move arrow toward target
  63. transform.position = Vector3.Lerp(startPosition, targetPosition, fractionOfJourney);
  64. yield return null;
  65. }
  66. // Arrow has reached target
  67. Land(journeyLength);
  68. }
  69. private void Land(float journeyLength = 2f)
  70. {
  71. isFlying = false;
  72. hasLanded = true;
  73. // If we hit a character, apply damage
  74. if (targetCharacter != null && targetCharacter.IsTargetable && damage > 0)
  75. {
  76. targetCharacter.TakeDamage(damage);
  77. Debug.Log($"=== ARROW IMPACT ===");
  78. Debug.Log($"Arrow hits {targetCharacter.CharacterName} for {damage} damage!");
  79. Debug.Log($"Target Health After: {targetCharacter.CurrentHealth}/{targetCharacter.MaxHealth}");
  80. Debug.Log($"=== END ARROW IMPACT ===");
  81. // Raycast from current arrow position forward to find actual hit point on collider
  82. Vector3 rayOrigin = arrowStartPosition;
  83. Vector3 rayDir = impactDirection;
  84. RaycastHit hitInfo;
  85. Vector3 finalHitPoint = transform.position;
  86. if (targetCollider != null && targetCollider.Raycast(new Ray(rayOrigin, rayDir), out hitInfo, journeyLength))
  87. {
  88. finalHitPoint = hitInfo.point;
  89. }
  90. // Move arrow to the actual hit point
  91. transform.position = finalHitPoint;
  92. // Stick arrow to target at the hit point and preserve world position/rotation
  93. Quaternion worldRot = transform.rotation;
  94. transform.SetParent(targetCharacter.transform, true);
  95. transform.position = finalHitPoint;
  96. transform.rotation = worldRot;
  97. Debug.Log($"Arrow hits {targetCharacter.CharacterName} at {finalHitPoint} for {damage} damage!");
  98. }
  99. else
  100. {
  101. Debug.Log("=== ARROW MISS ===");
  102. Debug.Log("Arrow misses and lands on the ground!");
  103. Debug.Log($"=== END ARROW MISS ===");
  104. }
  105. // Make arrow inactive but visible
  106. Collider arrowCollider = GetComponent<Collider>();
  107. if (arrowCollider != null)
  108. {
  109. arrowCollider.enabled = false;
  110. }
  111. // Disable rigidbody if present
  112. Rigidbody arrowRb = GetComponent<Rigidbody>();
  113. if (arrowRb != null)
  114. {
  115. arrowRb.isKinematic = true;
  116. }
  117. }
  118. public bool IsFlying => isFlying;
  119. public bool HasLanded => hasLanded;
  120. }