Modular Combo System for Combat in Unity

แชร์
ฝัง
  • เผยแพร่เมื่อ 22 ม.ค. 2025

ความคิดเห็น • 80

  • @thegamedevcave
    @thegamedevcave  2 ปีที่แล้ว +16

    anyone getting an error like this : error ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
    try to change the if statment to this :
    if(comboCounter +1 > combo.Count)
    {
    comboCounter = 0;
    }

    • @KandyMan90
      @KandyMan90 ปีที่แล้ว +6

      The bug is actually on line 29, the if statement should just check if it is less than combo.Count instead of less than or equal. If a list has 15 items in it you can access it using index 0-14, by checking less than or equal you allow it to proceed using index 15. You can then change line 41 to if comboCounter >= combo.Count and the error should be fixed

    • @thegamedevcave
      @thegamedevcave  ปีที่แล้ว

      @@KandyMan90 much more elegant fix for the issue for sure!

    • @fungalforest
      @fungalforest ปีที่แล้ว

      It worked for me! thank you very much!

    • @Ebrodrool
      @Ebrodrool 9 หลายเดือนก่อน

      THanks so much!!! That really helped.

  • @mesolagic
    @mesolagic 9 วันที่ผ่านมา

    Really flexible system! Thanks for sharing it :D I think I'll use this method for handling my player's attack combos.

  • @mrtaki998
    @mrtaki998 16 วันที่ผ่านมา +1

    For anyone who faced a similar problem to mine, where you can spam the combo even after t was done, just add to the counter > combo.Count if statement an invoke of the endCombo function, as that will force the character to stop hitting for the cool down duration.

  • @balbuzio
    @balbuzio ปีที่แล้ว +2

    this is great stuff, its always there small underrated channels that have the best content

  • @areallyboredindividual8766
    @areallyboredindividual8766 ปีที่แล้ว +2

    Fantastic channel, for a few different mechanics I've been working on it's been something from here that wound up helping. My PS2-era-inspired character action-survival horror hybrid may come out after all

    • @thegamedevcave
      @thegamedevcave  ปีที่แล้ว

      great that I could help that sounds super interesting!

    • @HolBolt
      @HolBolt 5 หลายเดือนก่อน

      is it silent hill inspired?

  • @halivudestevez2
    @halivudestevez2 ปีที่แล้ว +2

    so much invaluable information can be learnt here, and a most professional approach has been shown! wow! Not a beginner stuff! But nice solution!

  • @thunderhawk4592
    @thunderhawk4592 ปีที่แล้ว +7

    Any way to make this spam proof cause if u spam it skips most of the animation and moves on the next

    • @thegamedevcave
      @thegamedevcave  ปีที่แล้ว +1

      as it is, this code already has a spam protection build in though, just one based on time, the Time.time - lastclickedtime

    • @GamerevGames
      @GamerevGames 10 หลายเดือนก่อน +3

      I know I'm late to the party and you probably figured this out... But add these lines right after CanelInvoke:
      var m_clipInfo = animator.GetCurrentAnimatorClipInfo(0);
      float clipLength = m_clipInfo[0].clip.length;
      Then instead of doing: Time.time - lastClickedTime >= 0.2f or whatever number, use "Time.time - lastClickedTime >= clipLength - 0.1"
      Hope this helps!

  • @Inferim
    @Inferim ปีที่แล้ว +1

    Awesome stuff! I'm currently designing a combo system using state machines and I'm having a difficult time figuring out how to sync the different animations properly(I'm using a SetTrigger system to play the animations). I'm still new to Unity and learning about that Animator.Play() function that takes a normalized value for its start time is a lifesaver!

    • @thegamedevcave
      @thegamedevcave  ปีที่แล้ว +1

      the only downside to using it could be that it doesn't (as far as i know) blend between animations, but personally I think that also can be an upside since it'll make animations (especially for a combat system) feel a little more "snappy". but it is something to keep in mind :)

    • @luciorojas4278
      @luciorojas4278 10 หลายเดือนก่อน

      @@thegamedevcave I was going to ask just this! about the blending and if it was possible

  • @Bobster536
    @Bobster536 ปีที่แล้ว +1

    real cool, leaving comment for algorithm luck!

  • @exoltia9085
    @exoltia9085 9 หลายเดือนก่อน

    when i played my animation, all the things work but my played can't move after that, he play de run animation but he can't move

  • @nikzadataei7102
    @nikzadataei7102 ปีที่แล้ว

    Hi, how would I go about setting the controller back to its original controller?

  • @patat7873
    @patat7873 9 หลายเดือนก่อน

    How does the Weapon Script refer to the damage value in the SO. It works, but how ? I would like to reproduce it but i dont get it.

    • @thegamedevcave
      @thegamedevcave  9 หลายเดือนก่อน

      the player character has an array that holds the scriptable objects, so it knows the order in which the attacks happen. so we already have easy references to those objects. the player also has a value to keep track of which attack it does (the combo counter) so we simply look up the so at the position in the array of the attack that we are currently doing, and read the damage value that is in that SO (or you can have a damage value on yoru character which gets updated from the SO whenever an attack starts, in the same way, get the reference from the array and jsut read the public variable for damage on the SO)

  • @omernahum8336
    @omernahum8336 ปีที่แล้ว

    Thanks for the tutorial! great approach! One question though; I applied the Animator to the "Player" gameobject instead of the character itself (the children gameobject), like you did here, but because the animations require Root Motion, the animations look messy.
    When I apply the Animator to the character itself, the animations work more smoothly, but then the position of the Player gameobject is not aligned with the character's (children), causing the character to start from different places every time the character moves.
    What is the best practice and how to solve it?

    • @brandonmichael4105
      @brandonmichael4105 10 หลายเดือนก่อน

      If you go to the inspector and click on your animation tab of the model your using, you can select different root settings, when I have an animation that moves and I don't want it to because my script already does that, i adjust the root position or rotation. Use the preview window for an indication of how it will look, it shows a red circle where your position is

    • @renatosouza2741
      @renatosouza2741 หลายเดือนก่อน

      My solution for that was instead of "anim.Play" function I just used "anim.CrossFadeInFixedTime" in order to play the animation blending with the current one.
      That way it's way less jumpy and flacky.
      The fixedTime I've put somewhere between 0.2 and 0.3...

  • @QuantumVT
    @QuantumVT 10 หลายเดือนก่อน

    hey i just found this video and it works greats for my purposes but im having an issue where if you attack before the previous attack is finished it interrupts them and starts the new one
    any idea on how to prevent this?

    • @Jaskier13
      @Jaskier13 7 หลายเดือนก่อน

      Yes, although this method does not blend animations. Use another lastClicked float variable and check if the difference between that Time.time is greater than the length of the current animation being played. If it is true, assign the lastClicked variable to Time.time and run the Attack function shown in the video.

  • @Jaskier13
    @Jaskier13 7 หลายเดือนก่อน

    Hey great tutorial, but one thing I noticed is this does not blend the animations since it is not in a blend tree. Do you think I should make different blend trees for different combos if I want to blend the animations?

  • @nhlanganisotshabangu3774
    @nhlanganisotshabangu3774 3 หลายเดือนก่อน

    Amazing dude

  • @wasifalmeem4651
    @wasifalmeem4651 8 หลายเดือนก่อน

    Really great Tutorial, but i am still facing one issue, when i spam my mouse, the animation sometimes starts playing altogether even tho i copied your code. despite that no matter what settings i set, when i spam the mouse button, it sometimes mixup the animations

    • @Jaskier13
      @Jaskier13 7 หลายเดือนก่อน

      Yeah, that was one thing even I faced. This is how I solved it, although this method does not blend animations.
      Use another lastClicked float variable and check if the difference between that Time.time is greater than the length of the current animation being played. If it is true, assign the lastClicked variable to Time.time and run the Attack function shown in the video.

  • @AbachiriProduction
    @AbachiriProduction ปีที่แล้ว

    hi bro i have i problem : Animator.GotoState: State could not be found UnityEngine.Animator:Play (string,int,single). any ideas ?

    • @thegamedevcave
      @thegamedevcave  ปีที่แล้ว

      most likely one of the paramaters in the Play() fuction you're using isn't correct. usually it's a spelling mistake in the name (which is case sensitive, so maybe wrong capitalization)

  • @dip-c5z
    @dip-c5z ปีที่แล้ว

    sorry but there are errors in NullRefferenceException, Animator and Animation. I quadruple check everything but error still exist, deleted the project'

    • @thegamedevcave
      @thegamedevcave  ปีที่แล้ว +1

      unfortunate to delete the project and waste all the time you spent trying to fix things. that error sounds like it may not be an issue with the code itself, but rather the fact that you may have not put value's in for one or more of your variables or something along those lines.

  • @IJH-Music
    @IJH-Music ปีที่แล้ว

    Great tutorial!
    Would the "Up, Left and Right" Combat System from For Honor interest you?
    almost 10 years later, and Noone has done tutorials on For Honor Style Combat!

    • @thegamedevcave
      @thegamedevcave  ปีที่แล้ว

      not familiar with it but sounds interesting to look into!

    • @garulouie
      @garulouie 7 หลายเดือนก่อน +1

      Yo! Not sure if you're active as of writing, but reading up on For Honor's combat system (Haven't played it myself), It seems it works like Devil May Cry where when you lock onto an opponent you have unique attacks based on which movement direction you're holding. I think the following may help give a rough outline on how you can make a directional attack system using this video's system as a base:
      - Copy the attack function for each direction you want to have (Including 'neutral' attacks for when the player isn't holding a direction, or just make the forward attacks fire when not holding a direction) with their own unique attack list and combocount variables. (You can also make a total combatcount variable alongside the unique combocounts that goes up when any attack fires.) For my game, I made unique Attack function copies for light and heavy attacks, as well as variations for when the player is midair.
      - If a "Lock on to enemy" event fires (say for if a lock on button is pressed, or when a player enters an arena with one primary enemy), then find the enemy closest to your player and get their transform.
      - Make a bool to indicate if you've locked onto an enemy, and set it to true when you're locked on and false when you're not. When the bool is set to true, you disable the option to freely move the camera and you allow the directional attacks to fire if the player's holding a direction, something like "if the attack button is pressed, fire your neutral/forward attack. if attack is pressed, then if the lockon bool is true, then if the player's X movement axis is set to -1, fire your left directional attack, or if the player's x axis is set to 1, fire your right attack".
      - When the lockon bool is true, have your player object's model mesh look at the enemy's transform.
      - If you're using the cinemachine camera system, you can try setting the freelook camera's lookat value to the enemy's transform.
      I hope this helps!

  • @ahmedsiddique2998
    @ahmedsiddique2998 ปีที่แล้ว

    I have a question about your animation not playing fully if you click too fast Like attack_1 is not completed and you are going for attack 2, how shld i tackle this problem?

    • @thegamedevcave
      @thegamedevcave  ปีที่แล้ว +1

      in that case your time between allowing clicks is too low most likely. there is a bunch of things you can do about that.
      the code as it is designed now requires you to do an input during the previous attack animation to continue a combo, so having some part of the animation after the actual attack will help (the last 10-20% dedicated to not the actual attacking but the recovery (think with a sword slash, your character wills wing the sword but then need to balance himself as he overshoots a bit, aside from that helping the code, that's also how you generally make good animations).
      if for some reason that's not an option, you'll have to modify the code a little to include a timer that starts after an attack is finished and gives you X amount of seconds to do the next input to continue the combo and only allow that next attack input to be registered when you're not already doing your previous attack.
      Loong story short, this system assumes your animations dont instantly cut off after the attacking movement finishes because 99% of the time, you wouldn't want to do that when making an animation so the most straightforward way to help improve is the add some to the end of your animations, if you want to change the code itself you'll have to rework a pretty decent part of the input and reset related code.

    • @ahmedsiddique2998
      @ahmedsiddique2998 ปีที่แล้ว

      @@thegamedevcave thanks for the detail answer got your point :)

  • @minishouts272
    @minishouts272 ปีที่แล้ว

    animatorOV?
    need some help with this part at 12:40

  • @kingmurder8245
    @kingmurder8245 ปีที่แล้ว

    baldur gate 3 ad looking sweet tho

  • @dyguests
    @dyguests 5 หลายเดือนก่อน

    Creat! It's all I wanted.

  • @gxguy2906
    @gxguy2906 ปีที่แล้ว

    Do you think this will work on a 2d platformer using rigging bone? sorry am new to Unity

    • @thegamedevcave
      @thegamedevcave  ปีที่แล้ว +1

      anything using animation clips and the animator should work, 2D or 3D doesn't matter

    • @gxguy2906
      @gxguy2906 ปีที่แล้ว

      @@thegamedevcave Awesome! I'll try to implement this.

  • @csm12s
    @csm12s ปีที่แล้ว

    hi, do the animation attack1 and attack2 have a smooth transition?

    • @thegamedevcave
      @thegamedevcave  ปีที่แล้ว

      with this system they don't have a smooth transition, instead it'll cut from one to the other. changing thatto a system that transitions between animations modularly is a pretty major pain and in most cases probably not worth it. only if you have very big and slow movement can you actually tell the difference.
      So in order to keep things simple and easy to use this system just plays the animations without any transition time.

    • @ChapCanai
      @ChapCanai 11 หลายเดือนก่อน

      anim.CrossFade instead of anim.Play

  • @minishouts272
    @minishouts272 ปีที่แล้ว

    Will be tricky getting this one to work with Netcode for gameobjects, any thoughts?

    • @thegamedevcave
      @thegamedevcave  ปีที่แล้ว

      I'm not sure. I imagine you'd have to change a fair few things around to make it work for that

    • @minishouts272
      @minishouts272 ปีที่แล้ว

      @@thegamedevcave Got it working, ty for the video =]

    • @notvil1714
      @notvil1714 ปีที่แล้ว

      How did you manage? In my case only first attack is visible to the other player and then I'm also constantly getting this error:
      [DestinationState To Transition Info] Layer (2) does not exist!

    • @minishouts272
      @minishouts272 ปีที่แล้ว

      @@notvil1714 THe way I managed to pull this off is by using the animator and setting up a transition into a blend tree with all of the attacks I want to combo using a 1D blend Type. After that I created an indexer than will increment higher each time Attack() was called. Once the index was higher than the size of the 1D threshold, It resets back to 0 creating the attack loop. Should work for Netcode. Hope I explained it okay

    • @notvil1714
      @notvil1714 ปีที่แล้ว

      @@minishouts272 yeah i ended up doing something similiar but without the blendtree. Doesn't the 1D blend tree forces you to specify a maximum number of attack combo clips? Or there is some way to add motion to the 1D blend tree from script?

  • @vadandrumist1670
    @vadandrumist1670 2 ปีที่แล้ว

    Speaking of the combat system, how complex do you plan on making it? If I remember right you're juggling six weapons and a shield, but how much depth is each weapon to have?

    • @thegamedevcave
      @thegamedevcave  2 ปีที่แล้ว

      my system is a slightly more complex version of this. combines with a pokemon-like mechanics where certain weapons deal more damage against certain enemies. the combat itself differs mostly in the animations, how fast they are and the damage per hit. the actual weapons also have slightly different reach and all have a special attack that uses your MP (which is also used for healing).
      besides that , the normal attacks will at a base level always be the same combo but recently i've been working on some ideas to implement a more proximity based system, not as heavy as a game like Kingdom hearts though. What i'm thinking right now is much like you level up your own stats, you can level up your proficiency with a certain weapon (thinking it'll probably be 3 levels of upgrades per weapons). that'll unlock some more intelligent proximity based combat.
      by default you won't have anything, but maybe after leveling it up you'll do a special move slashing down on an enemy when the currently focused on enemy is below you, and at level 2 a circular attack around you when there is a number of enemies in your attacking range, etc. (with of course some minor differences between the weapons in exactly what new moves unlock and in what order they do, a heavy weapon like the hammer won't exactly make sense to get the same attacks as dual swords after all).
      I still expect for players with good timing that the shield will end up being the most powerful one though, i need to make sure that beating the boss that unlocks that as the first one is very hard XD

    • @vadandrumist1670
      @vadandrumist1670 2 ปีที่แล้ว

      @@thegamedevcave I see, much like how FF15 has enemies with specific weapon/element weaknesses. It's a mixed bag in my opinion. On one hand it encourages playing with all of the weapons, on the other it forces playing with specific weapons if you want to be efficient. Though if the weapons themselves don't have any outstanding features between one another these distinctions in weapons don't make a significant difference in gameplay, and therefore being forced to play with certain ones has less of a negative impact. Of course the weapons could all behave similarly with different results (such as all weapons have a lunge, but the lance lunges farthest while having the longest recovery on a wiff, the hammer having an aoe effect and leap while having the longest windup, dagger the shortest distance but fastest recovery, etc.), but in that case you'd probably be better off without the weapon-type weaknesses and instead make enemies different weapons are naturally more suited to.
      I would recommend making the intelligent proximity based combat (PBC) optional, specifically in giving an option allowing players to use the special moves manually. After all the more control the player has the higher the skill ceiling, and through skill, appreciable style. For example that circular attack might be only efficient against groups of enemies, but I could also see a player wanting to use it against a single target for a flashy finisher, and the downwards attack could possibly be used for rapid repositioning depending on how its executed.

  • @khnuxsora
    @khnuxsora ปีที่แล้ว

    hey can i use this for a 2D game?

    • @thegamedevcave
      @thegamedevcave  ปีที่แล้ว +2

      100%, the code itself doesn't really have much to do with 2D or 3D games so if you just use 2D animations in your animator it should work just fine :)

    • @khnuxsora
      @khnuxsora ปีที่แล้ว

      @@thegamedevcave thank you so much!

  • @antlermind
    @antlermind ปีที่แล้ว

    Wow! Awesome tutorial! I am having some slight issues with it though, currently, the system seems completely dependent on the 'Combo' array size, and once you've clicked through the number of attacks held within, Unity throws this error:
    ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
    Parameter name: index
    Anyone run into this and found a fix? I haven't spent much time on it, but what I've found is if there are 4 attacks held within the array, the error is thrown on your 5th click, if there are 2, error is thrown on your 3rd click. That's about all I've been able to pin down so far. Hope someone can help :)

    • @thegamedevcave
      @thegamedevcave  ปีที่แล้ว +1

      the pinned comment should help out with that i think, there's a small mistake in the code that causes that issue

    • @antlermind
      @antlermind ปีที่แล้ว

      @@thegamedevcave Oh... I don't know how I managed to miss that. Thank you so much for the awesome tutorial, and the helpful response :)

  • @abuzzakasm9767
    @abuzzakasm9767 ปีที่แล้ว

    Wow it was helpfull

  • @SlothHuntOnYou
    @SlothHuntOnYou 10 หลายเดือนก่อน

    why 60fps for tutorials=( everyone watch it on speed = 2x => 60fps breake it for fast surf timeline of the video=(

    • @thegamedevcave
      @thegamedevcave  10 หลายเดือนก่อน +1

      interesting point, never had anyone with this issue before. I make sure to edit my tutorials very tight and fast paced so there shouldn't be much need to watch at 2x speed.
      But there also isn't much reason to have a code tutorial be at 60fps, you're right.

  • @issue7278
    @issue7278 ปีที่แล้ว +1

    Love you bro You are best. But can you make a tutorial of Enemy Attack pattern just like 1st aatack then 2nd attack and then 3rd attack Like in a pattern there's no Video in youtube in this topic if you made it its a promise 20 new active suscriber for you by my side. plz made it a video

    • @thegamedevcave
      @thegamedevcave  ปีที่แล้ว +1

      really, what you're asking for is more or less than same iea as the system in this tutorial but instead of using it to change which attack animation the player runs, of course you'll do this with the different animations that the enemy has. if any attack needs to have special behavior (like also shooting a fireball or something) you can just make a function your enemy that does that and call it in the animation through the use of animation events.

    • @issue7278
      @issue7278 ปีที่แล้ว +1

      @@thegamedevcave But can you make a dedicated video for multi Attack pattern

  • @ksmleopard6890
    @ksmleopard6890 3 หลายเดือนก่อน +1

    For everyone asking for anti-spam and for all your animations to play out before going to the next one do this. You will need to have an attack bool in your animator and in the transition from attack to exit you will need to put the condition of "attack, false".
    Then in your "Attack" function in player combat script, the first line should be "anim.SetBool("attack", true);".
    Your "ExitAttack" method should have this line in your if statement before invoking "EndCombo", "anim.SetBool("attack", false).
    Finally, your if statement in the "Attack" method should look like this, "if(anim.GetCurrentAnimatorClipInfo(0).Length != 0 && Time.time - lastClickedTime >= anim.GetCurrentAnimatorClipInfo(0)[anim.GetCurrentAnimatorClipInfoCount(0) - 1].clip.length - 0.1)".
    This makes sure that the clicks only register after the current animation is done playing. Also, your character will stay in attack state until you're done attacking so it will be slightly smoother between attacks but not noticeably.

    • @AndreuJapan
      @AndreuJapan 3 หลายเดือนก่อน

      I tried your method but using that if condition is only playing the first animation. I think is all depending on the animations time also.
      If we use the same animations from this video will work, but using different animations with different times need to be adjust.