- Home /
How do I go about storing the last hit of a raycast and then using it for other stuff it on a character?
For example, I have characters with appropriately tagged colliders attached to their bones. Say the raycast hits an arm collider or head collider AND that hit kills the character (reduces their health to zero) and I'd like to play a specific animation depending on the collider that is hit by the killing shot. Pseudo code something like, "if the last hit was arm collider and it kills character, then play specific animation (or just return a boolean, whatever). I'm using C#, by the way
Answer by sevensixtytwo · Oct 01, 2014 at 03:55 AM
You could have a variable (maybe a String or even an Int) and update it when hitting your target. I prefer making a kill function that uses that variable in order to play a different Animation.
//Enemy script
function Kill (loc:int) {
//0 is for body, 1 is for right arm, -1 is for left arm, etc
//play animation based on loc
if (loc == 0) {
//play body hit death animation
}
}
You then tag your colliders properly like "ArmRight" or "Body."
//Bullet Script
OnTriggerEnter (col:Collider) {
if (col.tag == "Body") {
col.GetComponent(EnemyScript).Kill(0);
}
if (col.tag == "ArmRight") {
col.GetComponent(EnemyScript).Kill(1);
}
if (col.tag == "ArmLeft") {
col.GetComponent(EnemyScript).Kill(-1);
}
//And so on
}
Heck, you could put all the different animations in an array and call them by index!
Answer by Alec-Slayden · Oct 01, 2014 at 04:30 AM
If you're talking about a RaycastHit array from something like RaycastAll, and you want to know what the farthest object hit was (last hit object), you might be looking for this answer, where Mike 3 details how you can create a custom comparer to sort the builtin array returned by RaycastAll, so they are ordered by distance.;
If you are talking about simply registering whether a single raycast hit was a killing shot, I would recommend having health and death control on the character being shot at, not the weapon being fired.
For example, don't have the weapon say "If the last hit was the arm and the character is killed, tell it to play animation X",
I would recommend the weapon say "Hey, character, you're being shot at collider Y."
Then the character can say "Ok, thanks, I'll take care of the rest."
For example the weapon could have something like this:
void OnFireWeapon()
{
RaycastHit hitInfo;
Vector3 forward = transform.TransformDirection(Vector3.forward);
if (Physics.Raycast(transform.position, forward, out hitInfo, 100f) )
{
CharScript character = hit.transform.GetComponent<CharScript>();
character.OnShotByWeapon(this, hitInfo.collider);
}
}
If your character has a rigidbody attached, and a CharScript attached to handle health etc, then it shouldn't matter where it gets shot, the weapon will always be able to find the CharScript on the parent, and call that method. This is assuming you are using a rigidbody on your character; This is because the child colliders that create the limbs form a compound collider, which returns the parent rigidbody's transform in raycasts.
You can then alert the character that it has been shot, and tell it specifically where, by passing the collider. The character could have something like this to respond:
public void OnShotByWeapon(WeaponScript weapon, Collider limb)
{
//don't bother if already dead.
bool alreadyDead = Health <= 0;
if (alreadyDead) return;
// apply damage modifiers and death or hit animations
// here the name is checked, but you can compare limb.gameObject
// to preset gameobject vars instead, or something.
int baseDamage = weapon.Damage;
switch (limb.name)
{
case "Head":
Health -= baseDamage * 2;
if (Health <= 0)
HeadShotDeath.Play();
else
HeadShot.Play();
break;
case "LeftArm":
Health -= baseDamage;
if (Health <= 0)
LeftArmShotDeath.Play();
else
LeftArmShot.Play();
break;
default:
Health -= baseDamage;
if (Health <=0)
DefaultDeath.Play();
else
DefaultShot.Play();
break;
}
}