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. Join us on Thursday, June 8, for a Q&A with Unity's Content Pipeline group here on the forum, and on the Unity Discord, and discuss topics around Content Build, Import Workflows, Asset Database, and Addressables!
    Dismiss Notice

Bug Need help with score points at OnTriggerEnter

Discussion in 'Scripting' started by Lesk0v, Mar 30, 2023.

  1. Lesk0v

    Lesk0v

    Joined:
    Aug 1, 2019
    Posts:
    5
    Hello!

    I'm working on a project that the player have to kill zombies and he gains some points in a score.

    The logic is very simple:

    - When my projectile collide with other GameObject with tag "Zombie", both (projectile and zombie) should be destroy and the score increases in 1 point.

    What is happening:

    - OnTriggerEnter is called, both GameObjects are destroyed, my score increases in 1 point, OnTriggerEnter is called again and restart my score to 0

    I've tried create some auxiliary variables to storage the values but I have no success.

    bellow is my code:

    Code (CSharp):
    1. public class DetectCollisions : MonoBehaviour
    2. {
    3.     public int score;
    4.  
    5.     void OnTriggerEnter(Collider other)
    6.     {
    7.         Destroy(gameObject);
    8.         Destroy(other.gameObject);
    9.         if (other.gameObject.CompareTag("Zombie"))
    10.         {
    11.             Debug.Log("Score " + score);
    12.             score++;
    13.         }
    14.         Debug.Log("Score: " + score);
    15.     }
    16. }
    The Debug.Log when the OnTriggerEnter is called is:
    Score: 0
    Score: 1 -> (OnTriggerEnter called again)
    Score: 0

    The components of zombie and my projectile:
    Zombie - Rigdbody and box collider (Isn't Trigger)
    Projectile - Rigidbody and sphere collider (Is Trigger)

    Can someone help me?
     
    Last edited: Mar 30, 2023
  2. ZingZangGames

    ZingZangGames

    Joined:
    Dec 11, 2020
    Posts:
    69
    Hey,

    on which object is the script attached to? If you attached the script to a zombie/projectile, it might get resettet every time that zombie/projectile is destroyed. If possible, please attach the script to a static gameobject that you won't destroy.

    If that wasn't the solution, set the score attribute to 'private' to test whether the error is caused by another script or not.

    Hope it helps :)
     
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    33,682
    Whatever this is on is also destroyed. That seems wrong.

    What you probably want is a GameManager type construct where the points are stored / tracked.

    Here's some ways to do that in Unity, in roughly ascending order of complexity / features:

    ULTRA-simple static solution to a GameManager:

    https://forum.unity.com/threads/i-need-to-save-the-score-when-the-scene-resets.1168766/#post-7488068

    https://gist.github.com/kurtdekker/50faa0d78cd978375b2fe465d55b282b

    OR for a more-complex "lives as a MonoBehaviour or ScriptableObject" solution...

    Simple Singleton (UnitySingleton):

    Some super-simple Singleton examples to take and modify:

    Simple Unity3D Singleton (no predefined data):

    https://gist.github.com/kurtdekker/775bb97614047072f7004d6fb9ccce30

    Unity3D Singleton with a Prefab (or a ScriptableObject) used for predefined data:

    https://gist.github.com/kurtdekker/2f07be6f6a844cf82110fc42a774a625

    These are pure-code solutions, DO NOT put anything into any scene, just access it via .Instance!

    The above solutions can be modified to additively load a scene instead, BUT scenes do not load until end of frame, which means your static factory cannot return the instance that will be in the to-be-loaded scene. This is a minor limitation that is simple to work around.

    If it is a GameManager, when the game is over, make a function in that singleton that Destroys itself so the next time you access it you get a fresh one, something like:

    Code (csharp):
    1. public void DestroyThyself()
    2. {
    3.    Destroy(gameObject);
    4.    Instance = null;    // because destroy doesn't happen until end of frame
    5. }
    There are also lots of Youtube tutorials on the concepts involved in making a suitable GameManager, which obviously depends a lot on what your game might need.

    OR just make a custom ScriptableObject that has the shared fields you want for the duration of many scenes, and drag references to that one ScriptableObject instance into everything that needs it. It scales up to a certain point.

    And finally there's always just a simple "static locator" pattern you can use on MonoBehaviour-derived classes, just to give global access to them during their lifecycle.

    WARNING: this does NOT control their uniqueness.

    WARNING: this does NOT control their lifecycle.

    Code (csharp):
    1. public static MyClass Instance { get; private set; }
    2.  
    3. void OnEnable()
    4. {
    5.   Instance = this;
    6. }
    7. void OnDisable()
    8. {
    9.   Instance = null;     // keep everybody honest when we're not around
    10. }
    Anyone can get at it via
    MyClass.Instance.
    , but only while it exists.
     
  4. Lesk0v

    Lesk0v

    Joined:
    Aug 1, 2019
    Posts:
    5
    It was that!

    Now its working.

    Thank you!!
     
    ZingZangGames likes this.
  5. Lesk0v

    Lesk0v

    Joined:
    Aug 1, 2019
    Posts:
    5

    Hey, thanks for the help.

    I will look at the link you send. It became clear with your explanation.

    thanks again