Search Unity

Help with identifying exact instances of an object

Discussion in 'Scripting' started by petizero, Apr 14, 2020.

  1. petizero

    petizero

    Joined:
    Jan 1, 2019
    Posts:
    47
    Hi so this might be worder really poor. Sorry about that.

    Anyways. I wrote a script that instantiates 2 copies of the same object. (It's called QB in the inspector) The problem comes from the script i wrote where i use the line: gameObject.setactive(false) Which in theory should work. But in reality it chooses the first instantiated prefab no matter what. Any help?

    Here is the code:

    Code (CSharp):
    1.     void Update()
    2.     {
    3.         if(QuestAcceptSigno.questAccepted == true)
    4.         {
    5.             questNumber += 1;
    6.  
    7.             saveQuestDetails();
    8.  
    9.             QuestAcceptSigno.questAccepted = false;
    10.         }
    11.     }
    12.  
    13.    void saveQuestDetails()
    14.     {
    15.         savedQuestTypeNumber = questDecider;
    16.         savedTypeNumber = typeNumber;
    17.         gameObject.SetActive(false);
    18.         Debug.Log(questNumber);
    19.  
    20.     }
    21.  
    22. }
    23.  
    questAccepted is just a simple onMouseDown script.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class QuestAcceptSigno : MonoBehaviour
    6. {
    7.  
    8.     public static bool questAccepted;
    9.  
    10.     private void OnMouseDown()
    11.     {
    12.         questAccepted = true;
    13.     }
    14.  
    15. }
    16.  
    On the two pictures you can see somewhat the visual things going on. Note that i click the "Accept" button on the right QB and it deltes the middle one

    First.png Second.png
     
  2. Olmi

    Olmi

    Joined:
    Nov 29, 2012
    Posts:
    1,553
    Hi,
    I don't honestly understand your logic in this one. Wouldn't it be easier to send a callback of some sort to the correct object when you click/touch an UI element that represents a quest selection? Instead of doing something every frame in Update?
     
  3. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,187
    gameObject.SetActive doesn't choose the first instantiated object. It chooses the object the script is on. gameObject is a reserved word that says, target the gameObject this script is on. Then when you call SetActive, it then turns that off. So, calling saveQuestDetails is triggering that turn off.

    But since you didn't show your instantiate code or how you're keeping track of what you instantiated, or how you set questAccepted to true (honestly, I'm not a fan of your Update usage), it's difficult to tell you exactly what might fix it with your implementation. But normally when clicking on a button, you can get the button you clicked on and trigger code based on that if you want.
     
  4. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    This is an issue of execution order and the fact that .questAccepted is a static variable. There is only one .questAccepted, so when you set it to false in line 9, it sets it to false for everywhere; then the next object's Update comes around, and sees that it's set to false, so won't disable itself.

    How I would do this would be to put both of these buttons under a common parent, and when either button is selected, deactivate the parent, not the individual buttons.

    Though, if this is a UI that will come up often with different options (I imagine that a UI to accept quests would), then you may want to be taking a different approach entirely, something more generic and reusable, probably using callbacks and maybe inheritance, which I'm guessing are concepts you will need to learn. You almost certainly will want to use the Canvas UI system rather than the OnMouseDown based thing you're using there. I can help offer guidance for that, but it will probably be a fair amount of rewriting if you're up for that.
     
  5. petizero

    petizero

    Joined:
    Jan 1, 2019
    Posts:
    47
    Sure sounds good. I've been wanting to improve upon my coding skills too
     
  6. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    Alright, sweet. Let's see if we can make you a quest system!

    First, for some foundational knowledge, look up some tutorials - I'll give you some keywords to google for these. I'll briefly describe how the concepts would be used for this system (mostly because if you're anything like me, having context makes it much easier to learn) but definitely don't skip googling for the bolded terms to learn how to actually use them. (In fact, while writing this post, I determined that a quest system is kind of gauntlet for a ton of mid-to-high level coding skills, which makes it the perfect teaching tool!)

    The goal here is, you'll want to have a base "Quest" class which will solely hold quest information - the name, the description, etc. It's possible that you might need special logic for some quests, in which case you'll want to look up and learn about object inheritance, but we won't worry about that for now (I suspect you'll probably be fine just using delegates and callbacks as described below for this use case).

    Note: if you create a non-MonoBehaviour class and want to edit its contents in the inspector, you can use System.Serializable to do this, like so:
    Code (csharp):
    1. //some other script which you attach to an object
    2. public class SomeQuestTrigger : MonoBehaviour {
    3. public Quest myQuest;
    4. }
    5.  
    6. //should be in its own file. Notice that this does NOT inherit from MonoBehaviour
    7. [System.Serializable]
    8. public class Quest {
    9. public string questName = "name of Quest";
    10. }
    This way you'll be able to edit the quest info in the inspector, and then you will be able to pass around the Quest object to other scripts (such as, eventually, your UI script).

    Next concept to google: delegates and callbacks. The idea here is that, to trigger a quest decision like this, you'll be able to pass in a reference to a function, so that the game can store that function and call it later. (Also google lambda functions while you're at it, as these are a convenient way to use callbacks.)

    Combining that concept with the class created above, Unity has a wonderful class called UnityEvent. If you put this in your Quest class:
    Code (csharp):
    1.  
    2. public class Quest {
    3. public string questName = "name of Quest";
    4. public UnityEvent onQuestBegin;
    5. }
    Then check it out in the inspector, you can then create and assign functions in the inspector for the quest to call at various points. UnityEvent was created for the canvas UI system (e.g. so you can assign a function to a button easily), but is extremely useful in a lot of situations, and this is one of them.

    Speaking of UI, you'll want to make a sort of "Quest UI manager", and for this you'll probably want to create a singleton. This way you'll be able to reference the manager easily from anywhere, so you can do something like QuestUIManager.instance.ChooseFromQuests(quest1, quest2, quest3);

    Code (csharp):
    1. public class QuestUIManager : MonoBehaviour {
    2. public static QuestUIManager instance;
    3. void Awake() {
    4. instance = this;
    5. }
    6.  
    7. public void ChooseFromQuests(params Quest[] quests) {
    8. ...
    Which reminds me, if you're unfamiliar with arrays, now is a good time to read up on those.

    Now, for the manager itself, you probably want to have a set number of the UI objects as children, and when you call ChooseFromQuests, you'll loop through these UI objects, filling their UI elements from the Quest class objects that were provided.

    I'll leave you be at this point - it's not 100% done, but if you've made it through this far you can probably feel out the next steps on your own. If not at this point you'll probably have more questions etc, come back and ask anything you can't find by googling the bold words.

    Obviously this is a lot to throw at you all at once (learning all of these concepts is probably at least a week or two worth of curriculum in a computer science class, so don't worry if you need to take a little time to digest all of it), but it should guide you towards a robust quest system and you'll learn super useful stuff along the way.