Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Resolved Help with simple collision based combat script.

Discussion in 'Scripting' started by Latheeb, Jul 6, 2021.

  1. Latheeb

    Latheeb

    Joined:
    Jun 27, 2016
    Posts:
    21
    I'm trying to play around with a little bit of collision based combat (where a hit is registered if a weapon hits the opponent during an attack). I've written a simple script to test this out, but it isn't working quite the way I expect it to.

    Currently I'm just trying to use Animation Events on my attack animation to try to enable and disable a collider, but it isn't enabling/disabling the box collider on the weapon most of the time (it seems to work once in a while, but most attacks don't end up changing the status of the box collider).

    Here is my script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Pathfinding;
    5. using MEC;
    6. public class AttackScript : MonoBehaviour
    7. {
    8.     [SerializeField] float attackDamage = 10f;
    9.     [SerializeField] float attackRange;
    10.     [SerializeField] GameObject weapon;
    11.     Animator animator;
    12.     AIDestinationSetter setter;
    13.     BoxCollider weaponCollider;
    14.     float attackDelay;
    15.     float attackRangeSquared;
    16.     float timer;
    17.     bool colliderBool;
    18.     bool canAttack;
    19.     void Awake()
    20.     {
    21.         if(TryGetComponent(out Animator temp1))
    22.         {
    23.             animator = temp1;
    24.         }
    25.         if(TryGetComponent(out AIDestinationSetter temp))
    26.         {
    27.             setter = temp;
    28.         }
    29.         if(weapon.TryGetComponent(out BoxCollider coll))
    30.         {
    31.             weaponCollider = coll;
    32.         }
    33.     }
    34.     void Start()
    35.     {
    36.         colliderBool = false;
    37.         canAttack = true;
    38.         DisableWeaponCollider();
    39.         attackRangeSquared = attackRange * attackRange;
    40.         if(animator != null)
    41.         {
    42.             var animClips = animator.runtimeAnimatorController.animationClips;
    43.             foreach (AnimationClip clip in animClips)
    44.             {
    45.                 if (clip.name == "Attack")
    46.                 {
    47.                     attackDelay = clip.length;
    48.                 }
    49.             }
    50.         }
    51.     }
    52.     void Update()
    53.     {
    54.         timer -= Time.deltaTime;
    55.         if (timer > 0f && canAttack)
    56.         {
    57.             animator.SetBool("attack", false);
    58.             canAttack = false;
    59.         }
    60.         else if (timer <= 0f && setter.target != null)
    61.         {
    62.             canAttack = true;
    63.             var target = setter.target;
    64.             if((transform.position - target.position).sqrMagnitude <= attackRangeSquared && target != transform)
    65.             {
    66.                 Timing.RunCoroutine(Attack());
    67.                 timer = attackDelay;
    68.             }
    69.         }
    70.     }
    71.     IEnumerator<float> Attack()
    72.     {
    73.         animator.SetBool("attack", true);
    74.         if (setter.target.TryGetComponent(out HealthScript healthScript))
    75.         {
    76.             yield return Timing.WaitForSeconds(attackDelay * 0.5f);
    77.             healthScript.TakeDamage(attackDamage);
    78.         }
    79.     }
    80.     void EnableWeaponCollider()
    81.     {
    82.         colliderBool = weaponCollider.enabled;
    83.         if(!colliderBool)
    84.         {
    85.             colliderBool = true;
    86.             weaponCollider.enabled = true;
    87.             Debug.Log("Weapon Collider Enabled");
    88.         }
    89.     }
    90.     void DisableWeaponCollider()
    91.     {
    92.         if(colliderBool)
    93.         {
    94.             colliderBool = false;
    95.             weaponCollider.enabled = false;
    96.             Debug.Log("Weapon Collider Disabled");
    97.         }
    98.     }
    99. }
    Every attack cycle I get both Debug.Log messages logged to the consol saying that the collider has been enabled/disabled. It also always turns off in the beginning due to the DisableWeaponCollider() in Start. I'm just not sure why it's logging the messages but not actually running the line of code immediately above each of them, apparently?

    What am I doing wrong?
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,724
    This isn't possible.

    What makes you think the code above is not running?
     
    GroZZleR likes this.
  3. FIshy101

    FIshy101

    Joined:
    Jan 19, 2021
    Posts:
    10
    hello i know 1 fix you should add an attack point
     
  4. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    If the debug log is firing appropriately, what makes you think the other code isn't running?
     
  5. Latheeb

    Latheeb

    Joined:
    Jun 27, 2016
    Posts:
    21
    Well, I assume it's not running because the collider is not being enabled or disabled most of the time. I didn't believe that to be possible, either. Something else must be happening, I just can't figure out what.
     
  6. FIshy101

    FIshy101

    Joined:
    Jan 19, 2021
    Posts:
    10
    well make the collider a variable then just put it where its gonna be disabled and where its gonna be enabled
     
  7. FIshy101

    FIshy101

    Joined:
    Jan 19, 2021
    Posts:
    10
    and if that dose not work then il try to post my script
     
  8. Latheeb

    Latheeb

    Joined:
    Jun 27, 2016
    Posts:
    21
    Well, it's definitely a product my my inexperience in this area. I did not have a Rigidbody on the weapon. Adding one causes the box collider to enable and disable as I intent it to, but it also causes the weapon to progressively move further out of the character's hand with each swing. I'm really not having much luck with getting this going. I'm just going to keep at it, though.

    If anyone has any insight or any videos or resources that come to mind I would love any help in this area.
     
  9. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,724
    Set the Rigidbody to Kinematic.
     
  10. Latheeb

    Latheeb

    Joined:
    Jun 27, 2016
    Posts:
    21
    I have the Rigidbody set to kinematic. Also tried Freeze Position and Freeze Rotation all checked. Tried setting Box Collider to Is Trigger thinking maybe colliding with the target was the problem. Still slowly moving out of my hand with each swing, sadly.

    I appreciate the help tremendously, though!
     
  11. FIshy101

    FIshy101

    Joined:
    Jan 19, 2021
    Posts:
    10
    i have a brakeys video
     
  12. FIshy101

    FIshy101

    Joined:
    Jan 19, 2021
    Posts:
    10
  13. Latheeb

    Latheeb

    Joined:
    Jun 27, 2016
    Posts:
    21
    I was roughly trying to follow along with this guide, from around the 3:00 mark:



    I've rewatched it and toyed with my scripts a little bit, but I still haven't gotten anything acceptable. He didn't seem to have any of the problems I've run into. I had also seen the Brackeys video before, but thank you for reminding me of that one as well.

    I'm really not sure which direction to go in at this point.
     
  14. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    You probably want trigger based colliders, not a physically accurate simulated system with rigidbodies and physical colliders.
     
  15. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,724
    Even with triggers - you still probably want a kinematic RB on the trigger to ensure that you always get collision callbacks.
     
    GroZZleR likes this.
  16. Latheeb

    Latheeb

    Joined:
    Jun 27, 2016
    Posts:
    21
    Thank you very much for the help @PraetorBlue , @GroZZleR and @showthebelt. I finally got it all sorted out in a way that I'm happy with for the time being. It's been a long day so I'm probably not at my best and I'm sure I was just messing something up along the way. I'm using a kinematic Rigidbody on the weapon (without it sliding out my hand) just in case I need to collide with something that doesn't have one (that's how it works, right? As long as something in the collision has a rigidbody it will register?).

    I'm using the following scripts:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Pathfinding;
    5. public class AttackScript : MonoBehaviour
    6. {
    7.     [SerializeField] float attackDamage = 10f;
    8.     [SerializeField] float attackRange;
    9.     [SerializeField] GameObject weapon;
    10.     Animator animator;
    11.     AIDestinationSetter setter;
    12.     DamageCollider damageCollider;
    13.     float attackDelay;
    14.     float attackRangeSquared;
    15.     float timer;
    16.     bool canAttack;
    17.     void Awake()
    18.     {
    19.         if(TryGetComponent(out Animator temp1))
    20.         {
    21.             animator = temp1;
    22.         }
    23.         if(TryGetComponent(out AIDestinationSetter temp))
    24.         {
    25.             setter = temp;
    26.         }
    27.         damageCollider = GetComponentInChildren<DamageCollider>();
    28.     }
    29.     void Start()
    30.     {
    31.         canAttack = true;
    32.         DisableWeaponCollider();
    33.         attackRangeSquared = attackRange * attackRange;
    34.         if(animator != null)
    35.         {
    36.             var animClips = animator.runtimeAnimatorController.animationClips;
    37.             foreach (AnimationClip clip in animClips)
    38.             {
    39.                 if (clip.name == "Attack")
    40.                 {
    41.                     attackDelay = clip.length;
    42.                 }
    43.             }
    44.         }
    45.     }
    46.     void Update()
    47.     {
    48.         timer -= Time.deltaTime;
    49.         if (timer > 0f && canAttack)
    50.         {
    51.             animator.SetBool("attack", false);
    52.             canAttack = false;
    53.         }
    54.         else if (timer <= 0f && setter.target != null)
    55.         {
    56.             canAttack = true;
    57.             var target = setter.target;
    58.             if((transform.position - target.position).sqrMagnitude <= attackRangeSquared && target != transform)
    59.             {
    60.                 timer = attackDelay;
    61.                 animator.SetBool("attack", true);
    62.             }
    63.         }
    64.     }
    65.     void EnableWeaponCollider()
    66.     {
    67.         damageCollider.EnableDamageCollider();
    68.     }
    69.     void DisableWeaponCollider()
    70.     {
    71.         damageCollider.DisableDamageCollider();
    72.     }
    73. }
    and

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class DamageCollider : MonoBehaviour
    6. {
    7.     [SerializeField] float damage = 10f;
    8.     [SerializeField] BoxCollider damageCollider;
    9.  
    10.     private void Awake()
    11.     {
    12.         damageCollider = GetComponent<BoxCollider>();
    13.         damageCollider.gameObject.SetActive(true);
    14.         damageCollider.isTrigger = true;
    15.         damageCollider.enabled = false;
    16.     }
    17.     public void EnableDamageCollider()
    18.     {
    19.         damageCollider.enabled = true;
    20.         Debug.Log(damageCollider.enabled);
    21.     }
    22.     public void DisableDamageCollider()
    23.     {
    24.         damageCollider.enabled = false;
    25.         Debug.Log(damageCollider.enabled);
    26.     }
    27.  
    28.     private void OnTriggerEnter(Collider coll)
    29.     {
    30.         if(coll.tag == "Target")
    31.         {
    32.             HealthScript healthScript = coll.GetComponent<HealthScript>();
    33.             if(healthScript != null)
    34.             {
    35.                 healthScript.TakeDamage(damage);
    36.                 Debug.Log(damage);
    37.             }
    38.         }
    39.     }
    40. }

    With those changes everything works as I expect it would. Maybe my struggles here will help someone else in the future with a similar problem.
     
    GroZZleR and PraetorBlue like this.
  17. FIshy101

    FIshy101

    Joined:
    Jan 19, 2021
    Posts:
    10
    no problem im as bad at coding to like one time i had a error every time zoom in the editor the log would spam how big or small the editor was