Search Unity

Failure to Communicate From One Script to Another (Please Check My Work)

Discussion in 'Scripting' started by Adeno, Feb 12, 2014.

  1. Adeno

    Adeno

    Joined:
    Aug 7, 2011
    Posts:
    184
    C#

    Hi there! I'm having some trouble making one script communicate with the second one. Can somebody please check my work to see where I'm wrong? Here's a short summary of what I've been trying to do so that you'll have a clearer idea of my problem.

    1. I have a character who can do a "Push" attack by pressing a key (I set it to letter "E"). This is in my PlayerControl script.

    2. I created two empty gameobjects and gave them capsule colliders and then set them as triggers. I then attached them to the palms of my character. These gameobjects serve as the collision trigger so that when my character does the push attack, it would follow the palms and hit the enemy in front. These gameobjects were given the tag of "ChubbyPush" because enemies can die if they come into contact with something with this tag.

    3. Although I already can use these two collision capsules to kill enemies, I realized one thing: Even if I wasn't doing the "Push" attack, the enemies can die by simply touching my character's palms! That's not good because I only want them to die if my character attacks them.

    4. After that, I decided to make a second script called ChubbyPushAttack, intended to change the tags of the collision capsules depending on whether I already pushed the "E" key or not. If I pushed the "E" key, then the tags on the collision capsules should change into "ChubbyPush", if not, then they should remain as "Untagged".

    5. So far I've been testing it but it doesn't seem to work. Even if I push the "E" key, the tags on the collision capsules don't change into "ChubbyPush" (yes, I was looking at the inspector to see whether it was working or not). I must be doing something wrong when it comes to making one script communicate with the other.





    Here's my PlayerControl script, I'll just include the relevant Push Attack part (I don't want to drown you with too much unrelated stuff, it's very long). I attached this to my cute character named Chubby:):

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class PlayerControl : MonoBehaviour
    6. {
    7. private bool canMove = true;
    8. public bool chubbyUsedPushAttack;
    9.  
    10. void FixedUpdate ()  
    11.     {
    12.         if (canMove) {
    13.                         CharacterIdle();
    14.                         CharacterMove ();
    15.                         CharacterJump ();
    16.                         CharacterPush ();
    17.  
    18.                
    19.                 }
    20.        
    21.         else
    22.             if (!canMove) {
    23.             animator.SetBool("CanDie", true);
    24.                         RestartCountdown ();
    25.                 }
    26.  
    27.     }
    28.  
    29. void CharacterPush()
    30.     {
    31.         if (Input.GetKey (KeyCode.E)  animator.GetCurrentAnimatorStateInfo(0).IsName ("Idle")  isGrounded == true
    32.             || Input.GetKey(KeyCode.E)  animator.GetCurrentAnimatorStateInfo(0).IsName("Walk")  isGrounded == true)
    33.         {
    34.             chubbyUsedPushAttack = true;
    35.             print ("Chubby used Push Attack! " + chubbyUsedPushAttack);
    36.             animator.SetBool("CanPush", true);
    37.             rigidbody.velocity = transform.forward * 5;
    38.         }
    39.     }
    40.  
    41. }
    42.  
    43.  
    44.  


    Here's the other script that's supposed to change the tags of the collision capsules if I press the "E" key to push. Of course they are attached to the two collision capsules:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class ChubbyPushAttack : MonoBehaviour
    6. {
    7.  
    8.     public PlayerControl playerControlReference;
    9.     public bool chubbyPushed;
    10.  
    11.  
    12.  
    13.     // Use this for initialization
    14.     void Start () {
    15.  
    16.         chubbyPushed = playerControlReference.chubbyUsedPushAttack;
    17.    
    18.     }
    19.    
    20.     // Update is called once per frame
    21.     void Update () {
    22.  
    23.     if (playerControlReference.chubbyUsedPushAttack == true) {
    24.                         print ("Chubby Push Attack: Attacked!");
    25.             this.gameObject.tag = "ChubbyPush";
    26.                 } else
    27.  
    28.             if (playerControlReference.chubbyUsedPushAttack == false)
    29.         {
    30.  
    31.             print ("Chubby Push Attack: Did Not Attack!");
    32.  
    33.             this.gameObject.tag = "Untagged";
    34.                 }
    35.  
    36.  
    37.    
    38.     }
    39. }
    40.  
    41.  

    My goal is:

    a. When I press the "E" key, the bool called chubbyUsedPushAttack should become true in my PlayerControl (This one works, I checked).

    b. The ChubbyPushAttack script should be able to change the tags of my collider capsules from "Untagged" to "ChubbyAttack" if the bool chubbyUsedPushAttack is true in the PlayerControl script so that enemies can be killed if they come into contact with these capsules.



    So there, my second script called ChubbyPushAttack doesn't seem to work at all. I'm also pretty new to the idea of using references like "public PlayerControl playerControlReference;" because it's the first time I needed to make two scripts interact with each other. I just followed some tutorial that I found regarding references, but unfortunately when I tried to apply it on my own, I seem to have failed.

    Thanks in advance to whoever can give me advice on how to make my idea work. I also welcome tips on how to make different scripts interact with one another because I think this is a big part of making things work in games. It's still something that I haven't overcome. I'm just not too experienced when it comes to this matter. I really hope to learn using references more comfortably in the future, I think it will solve a lot of potential problems later on:)
     
  2. Trankilos

    Trankilos

    Joined:
    Jan 31, 2014
    Posts:
    9
    What i do ( and i don't say it's the best solution ) is activate / desactive the collider + coroutine.

    If the collider is active, your event on collision will always be called if collision ( as you said in your point 3 ).

    So :

    Code (csharp):
    1.  
    2.  
    3.  
    4. public class PlayerControl : MonoBehaviour
    5. {
    6. private bool canMove = true;
    7. public bool chubbyUsedPushAttack;
    8.  
    9. //Add your colliders
    10.  
    11. private CapsuleCollider myCollider;
    12.  
    13. void Start()
    14. {
    15. myCollider = gameObject.GetComponent<CapsuleCollider>();
    16. myCollider.enabled = false;
    17. }
    18.  
    19. void FixedUpdate ()  
    20. {
    21. void CharacterPush()
    22.  
    23.     {
    24.  
    25.         if (Input.GetKey (KeyCode.E)  animator.GetCurrentAnimatorStateInfo(0).IsName ("Idle")  isGrounded == true
    26.  
    27.             || Input.GetKey(KeyCode.E)  animator.GetCurrentAnimatorStateInfo(0).IsName("Walk")  isGrounded == true)
    28.  
    29.         {
    30.  
    31. //LaunchCoroutine
    32. StartCoroutine(ActivateCollider());
    33.  
    34.             chubbyUsedPushAttack = true;
    35.  
    36.             print ("Chubby used Push Attack! " + chubbyUsedPushAttack);
    37.  
    38.             animator.SetBool("CanPush", true);
    39.  
    40.             rigidbody.velocity = transform.forward * 5;
    41.  
    42.         }
    43.  
    44.     }
    45.  
    46. private IEnumerator ActivateCollider()
    47. {
    48. myCollider.enabled = true;
    49. yield return new WaitForSeconds(0.5f)
    50. myCollider.enabled = false;
    51. }
    52. }
    53. }
    54.  
    55.  
    So tag your punch as "punch" ( or what you want ) and add this to ennemy :

    Code (csharp):
    1.  
    2. void OnCollisionEnter (Collision col)
    3. {
    4. if(col.gameObject.tag == "punch")
    5. //call event ( die, loose life, ... )
    6. }
    7.  
    Hope it help a bit.
     
  3. Adeno

    Adeno

    Joined:
    Aug 7, 2011
    Posts:
    184
    Thank you Trankilos for sharing your way of dealing with such a problem. There really are many ways to get things done lol :D

    Anyway as for me, I continued researching and I found out that my mistake was not using the "GameObject.Find" part in the code, and instead I used a "wrong" style of reference. I created a new project just for the purpose of hunting down the solution to my little problem, and since I've already solved it, I want to share it with anyone who might encounter the same situation as I have.

    Here's the experiment that I made and anyone interested can also try it out. It's written in C#.


    Making One Script Communicate With Another Script:


    A. Preparing the Scene

    1. Open a New Project, you don't really need to import anything.
    2. At the top of the screen, click GameObject -> Create Other and then choose to make a Cube.
    3. Repeat the above and create a Sphere.
    4. In the hierarchy panel, drag the Sphere into the Cube (or not if you don't want to, I just want the example to mimic closely what I was trying to accomplish in my original post).
    5. On the Inspector panel of the Sphere, put a check mark on "IsTrigger" (or not if you don't want to).
    6. While still on the Inspector panel of the Sphere, click Tag -> Add Tag. You'll see Tags Layers section in the Inspector panel.
    7. On Element 0, type in Sphere_NotAttacking and press Enter key.
    8. On Element 1, type in Sphere_Attacking and press Enter key.
    9. Click on your Sphere (or the name of your sphere in the hierarchy panel) to bring back the Sphere's Inspector panel.
    10. Click the Sphere's tag and you'll find the tags you added there. Choose Sphere_NotAttacking as the sphere's tag.
    11. Feel free to position the Main Camera wherever you want. Personally, I placed it just behind the cube character out of habit.

    Your scene should look something similar to mine:




    Idea:
    - The cube represents a simple character who can attack when a key is pressed. In this simple example, the Spacebar is the attack key.
    - The cube will have an integer and its value will increase by 1 every time we press the Spacebar key.
    - In the cube, there is also a boolean that tells us whether the Spacebar key is down or up.
    - The sphere represents the collision object added to the cube character.
    - The point of this experiment is to make the sphere know when the cube character hits the Spacebar key. If the Spacebar key is held down, then the sphere's tag, which is "Sphere_NotAttacking" by default, should change into "Sphere_Attacking". If the Spacebar key is let go, then the sphere's tag should go back to "Sphere_NotAttacking".



    B: Writing the Scripts

    SquareAdder - think of this script as the player's controls (but just simplified for the sake of this experiment). In this script, it will contain an integer that will count how many times we pressed the Spacebar key, and a boolean that detects whether the Spacebar key is being pressed or not.

    SphereRelay - think of this script as something that enables/disables the ability to harm enemies. If the Spacebar key is being pressed, this information from the SquareAdder script will be read by SphereRelay. If it reads that the Spacebar key is being held down, then it changes the tag of the sphere into "Sphere_Attacking". If the Spacebar key is not being held, then it changes the tag of the sphere back into "Sphere_NotAttacking".


    1. In the Project panel, right click on the Assets folder and click Create -> Folder.
    2. Name the folder Scripts.
    3. Inside the Scripts folder, right click, choose Create and then choose C# Script.
    4. Rename the script into SquareAdder.
    5. Right click inside the Scripts folder again and create another C# Script. Name it SphereRelay.


    The SquareAdder Script:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class SquareAdder : MonoBehaviour {
    6.  
    7.     public int squareAdder;
    8.     public bool squarePressedSpace;
    9.  
    10.     // Use this for initialization
    11.     void Start () {
    12.    
    13.     }
    14.    
    15.     // Update is called once per frame
    16.     void Update () {
    17.  
    18.         AddSquare ();
    19.    
    20.     }
    21.  
    22.     void AddSquare()
    23.     {
    24.         if (Input.GetKeyDown (KeyCode.Space)) {
    25.                         squarePressedSpace = true;
    26.                         squareAdder++;
    27.                         print ("Square Says: " + squareAdder);
    28.                 } else
    29.  
    30.         if (Input.GetKeyUp (KeyCode.Space)) {
    31.             print ("Square Says: Space Key is UP");
    32.             squarePressedSpace = false;
    33.         }
    34.  
    35.     }
    36. }
    37.  
    38.  
    The script is pretty simple. We have two public variables (an int and a bool) to count how many times we pressed the Spacebar key and to tell us whether the Spacebar key is held down or not. Then we have an AddSquare() method that does the actual work of checking the conditions.



    The SphereRelay Script:


    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class SphereRelay : MonoBehaviour {
    6.  
    7.     public SquareAdder squareAdderReference;
    8.  
    9.  
    10.     // Use this for initialization
    11.     void Start () {
    12.  
    13.         squareAdderReference = GameObject.Find("Cube").gameObject.GetComponent<SquareAdder> ();
    14.  
    15.     }
    16.    
    17.     // Update is called once per frame
    18.     void Update () {
    19.  
    20.         CheckSpaceBarStatus ();
    21.    
    22.     }
    23.  
    24.     void CheckSpaceBarStatus()
    25.     {
    26.         if (squareAdderReference.squarePressedSpace == true) {
    27.             print ("Sphere Relay Says: " + squareAdderReference.squareAdder);
    28.             this.gameObject.tag = "Sphere_Attacking";
    29.             print ("Sphere Tag Is: " + this.gameObject.tag);
    30.         } else
    31.            
    32.         if (squareAdderReference.squarePressedSpace == false) {
    33.             this.gameObject.tag = "Sphere_NotAttacking";
    34.             print ("Sphere Relay Says: Space Bar NOT Pressed!");
    35.             print ("Sphere Tag Is: " + this.gameObject.tag);
    36.         }
    37.     }
    38. }
    39.  
    40.  
    41.  
    In the SphereRelay script, we simply make a way for it to read the information coming from the SquareAdder script by making a variable called squareAdderReference that looks for the gameobject called "Cube" (that's our cube character's default name!) and it's component (the class or name of the script) called SquareAdder. The rest is pretty straight forward, there's just a method called CheckSpaceBarStatus() that does the work of reading the variables coming from the SquareAdder script.



    C: Starting the Experiment:

    1. Click on the Cube on the scene or in the hierarchy panel.
    2. Choose Add Component -> Scripts -> then choose Square Adder. Alternatively, you can just drag the SquareAdder script from the Scripts folder onto the actual Cube object on the scene or on its name in the hierarchy panel.
    3. Do the same for the Sphere, but of course give it the SphereRelay script.
    4. Click on the Play button.
    5. Look at the Console. It will keep saying that the sphere is not attacking and that the Spacebar is not pressed. Try clicking on the word "Collapse" in the Console's panel so you won't get flooded with text all the time. You'll also notice that numbers keep rising if "Collapse" is enabled because it keeps outputing the same thing.
    6. Next, press and hold the Spacebar. You'll notice that it will now say that the sphere is attacking.
    7. With the game still playing, click on the Sphere in the hierarchy panel and you'll see the Sphere's information in the inspector panel.
    8. Click on the game screen again. Watch the Sphere's tag. Press and hold the Spacebar key and you'll notice that the tag will become "Sphere_Attacking". If you let go of the Spacebar key, it will revert back to "Sphere_NotAttacking".





    The Result:

    After I applied my experiment to my own project, the result was fortunately a success!



    My new code isn't really that different. I just had to actually use the GameObject.Find part and point it to my main character where my controls were attached to.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class ChubbyPushAttack : MonoBehaviour
    6. {
    7.  
    8.     public PlayerControl playerControlReferencePush;
    9.  
    10.     //public bool chubbyPushed;
    11.  
    12.  
    13.  
    14.     // Use this for initialization
    15.     void Start () {
    16.  
    17.         playerControlReferencePush = GameObject.Find ("Chubby_Prefab").gameObject.GetComponent<PlayerControl> ();
    18.    
    19.    
    20.     }
    21.    
    22.     // Update is called once per frame
    23.     void Update () {
    24.  
    25.     if (playerControlReferencePush.chubbyUsedPushAttack == true) {
    26.             print ("Chubby Push Attack: Attacked!");
    27.             this.gameObject.tag = "ChubbyPush";
    28.                 } else
    29.  
    30.             if (playerControlReferencePush.chubbyUsedPushAttack == false)
    31.         {
    32.  
    33.             print ("Chubby Push Attack: Did Not Attack!");
    34.  
    35.             this.gameObject.tag = "Untagged";
    36.                 }
    37.  
    38.  
    39.    
    40.     }
    41. }
    42.  
    43.  

    And there we go, one of my problems solved lol! Feel free to correct me if I made any mistakes on how I explained my solution (I'm not yet a master) and please feel free to share techniques on the subject if you have any more. I hope my experiment will help some fellow aspiring game developer in this matter because honestly, this was something I got stuck on for a while lol! :)

    After this experiment, my appreciation for those primitive objects has risen. Instead of little props whose only purpose is to serve as debris or placeholders, now they're important experimental subjects haha:)