Sharing data between GameObject from the same script.

So, i want to know how i can share a value between two game objects that have the same script. The situation is this: i have two npcs that can interact with each other, in my case, its the Talk behavior. So, when they come together, it trigger a OnTriggerCollider that has some conditions to meet that the two npcs can Talk to each other. What i am trying to do, its to add some Random Value that can be shared to each other to make the Talk Behavior more dynamically. What is the best way to do that? And how i can share the same Random value between this two npc`s?

Note: when i run this code, the first npc that process the code gets 0 in probability attribute.

OnTriggerEnter code:

protected void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("NPC"))
        {
            if (isInCombatMode)
            {
                return;
            }
            else
            {
                if (CanTalkTo(other.gameObject))
                {
                    Talk(other.gameObject);
                }
            }
        }
    }

CanTalkTo code:

protected bool CanTalkTo(GameObject npcTarget)
    {
        if (!IsInState("Talk") && IsReadyToTalk() && IsTargetNpcReadyToTalk(npcTarget))
        {
            NPCStatus npcTargetStatus = npcTarget.GetComponent<NPCGeneric>().status;
            chanceToTalk = GetWeightInteractionProbability(npcTargetStatus);
            float npcTargetChanceToTalk = 0;

            npcTargetChanceToTalk = npcTarget.GetComponent<NPCGeneric>().chanceToTalk;

            float avarage = (chanceToTalk + npcTargetChanceToTalk) / 2f;
            Debug.Log(status.name + " " + avarage + " PT: " + chanceToTalk + " NPC PT: " + npcTargetChanceToTalk);

            if (avarage >= 50f)
            {
                return true;
            }
        }

        return false;
    }

GetWeightInteractionProbability code:

protected float GetWeightInteractionProbability(NPCStatus npcTargetStatus)
    {
        float npcTargetWeight = 0;
        float npcWeight = 0;

        // ...

        float randomValue = 0; ;

        if (HasSameClass(npcTargetStatus.npcClass))
        {
            randomValue = Random.Range(3f, 11f) / 10f;
        }
        else
        {
            randomValue = Random.Range(1f, 8f) / 10f;
        }

        return ((npcWeight + npcTargetWeight) / 2f * randomValue);
    }

I think the reason you’re having trouble is you’re running into a race condition. If two NPCs run into each other you have no idea which one will have their “OnTrigger” event fire first, and they don’t fire at the same time so whoever is the first to fire will read the other NPCs “chanceToTalk” as 0 or whatever it was set to last interaction, so both the NPCs will have a different chance to talk which is not what you want!

There are a few solutions I can think of for this problem. One that comes to the top of my head (may not be the best solution) is to simply have a public boolean that indicates whether an NPC is currently talking. As soon as the OnTriggerEvent fires (and you’re confident you’ve hit an NPC) set that boolean to true, then check to see if the Other NPCs boolean is true. So for example your code would look like

public bool talking = false;
protected void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("NPC"))
        {
            if (isInCombatMode)
            {
                return;
            }
            else
            {
        talking = true;
                if (CanTalkTo(other.gameObject))
                {
                    Talk(other.gameObject);
                }
            }
        }
    }

Then your “CanTalkTo” function would be something like

protected bool CanTalkTo(GameObject npcTarget)
    {
      // ... Do stuff
      if (npcTarget.GetComponent<NPCGeneric>().talking) {
        chanceToTalk = npcTarget.GetComponent<NPCGeneric>().chanceToTalk;
      } else {
        chanceToTalk = GetWeightInteractionProbability(npcTargetStatus);
      }
      // ... Do stuff
    }

Just don’t forget to set “talking” to false sometime later!

There may be better more neat ways of doing it but that’s the simpliest solution I can think of right now.

I should note that my method won’t work if Unity Trigger events occur concurrently as opposed to sequentially, but I’m 95% sure it works sequentially, try it out to see if it works for you!

1 Like

Thanks for you response, but i think it won’t work because OnTriggerEnter it’s called one time for each npc and if i execute your code, it will execute only one time and for me to catch the “npcTarget.GetComponent().chanceToTalk” it will have to run twice that code. I think that is possible to put isTalking variable in OnUpdate method and wait both npc to calculate their talkChance, since OnUpdate runs every frame.

I will try when i get home. Thanks for your ideia again.