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. Dismiss Notice

Collider.enabled doesn't work when firing Animation event or StateMachineBehaviour

Discussion in 'Animation' started by KappaTheKid, Mar 18, 2019.

  1. KappaTheKid

    KappaTheKid

    Joined:
    Sep 9, 2016
    Posts:
    6
    I'm working on a thirdperson combat system, but I have problems when I try to change the active state of the melee weapon collider (so it's only Enabled when you are attacking, and Disabled when not).

    I use the following code to receive animation events:

    Code (CSharp):
    1. using UnityEngine;
    2. using _Project.Scripts.Combat.Units;
    3.  
    4. namespace _Project.Scripts.Combat.AnimEvents
    5. {
    6.     public class HeroAnimEvents : MonoBehaviour
    7.     {
    8.         public Hero HeroInstance;
    9.  
    10.         public void HitStart()
    11.         {
    12.             HeroInstance.CurrentWeapon.GetComponent<MeleeWeapon>().EnableCollider();
    13.         }
    14.         public void HitEnd()
    15.         {
    16.             HeroInstance.CurrentWeapon.GetComponent<MeleeWeapon>().DisableCollider();
    17.         }
    18.     }
    19. }
    HeroInstance is only used to get the reference for the Player's current weapon. EnableCollider and DisableCollider work like this:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. namespace _Project.Scripts.Combat.AnimEvents
    4. {
    5.     public class MeleeWeapon : MonoBehaviour
    6.     {
    7.         public BoxCollider BxCollider;
    8.         public Vector3 ColliderSize;
    9.        
    10.         private void Start()
    11.         {
    12.             DisableCollider();
    13.         }
    14.  
    15.         private void OnTriggerEnter(Collider other)
    16.         {
    17.             if (other.CompareTag("Enemy"))
    18.             {
    19.                 Debug.Log(other.name);
    20.             }
    21.         }
    22.  
    23.         public void EnableCollider()
    24.         {
    25.             BxCollider.enabled = true;
    26.             //BxCollider.size += ColliderSize;
    27.             Debug.Log("1");
    28.         }
    29.  
    30.         public void DisableCollider()
    31.         {
    32.             BxCollider.enabled = false;
    33.             //BxCollider.size = Vector3.zero;
    34.             Debug.Log("2");
    35.         }
    36.     }
    37. }
    When the code enters EnableCollider it doesn't enable the collider but it does Debug the "1", same for DisableCollider, so OnTriggerEnter never works since the collider is never enabled.

    I also tried to change the collider size but doesn't work either.

    It doesn't give any error message and the reference for BxCollider is assigned from the Inspector.

    I also tried using StateMachineBehaviours, and it worked the same, the Debugs work but the collider.enabled won't.

    Also, I if leave the collider enabled, the OnTriggerEnter does work, and debugs correctly, so I guess my colliders are ok (the Weapon collider is marked as trigger).

    Is there any reason why it is not working like I want it to?
     
  2. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,486
    Try Debug.Log("1", BxCollider); so that when you click on the message in the console window it highlights that object in the hierarchy so you can make sure the correct reference is assigned. I can't see any other reason why it wouldn't be working without giving any errors.
     
    KappaTheKid likes this.
  3. KappaTheKid

    KappaTheKid

    Joined:
    Sep 9, 2016
    Posts:
    6
    This actually helped me a lot, when clicking the debug message it highlighted the weapon prefab in the Project window, not the one in the Hierarchy.

    Turns out I was setting the current weapon as the prefab itself, and not a new instance of it. So now it works as expected and enables/disables the collider properly after fixing that issue in the script that sets the weapon as current.

    Code (CSharp):
    1. public GameObject WeaponPrefab;
    2. private GameObject _currentWeapon;
    3.  
    4. private void Start()
    5. {
    6.     _currentWeapon = Instantiate(WeaponPrefab, LeftHandSlot);
    7. }
    8.  
    9. public GameObject GetCurrentWeapon()
    10. {
    11.     return _currentWeapon;
    12. }
    Kind of a rookie mistake I guess. Also I think I will stick to StateMachineBehaviours, since it seems more consistent.

    Thanks a lot SilentSin
     
  4. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,486
    I'm not sure if StateMachineBehaviours are a good idea for this sort of thing. They make it easy to have an event at the very start of the animation, but attacks usually don't start hitting things right at the start of the animation. And having an animation event that you can adjust while clearly previewing the pose of the animation is going to be much more effective than hard coding an arbitrary event time into a script. But then, I'm a bit biased because I hate Mecanim's whole state machine system so I don't use it at all. Maybe it is possible to use it effectively.

    I can also suggest a couple of ways to improve that code:
    • Change "GameObject WeaponPrefab" to "MeleeWeapon WeaponPrefab". That way you can only assign prefabs that actually have the correct script attached and Instantiate returns the copy of the MeleeWeapon component so you don't need to call GetComponent every time an event is triggered.
    • Replace the "_currentWeapon" field and "GetCurrentWeapon" method with an auto property: "public MeleeWeapon CurrentWeapon { get; private set; }". It will achieve the same thing, but is much quicker to write and easier to read.
     
  5. KappaTheKid

    KappaTheKid

    Joined:
    Sep 9, 2016
    Posts:
    6
    I'll definitely use your suggestions, and yeah I'll look more into how to trigger those events, thanks.