Evening all I was working on my own solution to Rick’s challenge in Projectile.cs and thought I’d share it. My code doesn’t check if the target hit is the target; instead, it just looks for a target with a Health component, and if one exists, applies damage as appropriate. This way, if a damageable target comes in between you and your true target, it will take damage first. (I’d like to say I was trying to design it this way, but I didn’t know that you could compare two similar components to see if they were the same… silly me! forehead smack and thoughts of V8) Anyway, the downside of this was that fewer than half of the arrows made it far enough away from the player to damage the enemy, the rest triggering (and damaging) said player, so my solution was to start each projectile with its box collider disabled, and then enable it after a set time using a Coroutine. (I’ll post the code in a moment). I also cached the reference to the target’s Capsule Collider in the SetTarget() method so that it won’t be called repeatedly during Update (this may be done in a later refactor, but I’ve heard it’s good practice to avoid getting components in Update, so voila!) Anyway, here’s the code. I’d appreciate any comments, suggestions, corrections, quips, or mild sass Cheers!
using System.Collections;
using RPG.Core;
using UnityEngine;
namespace RPG.Combat {
public class Projectile : MonoBehaviour {
[SerializeField] float projectileSpeed = 5f;
[SerializeField] float targetHeightDivisor = 1.5f;
[SerializeField] float enableColliderAfter = 0.5f;
CapsuleCollider targetCollider;
Transform target;
float damage = 0f;
void Update() {
if (targetCollider == null) { return; }
transform.LookAt(GetTargetPosition());
transform.Translate(Vector3.forward * projectileSpeed * Time.deltaTime);
}
public void SetTarget(Transform target, float damage) {
this.target = target;
this.damage += damage;
targetCollider = target.GetComponent<CapsuleCollider>();
StartCoroutine(ActivateCollider());
}
Vector3 GetTargetPosition() {
if (targetCollider == null) { return target.position; }
return target.position + Vector3.up * targetCollider.height / targetHeightDivisor;
}
void OnTriggerEnter(Collider other) {
if (other.TryGetComponent<Health>(out Health targetHealth)) {
targetHealth.TakeDamage(damage);
Destroy(gameObject);
}
}
IEnumerator ActivateCollider() {
yield return new WaitForSeconds(enableColliderAfter);
GetComponent<BoxCollider>().enabled = true;
}
}
}