0
\$\begingroup\$

Basically I am making an inventory system where the player has a set amount of objects, and if they go to a pickup then it will give them more of that particular type of object. I have two problems currently. First the pickup script does indeed find the value, and update it properly. However when I go to update the value from the inventory script it keeps changing it back to it's last known value, and consequently keep it a static variable.

The other lesser issue is my OnTriggerEnter portion of the pickup system only adds once, and then stops despite the log telling me it is still detecting objects.

First script is the inventory system...

using UnityEngine;
using System.Collections;

public class InventoryManager : MonoBehaviour {

    public Rigidbody Shape1;
    public Rigidbody Shape2;
    public Rigidbody Shape3;
    public Rigidbody Shape4;
    public Rigidbody Shape5;

    public float Shape1Amount;
    public float Shape2Amount;
    public float Shape3Amount;
    public float Shape4Amount;
    public float Shape5Amount;

    public float Shape1AmountUpdated;

    public Transform SpawnLoc;
    public Transform SpawnLoc2; //I had to make this due tot he fact because it doesn't like to spawn centered properly :(.

    public float coolDown;
    public float coolDownTimer;

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update ()
    {
        Shape1AmountUpdated = GameObject.Find("PickUp").GetComponent<PickUpSystem>().ShapeValue1; //This was my attempt at trying to *tell* the pick up system the new amount, but it didn't quite work.
        Shape1Amount = Shape1AmountUpdated;

        if (coolDownTimer > 0) // If it's above it will subtract from timer.
        {
            coolDownTimer -= Time.deltaTime;
        }

        if (coolDownTimer < 0) // Checks that cd timer isn't below zero.
        {
            coolDownTimer = 0;
        }

        if (Input.GetKeyDown("1") && coolDownTimer == 0 && Shape1Amount > 0)
        {
            Rigidbody ShapeToSpawn1;
            ShapeToSpawn1 = Instantiate(Shape1, SpawnLoc.position, SpawnLoc.rotation) as Rigidbody;
            coolDownTimer = coolDown;
            Shape1Amount = Shape1Amount - 1;
        }
        if (Input.GetKeyDown("2") && coolDownTimer == 0 && Shape2Amount > 0)
        {
            Rigidbody ShapeToSpawn2;
            ShapeToSpawn2 = Instantiate(Shape2, SpawnLoc2.position, SpawnLoc.rotation) as Rigidbody;
            coolDownTimer = coolDown;
            Shape2Amount = Shape2Amount - 1;
        }
        if (Input.GetKeyDown("3") && coolDownTimer == 0 && Shape3Amount > 0)
        {
            Rigidbody ShapeToSpawn3;
            ShapeToSpawn3 = Instantiate(Shape3, SpawnLoc2.position, SpawnLoc.rotation) as Rigidbody;
            coolDownTimer = coolDown;
            Shape3Amount = Shape3Amount - 1;
        }
        if (Input.GetKeyDown("4") && coolDownTimer == 0 && Shape4Amount > 0)
        {
            Rigidbody ShapeToSpawn4;
            ShapeToSpawn4 = Instantiate(Shape4, SpawnLoc2.position, SpawnLoc.rotation) as Rigidbody;
            coolDownTimer = coolDown;
            Shape4Amount = Shape4Amount - 1;
        }
        if (Input.GetKeyDown("5") && coolDownTimer == 0 && Shape5Amount > 0)
        {
            Rigidbody ShapeToSpawn5;
            ShapeToSpawn5 = Instantiate(Shape5, SpawnLoc.position, SpawnLoc.rotation) as Rigidbody;
            coolDownTimer = coolDown;
            Shape5Amount = Shape5Amount - 1;
        }
    }
}

And here is the pickup system itself...

using UnityEngine;
using System.Collections;

public class PickUpSystem : MonoBehaviour {

    public float ShapeValue1;
    public float ShapeValue2;
    public float ShapeValue3;
    public float ShapeValue4;
    public float ShapeValue5;

    private float oldShapeValue1;
    private float oldShapeValue2;
    private float oldShapeValue3;
    private float oldShapeValue4;
    private float oldShapeValue5;

    private float ShapeValue1Updated;

    // Use this for initialization
    void Update ()
    {
        oldShapeValue1 = GameObject.Find("Main Camera").GetComponent<InventoryManager>().Shape1Amount;
        oldShapeValue2 = GameObject.Find("Main Camera").GetComponent<InventoryManager>().Shape2Amount;
        oldShapeValue3 = GameObject.Find("Main Camera").GetComponent<InventoryManager>().Shape3Amount;
        oldShapeValue4 = GameObject.Find("Main Camera").GetComponent<InventoryManager>().Shape4Amount;
        oldShapeValue5 = GameObject.Find("Main Camera").GetComponent<InventoryManager>().Shape5Amount;
    }

    // Update is called once per frame
    //void Update ()
    //{

    //}

    void OnTriggerEnter (Collider other)
    {
        if (ShapeValue1 > 0)
        {
            Debug.Log("Object detected!");
            ShapeValue1 = oldShapeValue1 + 1; //Fix me. I only add 1 on the first collision afterwards I won't add anymore.
        }
    }
}

Anyone know how I should be "syncing" the two variables? Basically the ShapeAmount1 value should always be equal to the ShapeValue1 in the other script.

\$\endgroup\$
1
  • \$\begingroup\$ Ummm, have you considered List<float>? And loops? \$\endgroup\$
    – 3Dave
    Commented Dec 21, 2016 at 21:46

3 Answers 3

4
\$\begingroup\$

When trying to keep 2 variables in 2 different scripts synced you should update them both from only one script. Scripts don't run at the same time, and it is hard, if not impossible, to keep track of what order the scripts run in. Also to keep in mind is that Update functions will not run simultaneously with trigger / collider functions. The physics engine has it's own Update function called FixedUpdate.

Please have a look at this page (http://docs.unity3d.com/Manual/ExecutionOrder.html) for some more information on this.

For a solution to your problem, you should get rid of the variable updating code in your InventoryManager's Update, and update the variable there from the Trigger function in your pick-up system where the variable actually gets updated (See code below). Or use volvis' answer.

A little side note: The "find" function is very heavy and is never a good idea to use in an Update function.

As for the problem of your trigger only updating once, this is because the OnTriggerEnter only fires once when the trigger is entered. To keep updating while in the trigger, you need to use OnTriggerStay.

    // Use OnTriggerStay instead of OnTriggerEnter
    void OnTriggerStay (Collider other)
    {
        if (ShapeValue1 > 0)
        {
            Debug.Log("Object detected!");
            ShapeValue1 = oldShapeValue1 + 1;
            // After Updating send the updated variable back to the InventoryManager
            // Or just update the variable in the InventoryManger directly
            GameObject.Find("Main Camera").GetComponent<InventoryManager>().Shape1Amount = ShapeValue1;
        }
    }

Using this in your pickup system script and removing the variable update in the inventory manager should fix your problems.

\$\endgroup\$
2
  • \$\begingroup\$ Alright I figured it out, and it works well :). Only is that since it's a pickup I'd like to be limited. So I need a way to end it. Like as it just adds to the inventory. Would I want to create a new variable that subtracts on each use, and then if it goes to zero, or below stop it? \$\endgroup\$
    – Sie
    Commented Mar 2, 2016 at 8:13
  • \$\begingroup\$ I'm not completely understanding your question. I think it is best to create a new question, since your original question got answered, and explain your question a bit more. \$\endgroup\$
    – Tithian
    Commented Mar 2, 2016 at 12:27
0
\$\begingroup\$

One way about it is moving your shared variables into a ScriptableObject instance and passing that to components that require access to them. Something like--

using UnityEngine;

[CreateAssetMenu()]
public class MySharedStuff : ScriptableObject {
    public float SharedFloat {get; set;}
}

public class ObjectUsingSharedStuff : MonoBehaviour {
    [SerializeField]
    MySharedStuff mySharedStuff;
}

The ScriptableObject is passed as a reference so they're always 'in sync'.

\$\endgroup\$
0
\$\begingroup\$

Generally, you can sync variables between two scripts by making instance of script. Make instance of InventoryManager like below:

public static InventoryManager instance
//public variables

void Awake()
{
    MakeInstance ();
}

void MakeInstance()
{
    if (instance == null) {
        instance = this;
    }
}

And use public variables in another script like below,

ScriptName.instance.variableName
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .