- Home /
Diablo 3 style melee combat
Hello everybody, Im really curious on perfecting a simple melee combat sandbox similar to diablo 3. I worked on it over the last weekend and my current state of affairs is such :
https://www.youtube.com/watch?v=qe9vWksrtOQ
This approach was very scrappy, but I tried a lot of different variations.
I want to emphises that Im working on gamepad, not a click to point mechanic which I feel is much more simpler.
My first try was to use physics based collision detection using collisions. I didnt enjoy this at all and quickly realised that while this leads to real time combat this is not great for game design etc because i wasnt able to hit people until i was right on top of them and I did try playing around with the colliders etc but it just didnt feel natural.
My second approach was to use a hit frame and cast a sphere cast at the point where I my animation was at the most obvious point where it would impact, and then check all the colliders in the sphere at that particular frame and do damage. I was also not happy with this situation because again it really did depend a lot on the position of my player and since my player is right handed etc It was easier to kill enemies to my right then left etc and once again I was having a really hard time rotating my player such that I could hit the enemy, once again undesirable.
Next I went and got diablo 3 on my console and tried it out. I really wanted to see how they were tackling this issue so I realized that there is some sort of auto assist going on. That made sense. So, In the video you see above my current solution was to - keep a list of all the enemies within a certain radius of my player, this was 2.5 units or so. - of the enemies in that radius, I would find out the one which is nearest to me. - and auto rotate my player to look at that enemy.
This meant that if I went up to the enemy or if the enemy came up to me, my player would automatically look at it. With this I tried the colliders and sphere cast approach and still I wasnt getting the result I wanted so I went with a simple approach of distance. You can see the results i got in my video.
Now I could do a further simple test for field of view and thats fairly simple to make sure that the enemies who get hit are only in front of me which is good. In the current state when I attack, my player is looking towards the closest enemy, and it plays the attack animation and all the enemies in a certain radius get damaged and i spawn particle effects to each enemy damage make this a little less visible but also give visual feedback as to who is getting damaged. This is the best I have so far but I am still not happy with it. Furthermore even though this "looks" okay I am having problems doing damage calculations. Because irrespective of my animation and distance all the enemies in the radius lose health at the same time and you can image if I spawn a hit animation now on my enemies, all of them play that animation which looks fine for the one Im looking at but the sudden drop in life and hit animations for those to my right and left etc look dumb.
This is a link to a unity discussion which I found somewhat helpful but it rather reaffirmed my faith in my approach but as I said I still have many other issues: https://forum.unity.com/threads/collider-or-ray-cast-for-melee-weapons.252362/
This is the link to a gameplay video on ps4 of diablo 3: https://www.youtube.com/watch?v=ljpVk8zHbHw
In my current solution i can move and attack as well, Im using layer masks to implement this, but when I am moving around and attacking it doesnt work, maybe its having a hard time calculating the nearest enemy etc but i have to stop and attack. I also noticed that in d3 they seem to stop the person while hes attacking. Which is fine I suppose its not very hard to do.
In response to your P$$anonymous$$, it sounds like you're following the right process here. I don't mean the technical solution, I mean the fact that you're trying things, seeing what you do and don't like about them, changing your approach, and looking into how others have got results you like.
If you've only been working in it for "the last weekend" then I think you're doing pretty well!
I'm going to have a crack at an answer below, but keep the following in $$anonymous$$d: - I'm not seeing a specific question written in your post, so I may end up answering the wrong thing. - You haven't said the specific result you're looking for, so I'm guessing at that.
So the specific result that Im looking for is something similar to the diablo 3 gameplay. Not looking into a million different weapon type/stats/ranges etc at the moment. At the moment here is what I want:
Character single wielding an axe/sword in his hand. When I swing my sword I should hit an enemy if in range every single time I the user legitimately expect to hit him, have a particle effect spawn as a visual aid, play the hit animation on my enemy, and reduce his life. The hit animation and life reduction should seem like they are happening at the time of impact of my weapon and the reason I say it should seem that way is because I want to solve this using the distance approach we have been discussing and not actual collider/triggers.
Answer by angrypenguin · Dec 10, 2017 at 11:23 PM
[Alas, the formatting here seems busted...]
In the thread that you linked there's a suggestion, from me :-), to use a simple series of checks:
Is the enemy close enough?
Are they within my angle of attack?
Is there a clear line between you and them?
If the answers are all "yes" then deal some damage. If any answer is no, then don't.
That's pretty easy if there's only one enemy, so selection of an enemy in a group is important. This is tricky, though, as you'll probably want different rules for each weapon. A shortsword is probably used to attack a single enemy directly in front. A greatsword might be used to swipe at enemies in a larger arc. A spear might be used to attack enemies at medium distance, potentially behind other enemies.
I've not done this before, I can think of a couple of approaches to start trying.
One is to give each weapon a range, an angle, and a boolean for being able to attack multiple targets simultaneously. Then you just take those rules into account in the same logic as above. For single-target weapons you get the closest enemy (accounting for both distance and angle, so tweak a formula until it feels good for that) and just deal damage to them. For multi-attack weapons you find all of the enemies in that area and damage them all, potentially with some distance-based falloff.
Another is to give each weapon an attack position transform, and simply damaging the enemy or enemies closest to that at the appropriate time. You can move the point, and you can again account for single or multiple hits.
In either case, I'd keep a list of enemies who have been damaged by the current attack so that you can avoid multi-hitting the same enemy.
You also mentioned timing in there. That's only really important for attacks that hit in large arcs, right? In those cases you should be able to figure out where in the arc your damage should currently be getting dealt, thus dividing your attack's area into "already hit" and "not hit yet" areas. With that and the list of enemies already damaged by the attack, you can now apply damage to anyone in the "already hit" area who haven't yet been damaged. Depending on the attack type that can all be done with simple math based on either angle or distance.
One last thing, I personally don't know if I'd like auto-turning/aiming on my character unless there was an explicit target selection system. I'd want attacks to go where I was holding the stick, and to have enough leeway that I could reliably and quickly aim that way. I really dislike it in games when I'm trying to attack a specific enemy but the "assistance" systems keep getting me stuck on other things instead.
I hope that something in there is helpful to some of what you're trying to figure out.
Answer by hasannagaria321 · Dec 11, 2017 at 08:15 AM
@angrypenguin Thanks for the speedy response! Ill try and experiment with the things you mentioned and wrap my head around them. If I have some questions Ill update here, for example I can already think Ill have problems with the multiple enemy hit arc solution you suggested but ill try it first.
As for your last suggestion, since thats the one I can answer now, to be honest I also dont want auto aiming/turning if I can make a robust enough melee attack system where I can reliably hit the enemy that I expect to hit. I noticed in diablo 3 the auto-assist is tuned to such an amount that the user doesnt even realise its there and its very seemless.
Okay, lets just consider one enemy in the first iteration. 1 - User Input: Attack button pressed, attack animation played.
2 - Check - Is the enemy close enough? yes 3 - Check - Are they within my angle of attack? yes 4 - Check - Is there a clear line between you and them? yes
how do i reconcile these two? should all these checks be in a "hit frame" where I fire off an animation even which checks for all three? if the three return true I go on with
5 - Deal Damage 6 - Play enemy hit animation.
Also i dont understand, if i think about the one attack hits only one enemy situation what if i have multiple enemies? without auto aim etc how do i know which enemy to subtract from? I mean what if there are two enemies close enough, in my angle and i have a clear LOS to both. How do I now deter$$anonymous$$e which one to strike, naturally it should either be the one which is closer or the one im kind of facing more than the other etc. How do i do that?
I dont know why Im having such a hard time with this problem, is it just a hard situation to solve?