(edit: gif was too big!)
I’m sure this is a bad way to do it and no doubt I’ll regret it later, but I had fun making the arrows stay in the enemy model instead of destroying on collision.
If anyone wants to recreate it, I added:
- A bool so that movement only occurs if the arrow is still intended to be travelling, i.e. wrapped an IF statement around the transform lines in Update
- A line to change the parent of the projectile to be the ‘Spine_01’ object of the target upon collision with a disgustingly long GetChild() chain. I didn’t want to do it by string-search but if arrows are ever meant to hit other models, this will stop working. The reason I wanted to use the Spine_01 object was so that the arrows move with the model as it jostles about during animations. Parenting it at the root level made it look as if it were floating inside the model
- An “ArrowProjectile” tag since it looks like non-arrow projectiles are going be implemented next, and I wouldn’t want to have fireballs stick to enemies in the same way
Here’s my code:
public class Projectile : MonoBehaviour
{
[SerializeField] float projectileSpeed = 1f;
Health target = null;
float damage = 0;
bool inFlight = true;
void Update()
{
if(target == null) return;
if(inFlight)
{
transform.LookAt(GetAimLocation());
transform.Translate(Vector3.forward * projectileSpeed * Time.deltaTime);
}
}
public void SetTarget(Health target, float damage)
{
this.target = target;
this.damage = damage;
}
private Vector3 GetAimLocation()
{
CapsuleCollider targetCapsule = target.GetComponent<CapsuleCollider>();
if(targetCapsule == null) return target.transform.position;
return target.transform.position + Vector3.up * targetCapsule.height / 2;
}
private void OnTriggerEnter(Collider other) {
if(other.GetComponent<Health>() != target) return;
target.TakeDamage(damage);
inFlight = false;
//arrow childed to Spine_01 object, will probably break later!
if(gameObject.tag == "ArrowProjectile")
{
gameObject.transform.SetParent(target.transform.GetChild(0).GetChild(1).GetChild(0).GetChild(2));
}
else
{
Destroy(gameObject);
}
}
}
There’s a few quirks of course, like that arrows seem to ‘stick’ at differing frames which honestly makes for some nice randomisation