Hello, My game has a melee combat system. I parented the melee weapon to the hand bone and gave the weapon a "weapon" script. I gave a box a "health" script. I want to make it so when I hit the box the box loses health. I was thinking about using triggers, but I only want the box to lose health if the object colliding with the box has the "weapon" script and during the players attack animation state. How would I go about doing this?
You check the distance between the player and the box, if for example the box is 5 m away from the player and the player presses LMB you decrease its damage. If the health is in a different script you can go around by using GetComponent Code (CSharp): scriptName variablename; void Start() { variablename = GetComponent<scriptName>(); } void Update() { if(Vector3.Distance(transform.position, enemyGameObject.transform.position) <= 5.0f && Input.GetKeyDown(KeyCode.Mouse0)) //transform.position is the position of the player in case the script is attached to him { variableName.Health -= damage; } } Note that it doesn't check if the box is in the player field of view as checking if an object is in the field of view never worked for me. You have to set the health variable to public.
Triggers are the way to go. You just described in plain English exactly what the code will need to do. Tick Is Trigger on your box's collider. Then add an OnTriggerEnter() method to your health script, like in the example below. (Warning -- I just typed this into the reply; it could have typos.) Code (csharp): void OnTriggerEnter(Collider other) { var weapon = other.GetComponent<Weapon>(); if (IsAttacking(other.gameObject) && (weapon != null)) { LoseHealth(weapon.damage); } } bool IsAttacking(GameObject go) { var animator = go.GetComponentInParent<Animator>(); return (animator != null) && animator.GetCurrentAnimatorStateInfo(0).IsName("Attacking"); } The code above assumes that: Your weapon script is named Weapon, and has a property named damage. You're using Mecanim, and the attack state is on layer 0 and named "Attacking".
The above post works, but keep in mind your actual attack animation if you are going to parent your trigger to your weapon. An issue I was running into with triggers is that my attack animation was so fast (the swing was 4-5 frames) that the collision was not being registered. The trigger on my weapon would jump from frame 3-4 for example and completely "pass through", or jump from one side to the other, of the enemy. In that case it was just better to have the trigger be parented to my player, just in front of him, and have it "float" in the direction I wanted to attack.
would it be possible to use a raycast from the hands with a length of the blade to determine if contact is made during the animation??
Yes, its done easily. Create two bones - start, end, then find if there is any other collider between position of these bones. I suppose you can code it easily.
To improve collision detection, set Collision Detection to Continuous for fast-moving objects. Depending on your fixed update interval and other factors, this might resolve the issue with fast sword swings. It adds a little overhead to Physics. You could also raycast from the hands. But you'd really want to do something like a CapsuleCast or multiple rays. Here's the reason: Say the player swings his sword down really fast. One frame 1, the player's sword is over his head. On frame 2, the player's sword is down between his enemy's knees. On both frames, the sword is not in contact with the enemy. But between frame 1 and frame 2, the sword must have passed down through the enemy's head and body. If you do a single raycast on frame 1 or frame 2, you won't detect the hit. Instead, on frame 1, record the position of the sword. On frame 2, run a CapsuleCast from frame 1's position to frame 2's position. This basically covers the entire arc. I say "basically" because it casts in a straight line, whereas the sword probably moves in a slight curve. But in practice the difference shouldn't be noticeable. The size of the capsule for the CapsuleCast should be roughly the size of the sword's blade.