| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- using UnityEngine;
- using System.Collections;
- public class Arrow : MonoBehaviour
- {
- [Header("Arrow Settings")]
- public float flightSpeed = 20f;
- public GameObject arrowModel; // Assign arrow 3D model
- private Vector3 targetPosition;
- private Character targetCharacter;
- private int damage;
- private bool isFlying = false;
- private bool hasLanded = false;
- private Vector3 impactDirection;
- private Collider targetCollider;
- private Vector3 arrowStartPosition;
- public void Initialize(Vector3 startPos, Vector3 hitPoint, Character target, int damageAmount)
- {
- transform.position = startPos;
- arrowStartPosition = startPos;
- targetCharacter = target;
- targetPosition = hitPoint;
- damage = damageAmount;
- // Store direction and collider for later
- impactDirection = (hitPoint - startPos).normalized;
- targetCollider = target.GetComponent<Collider>();
- transform.LookAt(targetPosition);
- StartCoroutine(FlyToTarget());
- }
- public void InitializeMiss(Vector3 startPos, Vector3 missPos)
- {
- transform.position = startPos;
- arrowStartPosition = startPos;
- targetCharacter = null;
- // Raycast down from missPos to find ground
- RaycastHit groundHit;
- if (Physics.Raycast(missPos + Vector3.up * 10f, Vector3.down, out groundHit, 50f, LayerMask.GetMask("Ground")))
- {
- targetPosition = groundHit.point;
- }
- else
- {
- // No ground found, destroy arrow
- Destroy(gameObject);
- return;
- }
- // Point arrow toward miss position on ground
- Vector3 direction = (targetPosition - startPos).normalized;
- transform.LookAt(targetPosition);
- StartCoroutine(FlyToTarget());
- }
- private IEnumerator FlyToTarget()
- {
- isFlying = true;
- Vector3 startPosition = transform.position;
- float journeyLength = Vector3.Distance(startPosition, targetPosition);
- float journeyTime = journeyLength / flightSpeed;
- float elapsedTime = 0f;
- while (elapsedTime < journeyTime && !hasLanded)
- {
- elapsedTime += Time.deltaTime;
- float fractionOfJourney = elapsedTime / journeyTime;
- // Move arrow toward target
- transform.position = Vector3.Lerp(startPosition, targetPosition, fractionOfJourney);
- yield return null;
- }
- // Arrow has reached target
- Land(journeyLength);
- }
- private void Land(float journeyLength = 2f)
- {
- isFlying = false;
- hasLanded = true;
- // If we hit a character, apply damage
- if (targetCharacter != null && targetCharacter.IsTargetable && damage > 0)
- {
- targetCharacter.TakeDamage(damage);
- Debug.Log($"=== ARROW IMPACT ===");
- Debug.Log($"Arrow hits {targetCharacter.CharacterName} for {damage} damage!");
- Debug.Log($"Target Health After: {targetCharacter.CurrentHealth}/{targetCharacter.MaxHealth}");
- Debug.Log($"=== END ARROW IMPACT ===");
- // Raycast from current arrow position forward to find actual hit point on collider
- Vector3 rayOrigin = arrowStartPosition;
- Vector3 rayDir = impactDirection;
- RaycastHit hitInfo;
- Vector3 finalHitPoint = transform.position;
- if (targetCollider != null && targetCollider.Raycast(new Ray(rayOrigin, rayDir), out hitInfo, journeyLength))
- {
- finalHitPoint = hitInfo.point;
- }
- // Move arrow to the actual hit point
- transform.position = finalHitPoint;
- // Stick arrow to target at the hit point and preserve world position/rotation
- Quaternion worldRot = transform.rotation;
- transform.SetParent(targetCharacter.transform, true);
- transform.position = finalHitPoint;
- transform.rotation = worldRot;
- Debug.Log($"Arrow hits {targetCharacter.CharacterName} at {finalHitPoint} for {damage} damage!");
- }
- else
- {
- Debug.Log("=== ARROW MISS ===");
- Debug.Log("Arrow misses and lands on the ground!");
- Debug.Log($"=== END ARROW MISS ===");
- }
- // Make arrow inactive but visible
- Collider arrowCollider = GetComponent<Collider>();
- if (arrowCollider != null)
- {
- arrowCollider.enabled = false;
- }
- // Disable rigidbody if present
- Rigidbody arrowRb = GetComponent<Rigidbody>();
- if (arrowRb != null)
- {
- arrowRb.isKinematic = true;
- }
- }
- public bool IsFlying => isFlying;
- public bool HasLanded => hasLanded;
- }
|