private Array gets changed

Hi,
I’m currently making a 2D game, where the player can choose from various weapons.
But for some reason, if i change the weaponAmmo value in the shoot class (line 132 in the class), the private selectedWeaponsAmmo value (line12 in the class) in the factoryController class and the public static selectedWeaponsAmmo value (line22 in the class) int the SessionData class also change their values.
Does anyone know why this happens?

FACTORY CONTROLLER CLASS

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class FactoryManager : MonoBehaviour
{
    public Button nextSlot, previousSlot;
    public Button useNothing, usePistol, useMachineGun, useSonicBlaster, useLaserBlaster, useElectricBlaster, useGrenadelauncher;
    public Text selectedWeaponsText, selectedSlotText;
    private string[] selectedWeapons = new string[3];
    private int[] selectedWeaponsAmmo = new int[3] {
        2,
        3,
        4
    };
    private int selectedSlot, selectedSlotUIText;

    private void Start() {
        Shoot.test += test;
        selectedWeapons = SessionData.selectedWeapons;
        selectedSlot = 0;
        selectedSlotUIText = 1;
        selectedSlotText.text = selectedSlotUIText.ToString();
        selectedWeaponsText.text =
            "1:" + selectedWeapons[0] + "

" +
“2:” + selectedWeapons[1] + "
" +
“3:” + selectedWeapons[2] + "
";
}

    private void test() {
        Debug.Log(selectedWeaponsAmmo[0]);
    }

    public void ChangeSlot() {
        string button = UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject.name;

        if (button == "NextSlot") {
            if (selectedSlot < 2) {
                selectedSlot++;
                selectedSlotUIText++;
                selectedSlotText.text = selectedSlotUIText.ToString();
            } 
        }
        else if (button == "PreviousSlot") {
            if (selectedSlot > 0) {
                selectedSlot--;
                selectedSlotUIText--;
                selectedSlotText.text = selectedSlotUIText.ToString();
            }
        }
    }

    public void AddWeaponToSlot() {
        string button = UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject.name;

        if (button == "UseNothing") {
            selectedWeapons[selectedSlot] = null;
            selectedWeaponsAmmo[selectedSlot] = 0;
            SessionData.selectedWeapons = selectedWeapons;
            SessionData.selectedWeaponsAmmo = selectedWeaponsAmmo;
            selectedWeaponsText.text =
                "1:" + selectedWeapons[0] + "

" +
“2:” + selectedWeapons[1] + "
" +
“3:” + selectedWeapons[2] + "
";
}
else if (button == “UsePistol”) {
selectedWeapons[selectedSlot] = “Pistol”;
selectedWeaponsAmmo[selectedSlot] = 10;
Debug.Log(selectedWeaponsAmmo[selectedSlot]);
SessionData.selectedWeapons = selectedWeapons;
SessionData.selectedWeaponsAmmo = selectedWeaponsAmmo;
selectedWeaponsText.text =
“1:” + selectedWeapons[0] + "
" +
“2:” + selectedWeapons[1] + "
" +
“3:” + selectedWeapons[2] + "
";
}
else if (button == “UseMachineGun”) {
selectedWeapons[selectedSlot] = “MachineGun”;
selectedWeaponsAmmo[selectedSlot] = 35;
SessionData.selectedWeapons = selectedWeapons;
SessionData.selectedWeaponsAmmo = selectedWeaponsAmmo;
selectedWeaponsText.text =
“1:” + selectedWeapons[0] + "
" +
“2:” + selectedWeapons[1] + "
" +
“3:” + selectedWeapons[2] + "
";
}
else if (button == “UseSonicBlaster”) {
selectedWeapons[selectedSlot] = “SonicBlaster”;
selectedWeaponsAmmo[selectedSlot] = 5;
SessionData.selectedWeapons = selectedWeapons;
SessionData.selectedWeaponsAmmo = selectedWeaponsAmmo;
selectedWeaponsText.text =
“1:” + selectedWeapons[0] + "
" +
“2:” + selectedWeapons[1] + "
" +
“3:” + selectedWeapons[2] + "
";
}
else if (button == “UseLaserBlaster”) {
selectedWeapons[selectedSlot] = “LaserBlaster”;
selectedWeaponsAmmo[selectedSlot] = 2;
SessionData.selectedWeapons = selectedWeapons;
SessionData.selectedWeaponsAmmo = selectedWeaponsAmmo;
selectedWeaponsText.text =
“1:” + selectedWeapons[0] + "
" +
“2:” + selectedWeapons[1] + "
" +
“3:” + selectedWeapons[2] + "
";
}
else if (button == “UseElectricBlaster”) {
selectedWeapons[selectedSlot] = “ElectricBlaster”;
selectedWeaponsAmmo[selectedSlot] = 4;
SessionData.selectedWeapons = selectedWeapons;
SessionData.selectedWeaponsAmmo = selectedWeaponsAmmo;
selectedWeaponsText.text =
“1:” + selectedWeapons[0] + "
" +
“2:” + selectedWeapons[1] + "
" +
“3:” + selectedWeapons[2] + "
";
}
else if (button == “UseGrenadeLauncher”) {
selectedWeapons[selectedSlot] = “GrenadeLauncher”;
selectedWeaponsAmmo[selectedSlot] = 6;
SessionData.selectedWeapons = selectedWeapons;
SessionData.selectedWeaponsAmmo = selectedWeaponsAmmo;
selectedWeaponsText.text =
“1:” + selectedWeapons[0] + "
" +
“2:” + selectedWeapons[1] + "
" +
“3:” + selectedWeapons[2] + "
";
}
}
}

SESSIONDATA CLASS

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SessionData : MonoBehaviour
{
    public static bool[] worlds = new bool[1];
    public static bool[] levels = new bool[5];

    //Persistent values
    public static Dictionary<string, bool> unlockedWeapons = new Dictionary<string, bool> {
        {"Pistol", false },
        {"MachineGun", false },
        {"SonicBlaster", false },
        {"LaserBlaster", false },
        {"ElectricBlaster", false },
        {"GrenadeLauncher", false },
    };

    // Changing values
    public static string[] selectedWeapons = new string[3];
    public static int[] selectedWeaponsAmmo = new int[3];
}

SHOOT CLASS

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Shoot : MonoBehaviour
{
    public static string[] weapons;
    private int[] weaponAmmo, weaponMaxAmmo;
    public static string currentWeaponName;
    public static int currentWeaponAmmo, currenWeaponMaxAmmo;
    public GameObject[] PistolProjectiles, MachineGunProjectiles, SonicBlasts, LaserBlasts, ElectricBlasts, Grenades;
    public GameObject projectileSpawn, shootDirObject;
    public AudioClip laserPowerUp;
    private bool isFiring;
    private int currentWeapon;
    private int BulletTier = 1;
    private float grenadeShootPower;
    private float pistolTimer, machineGunTimer, sonicBlasterTimer, laserBlasterTimer, electricBlasterTimer, grenadeLauncherTimer;
    private int pistolSlot, machineGunSlot, sonicBlasterSlot, laserBlasterSlot, electricBlasterSlot, grenadeLauncherSlot;
    private bool isStunned;

    public delegate void Test();
    public static event Test test;

    private void Start() {
        weapons = SessionData.selectedWeapons;
        weaponMaxAmmo = SessionData.selectedWeaponsAmmo;
        //Debug.Log("Hi");
        //st = new int[3] {
        //    35,
        //    2,
        //    6
        //};
        //Debug.Log("Hi");
        weaponAmmo = weaponMaxAmmo;
        SetValues();
        CheckWeaponSlots();
        //Debug.Log(weaponMaxAmmo[pistolSlot]);
        //Debug.Log(weaponMaxAmmo[machineGunSlot]);
        //Debug.Log(weaponMaxAmmo[sonicBlasterSlot]);
        //Debug.Log(weaponMaxAmmo[laserBlasterSlot]);
        //Debug.Log(weaponMaxAmmo[electricBlasterSlot]);
        //Debug.Log(weaponMaxAmmo[grenadeLauncherSlot]);

    }

    private void SetValues() {
        currentWeapon = 0;
        currentWeaponName = weapons[currentWeapon];
        currentWeaponAmmo = weaponAmmo[0];
        grenadeShootPower = 10;

        pistolTimer = 0f;
        machineGunTimer = 0f;
        sonicBlasterTimer = 0f;
        laserBlasterTimer = 0f;
        electricBlasterTimer = 0f;
        grenadeLauncherTimer = 0f;
    }

    private void CheckWeaponSlots() {
        for (int i = 0; i < weapons.Length; i++) {
            if (weapons *== "Pistol") {*

pistolSlot = i ;
}
else if (weapons == “MachineGun”) {
machineGunSlot = i ;
}
else if (weapons == “SonicBlaster”) {
sonicBlasterSlot = i ;
}
else if (weapons == “LaserBlaster”) {
laserBlasterSlot = i;
}
else if (weapons == “ElectricBlaster”) {
electricBlasterSlot = i;
}
else if (weapons == “GrenadeLauncher”) {
grenadeLauncherSlot = i;
}
}
}

void Update(){
PlayerMovement coreScript = transform.parent.GetComponent();
isStunned = coreScript.isStunned;
if (isStunned == false) {
Shot();
RotateArm();
ChangeWeapon();
}
ShootTimer();
//To Let PlayerStats display the Ammo of the current Weapon
currentWeaponAmmo = weaponAmmo[currentWeapon];
currenWeaponMaxAmmo = weaponMaxAmmo[currentWeapon];
}

private void ChangeWeapon() {
if (isFiring == false) {
if (Input.GetMouseButtonDown(1)) {
currentWeapon += 1;
if (currentWeapon >= weapons.Length) {
currentWeapon = 0;
}
currentWeaponName = weapons[currentWeapon];
}
}
}

private void Shot() {
if (currentWeaponName == “Pistol”) {
if (Input.GetMouseButtonDown(0)) {
if (weaponAmmo[pistolSlot] > 0) {
if (pistolTimer <= 0) {
pistolTimer = 0.17f;
weaponAmmo[pistolSlot] -= 1;
isFiring = true;
PistolShot();
}
}
else if (weaponAmmo[pistolSlot] == 0) {
weaponAmmo[pistolSlot] = -1;
StartCoroutine(Reload(3, pistolSlot, weaponMaxAmmo[pistolSlot])); // ReloadTime, WeaponID, MaxAmmo
}
}
}
else if (currentWeaponName == “MachineGun”) {
if (Input.GetMouseButton(0)) {
if (weaponAmmo[machineGunSlot] > 0) {
if (machineGunTimer <= 0) {
machineGunTimer = 0.07f;
weaponAmmo[machineGunSlot] -= 1;
isFiring = true;
test();
MachineGunShot();
}
}
else if (weaponAmmo[machineGunSlot] == 0) {
weaponAmmo[machineGunSlot] = -1;
StartCoroutine(Reload(6, machineGunSlot, weaponMaxAmmo[machineGunSlot])); // ReloadTime, WeaponID, MaxAmmo
Debug.Log(weaponMaxAmmo[machineGunSlot]);
}
}
}
else if (currentWeaponName == “SonicBlaster”) {
if (Input.GetMouseButtonDown(0)) {
if (weaponAmmo[sonicBlasterSlot] > 0) {
if (sonicBlasterTimer <= 0) {
sonicBlasterTimer = 0.6f;
weaponAmmo[sonicBlasterSlot] -= 1;
isFiring = true;
StartCoroutine(SonicBlast());
}
}
else if (weaponAmmo[sonicBlasterSlot] == 0) {
weaponAmmo[sonicBlasterSlot] = -1;
StartCoroutine(Reload(4, sonicBlasterSlot, weaponMaxAmmo[sonicBlasterSlot])); // ReloadTime, WeaponID, MaxAmmo
}
}
}
else if (currentWeaponName == “LaserBlaster”) {
if (Input.GetMouseButtonDown(0)) {
if (weaponAmmo[laserBlasterSlot] > 0) {
if (laserBlasterTimer <= 0) {
laserBlasterTimer = 2.3f;
weaponAmmo[laserBlasterSlot] -= 1;
isFiring = true;
StartCoroutine(LaserBlast());
}
}
else if (weaponAmmo[laserBlasterSlot] == 0) {
weaponAmmo[laserBlasterSlot] = -1;
StartCoroutine(Reload(6, laserBlasterSlot, weaponMaxAmmo[laserBlasterSlot])); // ReloadTime, WeaponID, MaxAmmo
}
}
}
else if (currentWeaponName == “ElectricBlaster”) {
if (Input.GetMouseButtonDown(0)) {
if (weaponAmmo[electricBlasterSlot] > 0) {
if (electricBlasterTimer <= 0) {
electricBlasterTimer = 1.4f;
weaponAmmo[electricBlasterSlot] -= 1;
isFiring = true;
ElectricBlast();
}
}
else if (weaponAmmo[electricBlasterSlot] == 0) {
weaponAmmo[electricBlasterSlot] = -1;
StartCoroutine(Reload(4, electricBlasterSlot, weaponMaxAmmo[electricBlasterSlot])); // ReloadTime, WeaponID, MaxAmmo
}
}
}
else if (currentWeaponName == “GrenadeLauncher”) {
if (Input.GetMouseButtonDown(0)) {
if (weaponAmmo[grenadeLauncherSlot] > 0) {
if (grenadeLauncherTimer <= 0) {
grenadeLauncherTimer = 2f;
weaponAmmo[grenadeLauncherSlot] -= 1;
isFiring = true;
GrenadeLaunch();
}
}
else if (weaponAmmo[grenadeLauncherSlot] == 0) {
weaponAmmo[grenadeLauncherSlot] = -1;
StartCoroutine(Reload(7, grenadeLauncherSlot, weaponMaxAmmo[grenadeLauncherSlot])); // ReloadTime, WeaponID, MaxAmmo
}
}
}
}

private IEnumerator Reload(float reloadTime, int weapon, int maxAmmo) {
yield return new WaitForSeconds(reloadTime);
weaponAmmo[weapon] = maxAmmo;
}

private void ShootTimer() {
pistolTimer -= 1 * Time.deltaTime;
machineGunTimer -= 1 * Time.deltaTime;
sonicBlasterTimer -= 1 * Time.deltaTime;
laserBlasterTimer -= 1 * Time.deltaTime;
electricBlasterTimer -= 1 * Time.deltaTime;
grenadeLauncherTimer -= 1 * Time.deltaTime;
}

private void PistolShot() {
Transform projectileTransform = Instantiate(PistolProjectiles[BulletTier - 1], projectileSpawn.transform.position, Quaternion.identity).transform;
Vector3 shootDir = (shootDirObject.transform.position - projectileSpawn.transform.position).normalized;
if (BulletTier == 1) {
projectileTransform.GetComponent().GetDirection(shootDir);
}
else if (BulletTier == 2) {
projectileTransform.GetComponent().GetDirection(shootDir);
}
else if (BulletTier == 3) {
projectileTransform.GetComponent().GetDirection(shootDir);
}

isFiring = false;
}

private void MachineGunShot() {
Transform projectileTransform = Instantiate(MachineGunProjectiles[BulletTier - 1], projectileSpawn.transform.position, Quaternion.identity).transform;
Vector3 shootDir = (shootDirObject.transform.position - projectileSpawn.transform.position).normalized;
if (BulletTier == 1) {
projectileTransform.GetComponent().GetDirection(shootDir);
}
else if (BulletTier == 2) {
projectileTransform.GetComponent().GetDirection(shootDir);
}
else if (BulletTier == 3) {
projectileTransform.GetComponent().GetDirection(shootDir);
}

isFiring = false;
}

private IEnumerator SonicBlast() {
GameObject spawnPoint = projectileSpawn, DirObject = shootDirObject;
Vector3 shootDir = (DirObject.transform.position - spawnPoint.transform.position).normalized;

Transform projectileTransform = Instantiate(SonicBlasts[BulletTier - 1], spawnPoint.transform.position, Quaternion.identity).transform;
if (BulletTier == 1) {
projectileTransform.GetComponent().GetDirection(shootDir);
}
else if (BulletTier == 2) {
projectileTransform.GetComponent().GetDirection(shootDir);
}
else if (BulletTier == 3) {
projectileTransform.GetComponent().GetDirection(shootDir);
}

yield return new WaitForSeconds(0.08f);

projectileTransform = Instantiate(SonicBlasts[BulletTier - 1], spawnPoint.transform.position, Quaternion.identity).transform;
if (BulletTier == 1) {
projectileTransform.GetComponent().GetDirection(shootDir);
}
else if (BulletTier == 2) {
projectileTransform.GetComponent().GetDirection(shootDir);
}
else if (BulletTier == 3) {
projectileTransform.GetComponent().GetDirection(shootDir);
}

yield return new WaitForSeconds(0.08f);

projectileTransform = Instantiate(SonicBlasts[BulletTier - 1], spawnPoint.transform.position, Quaternion.identity).transform;
if (BulletTier == 1) {
projectileTransform.GetComponent().GetDirection(shootDir);
}
else if (BulletTier == 2) {
projectileTransform.GetComponent().GetDirection(shootDir);
}
else if (BulletTier == 3) {
projectileTransform.GetComponent().GetDirection(shootDir);
}

isFiring = false;
}

private IEnumerator LaserBlast() {
AudioSource.PlayClipAtPoint(laserPowerUp, transform.position, 1f);
yield return new WaitForSeconds(1f);

Transform projectileTransform = Instantiate(LaserBlasts[BulletTier - 1], projectileSpawn.transform.position, Quaternion.identity).transform;
Vector3 shootDir = (shootDirObject.transform.position - projectileSpawn.transform.position).normalized;
if (BulletTier == 1) {
projectileTransform.GetComponent().GetDirection(shootDir);
}
else if (BulletTier == 2) {
projectileTransform.GetComponent().GetDirection(shootDir);
}
else if (BulletTier == 3) {
projectileTransform.GetComponent().GetDirection(shootDir);
}

isFiring = false;
}

private void ElectricBlast() {
Transform projectileTransform = Instantiate(ElectricBlasts[BulletTier - 1], projectileSpawn.transform.position, Quaternion.identity).transform;
Vector3 shootDir = (shootDirObject.transform.position - projectileSpawn.transform.position).normalized;
if (BulletTier == 1) {
projectileTransform.GetComponent().GetDirection(shootDir);
}
else if (BulletTier == 2) {
projectileTransform.GetComponent().GetDirection(shootDir);
}
else if (BulletTier == 3) {
projectileTransform.GetComponent().GetDirection(shootDir);
}

isFiring = false;
}

private void GrenadeLaunch() {
GameObject grenade = Instantiate(Grenades[BulletTier - 1], projectileSpawn.transform.position, Quaternion.identity);
Vector3 shootDir = (shootDirObject.transform.position - projectileSpawn.transform.position).normalized;
if (BulletTier == 1) {
grenade.GetComponent().AddForce(shootDir * grenadeShootPower, ForceMode2D.Impulse);
}
else if (BulletTier == 2) {
grenade.GetComponent().AddForce(shootDir * grenadeShootPower, ForceMode2D.Impulse);
}
else if (BulletTier == 3) {
grenade.GetComponent().AddForce(shootDir * grenadeShootPower, ForceMode2D.Impulse);
}

isFiring = false;
}

private void RotateArm() {
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 faceDir = new Vector2(transform.position.x - mousePos.x, transform.position.y - mousePos.y);

if (GameObject.FindWithTag(“Player”).transform.rotation.y == 0) {
if (mousePos.x > transform.position.x) {
transform.up = faceDir;
transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y,
Mathf.Clamp(transform.rotation.eulerAngles.z, 30f, 135f));
}
}
else {
if (mousePos.x < transform.position.x) {
transform.up = -faceDir;
transform.rotation = Quaternion.Euler(180, 180f,
Mathf.Clamp(transform.rotation.eulerAngles.z, 38f, 145f));
}
}
}
}

There are no “private” arrays, only private variables. Arrays are reference types, not value types. So a line like this:

SessionData.selectedWeaponsAmmo = selectedWeaponsAmmo;

will not copy the values over, but it copies the reference to the array over. So both variables now point to the same array. The array you created at the top of your factory manager:

private int[] selectedWeaponsAmmo = new int[3] {
    2,
    3,
    4
};

This declares a private variable “selectedWeaponsAmmo”. You also create a new integer array with 3 elements and you store a reference to that array in your variable. While the variable is private and therefore can not be accessed outside the class, you copy the reference to the array to another classes’ public static variable.

Likewise in your Shoot class you have this line:

weaponMaxAmmo = SessionData.selectedWeaponsAmmo;

which again copies the same reference from the public static variable into a private varaible inside your Shoot class. However all those 3 variables still point to the single int array and any reference can be used to access the object behind that reference.

If you actually wanted to copy the values into a new array, you have to create a new array and copy the values over. So in the first case you would have to do something like:

// create new seperate array with the same size
SessionData.selectedWeaponsAmmo = new int[selectedWeaponsAmmo.Length];
// use the Array.Copy helper method to copy the content of one array to the other:
System.Array.Copy(selectedWeaponsAmmo, SessionData.selectedWeaponsAmmo, selectedWeaponsAmmo.Length);

Of course instead of using the Array.Copy helper method you could also use a for loop and copy them over yourself.

Just another warning for the future: An array of a reference type like a class would also have a similar issue with the actual class instances stored in the array. When you “copy” the class instances from one array to another, the two arrays are of course now seperate, but the references stored in the array point to the same class instances. You can not simply copy or clone a class instance unless the class itself provides a way to create a copy. Of course that does not apply in your case here, but since it seems you have trouble understanding reference types, I think at least a warning could be helpful.