- Home /
Melee Combat - Collision Detection
Im stuck.. I have a player and all my enemies tagged with "enemy"! Now Ive been searching, trying collision scripting but all ive managed to do was delete the game object on collison, I want to be able to press F and make the Attack function work! Detect if Im near an enemy and if there are any near me in my collision, call the function.. Seems easy right? Im new to this bout 5 days ago so any help please!! C# Script -
using UnityEngine;
using System.Collections;
public class PlayerAttack : MonoBehaviour {
public GameObject target;
public float attackTimer;
public float coolDown;
// Use this for initialization
void Start () {
attackTimer = 0;
coolDown = 2.0f;
}
// Update is called once per frame
void Update () {
if(attackTimer > 0)
attackTimer -= Time.deltaTime;
if(attackTimer < 0)
attackTimer = 0;
//attack press F key
if (Input.GetKey (KeyCode.F)) {
if(attackTimer == 0) {
Attack();
attackTimer = coolDown;
}
}
}
// CHANGE TO HIT NEAREST ENEMY?? IDK HOW MAN!!!
private void Attack() {
AttackandHP eh = (AttackandHP)target.GetComponent ("AttackandHP");
eh.AdjustCurrentHealth (-2);
}
}
Your not actually doing any collision detection.
Is the game using 2D colliders or 3D colliders?
Go on god damn google and search "find closest gameObject with tag" and check if that gameObject is close enough and if you are hitting the F button and damage that object.
Answer by fafase · Dec 23, 2013 at 09:32 PM
One problem will rise using the closest enemy, how do you hit to enemy with one melee if they are next to each other? Even though they are both in range, only the closest one is taken care of, which is not what the player expect to happen.
So what you could do is add a sphere collider to your player, set it to trigger, this sphere would have the radius matching the melee range. Then there you go:
List<GameObject>nearEnemy = new List<GameObject>();
void OnTriggerEnter(Collider col)
{
if(col.gameObject.tag == "Enemy")nearEnemy.Add(col.gameObject);
}
void OnTriggerExit(Collider col)
{
if(col.gameObject.tag == "Enemy")nearEnemy.Remove(col.gameObject);
}
Now you can add this below as an animation event http://docs.unity3d.com/Documentation/Components/animeditor-AnimationEvents.html so that it happens at an appropriate time during the melee animation.
void Melee()
{
Vector3 pos = transform.position;
for(int i = 0; i < nearEnemy.Count;i++)
{
Vector3 vec = nearEnemy[i].transform.position;
Vector3 direction = vec - pos;
if(Vector3.Dot(direction, transform.forward)<0.7))
{
nearEnemy[i].GetComponent <AttackandHP>().ApplyDamage(damage);
}
}
}
All it does is going through any enemy that is within the sphere and check with dot product if the guy is on the front at the time of call.
Where do I place these codes and are they javascript?
They go on the player and it is C#. Pretty simple to convert though.
I've used a solution similar to this one, but I find that it fails to calculate hits for GameObjects that are wider than an average human. When attacking the broad side of a gate, door, barricade,etc. the Dot product fails to calculate a hit because the player is attacking the side/corner ins$$anonymous$$d of facing the body position/root position (target's center).
The only way I can think to solve this is to get the Dot product and then RayCast toward the target as a redundant measure, but this becomes very expensive at runtime.
Does any have a better idea of a more reliable means of calculating a hit for normal sized and large sized targets?
I think you can also calculate the enemy's transform and its relation to the player's position
In world space, playertransformposition - enemytransformposition will acquire you the vector's position that you can use in localspace in relation to the player's forward direction vector. You can then compare this two vector's angle in localspace, and as long as it is within a certain angle, you can then register the attack as hit or not, hit forward or back, etcs.
Answer by Divine · Dec 23, 2013 at 08:02 PM
The second example should work out of the box. Just replace
AttackandHP eh = (AttackandHP)target.GetComponent ("AttackandHP");
with
AttackandHP eh = FindClosestEnemy.GetComponent<AttackandHP>();
Always use the generic one. Always.
Two errors. I added the second code and replaced the attack one. BTW Thank you very much for taking the time to help, appreciate it man!
error CS0119: Expression denotes a method group', where a
variable', value' or
type' was expected
error CS0165: Use of unassigned local variable `closest'
Your answer
Follow this Question
Related Questions
melee combat 0 Answers
How can i detect collision in melee combat? 2 Answers
Best way to detect sword hit 0 Answers
IK for Precise Parrying Animations - Sword Combat System 1 Answer
Full Performance On Melee Combat 0 Answers