Search Unity

[SOLVED] List.Contains() not working

Discussion in 'Scripting' started by aranthel09, Dec 11, 2016.

  1. aranthel09

    aranthel09

    Joined:
    Jul 17, 2015
    Posts:
    66
    if (List.Contains(gameObject.GetComponent<Stun>)) simply doesn't work. I've debugged and found that Stun() > 0 works perfecly. The problem lies within this conditional. For some reason, this is always false. Through Inspector I can see that Entity receives and Add Stun to the List. Game runs without any problem, but this is simply always false.

    Code (CSharp):
    1. //Stun script
    2.  
    3. using UnityEngine;
    4. using System.Collections;
    5. using UnityEngine.Networking;
    6.  
    7. public class Stun : CCTemplate {
    8.  
    9.     [Server]
    10.     public override void ApplyCC(Entity entity, Skill skill){
    11.  
    12.         if (entity.cc3.Contains (gameObject.GetComponent<Stun>())) {
    13.  
    14.  
    15.         } else {
    16.             entity.cc3.Add (this);
    17.             skill.stunTimeEnd = NetworkTime.UnifiedServerTime() + skill.stunDuration;
    18.             entity.stunDuration = skill.stunDuration;
    19.             entity.stunTimeEnd = skill.stunTimeEnd;
    20.         }
    21. }

    Code (CSharp):
    1. //Entity script
    2.  
    3. public List<CCTemplate> cc3 = new List<CCTemplate>();
    4.  
    5. void Update() {
    6.  
    7.         serverTime = NetworkTime.UnifiedServerTime ();
    8.  
    9.         CCControl ();
    10.         calcStun ();
    11.  
    12. }
    13.  
    14. [Server]
    15.     public float calcStun(){
    16.         return serverTime >= stunTimeEnd ? 0f : stunTimeEnd - serverTime;
    17.     }
    18.  
    19. [Server]
    20.     public void CCControl (){
    21.  
    22.         if (calcStun () > 0) {
    23.             isStunned = true;
    24.         } else if (cc3.Contains(gameObject.GetComponent<Stun>())){
    25.             stunTimeEnd = 0f;
    26.             isStunned = false;
    27.         }
    28. }

    A print screen of Stun prefab.
     
    Last edited: Dec 11, 2016
  2. Zaflis

    Zaflis

    Joined:
    May 26, 2014
    Posts:
    438
    You didn't show how you're passing entity to ApplyCC(). Is it the right object?

    But hard to say anything, only you can see the debugs.
     
    zhishang0001 likes this.
  3. aranthel09

    aranthel09

    Joined:
    Jul 17, 2015
    Posts:
    66
    Both Player and Monster are derived from Entity. Players casts a skill which calls ApplyCC(target, skill). It works when I use an array of Strings, something like entity.cc = "Stun". I switched to Lists since I'll need info from Stun, like Toolstips, etc. Now this doesn't work anymore. I have a guess that in entity.cc3.Add(this); the result is not object that contains Stun script, but I don't have sure. I'm not sure what data type goes to Monster when I do this. Anyway, this is what shows on my Monster Inspector.

     
  4. Zaflis

    Zaflis

    Joined:
    May 26, 2014
    Posts:
    438
    CCTemplate is a MonoBehavior, correct? Assuming you created it with null parent, and now trying to assign it to the gameobject?

    This would seem to be the right way:
    https://docs.unity3d.com/ScriptReference/GameObject.AddComponent.html
    (edit: It's still correct it seems, just the one with string parameter is no longer supported.)

    But Unity has powerful debugging tools, you can do:
    Code (CSharp):
    1. Debug.Log(entity);
    2. Debug.Log(gameObject.GetComponent<Stun>());
    3. Debug.Log(entity.cc3.Contains (gameObject.GetComponent<Stun>()));
    4. if (entity.cc3.Contains (gameObject.GetComponent<Stun>())) {
     
    Last edited: Dec 13, 2016
    TSteff63 and aranthel09 like this.
  5. aranthel09

    aranthel09

    Joined:
    Jul 17, 2015
    Posts:
    66
    Well, I changed the approach... Went back to using Array (Lists are not much my type anyway).
    Code (CSharp):
    1. [Server]
    2.     public override void ApplyCC(Entity entity, Skill skill){
    3.  
    4.         for (int i = 0; i < entity.cc.Length; i++) {
    5.             if (entity.isStunned == true) {
    6.                 break;
    7.             }
    8.  
    9.             if (entity.cc [i] == null) {
    10.  
    11.                 entity.cc [i] = gameObject.GetComponent<Stun>();
    12.                 skill.stunTimeEnd = NetworkTime.UnifiedServerTime () + skill.stunDuration;
    13.                 entity.stunDuration = skill.stunDuration;
    14.                 entity.stunTimeEnd = skill.stunTimeEnd;
    15.                 break;
    16.             }
    17.         }
    18.     }
    19. }
    Here is how Entity receives the CCTemplate:


    Code (CSharp):
    1. [Server]
    2.     public void CCControl (){
    3.  
    4.         if (calcStun () > 0) {
    5.             isStunned = true;
    6.         } else {
    7.             for (int i = 0; i < cc.Length; i++) {
    8.                 if (cc [i] == gameObject.GetComponent<Stun>()) {
    9.                     stunTimeEnd = 0f;
    10.                     isStunned = false;
    11.                     break;
    12.                 }
    13.             }
    14.         }
    Now, the weird thing is: cc = null right after isStunned doesn't work. I've tried several methods, only one that seemed to work was Array.Clear (cc, i, i). But problem is I don't have only "Stun" on my array, I have several other CCTemplates. Array.Clear(cc, i, i) erases ALL indexes of the array.... So, I kinda made it work ,but stepped into this other problem :(
     
  6. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    This call adds a Stun that is local to one gameObject:
    Code (csharp):
    1.  
    2.             entity.cc3.Add (this);
    3.  
    And this call looks for a Stun that is local to itself:
    Code (csharp):
    1.  
    2.   public void CCControl (){
    3.   if (calcStun () > 0) {
    4.   isStunned = true;
    5.   } else if (cc3.Contains(gameObject.GetComponent<Stun>())){ // gameObject is THIS entity, not the entity that stunned me
    6.  
    I doubt the entity is stunning itself in the first call, so you need to sort out a different way to search your List since you probably don't have a reference to the entity that stunned you from outside of the Stun component itself.

    Try something like:
    Code (csharp):
    1.  
    2. public T GetCC<T>() where T : CCTemplate
    3. {
    4.    foreach(CCTemplate cc in cc3)
    5.    {
    6.        if(cc is T)
    7.          return cc;
    8.    }
    9.  
    10.    return null;
    11. }
    12.  
    Then to find out if you're stunned (or some other type of CC):
    Code (csharp):
    1.  
    2. Stun stunned = GetCC<Stun>();
    3.  
    4. if(stunned != null)
    5. {
    6.    // stunned
    7. }
    8.  
    A handy tool in the Inspector is that if you double click that Stun reference in your CC3 list, it will show you what GameObject it belongs to.
     
    aranthel09 likes this.
  7. aranthel09

    aranthel09

    Joined:
    Jul 17, 2015
    Posts:
    66
    Thank you very much for your efforts in trying to help me!

    Those answers gave me an ideia. Instead of declaring an array / a list of CCTemplate, I created a GameObject list. On Stun.cs I did: List.Add(this.gameObject as GameObject) ( I doubt this redundance was needed, but, just in case..)

    Then on enttity I made a loop to check if there was a gameobject with a name "Stun". Worked like a charm!

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.Networking;
    4. using System.Linq;
    5.  
    6. public class Stun : CCTemplate {
    7.  
    8.  
    9.     [Server]
    10.     public override void ApplyCC (Entity entity, Skill skill)
    11.     {
    12.  
    13.         if (entity.isStunned == true) {
    14.  
    15.         } else {
    16.             entity.cc2.Add (this.gameObject as GameObject);
    17.             skill.stunTimeEnd = NetworkTime.UnifiedServerTime () + skill.stunDuration;
    18.             entity.stunDuration = skill.stunDuration;
    19.             entity.stunTimeEnd = skill.stunTimeEnd;
    20.         }
    21.  
    22.     }
    23.  
    24. }

    Code (CSharp):
    1. #region CC Handle
    2.         if (calcStun () > 0) {
    3.             isStunned = true;
    4.         } else if (cc2.Count > 0) {
    5.             for (int i = 0; i < cc2.Count; i++) {
    6.                 if (cc2 [i].name == "Stun") {
    7.                     stunTimeEnd = 0f;
    8.                     isStunned = false;
    9.                     var temp = cc2 [i];
    10.                     skillCur = skillCurTemp;
    11.                     cc2.Remove (temp);
    12.                     break;
    13.                 }
    14.             }
    15.         }
    Everything works now! Tyvm to both of you :)

    EDIT: Passing as GameObject allows me even to get a reference to the Icon of ccs, tooltip describing it and even the sender of the attack! Ty SO MUCH!