iterate through dictionary with array c# - c#

I have a dictionary with gameobjects as the keys, which is n amount and gameobjects as the values, which is amount of possible 4.
Dictionary<GameObject, ArrayList> polesAttachedToFloor = new Dictionary<GameObject, ArrayList>();
public void AddFloor(GameObject floor)
{
if(floor != null)
{
polesAttachedToFloor.Add(floor, new ArrayList { null,null,null,null });
}
}
public void AddPole(GameObject floor, GameObject pole)
{
for (int i = 0; i <= 4; i++)
{
}
}
How do I iterate through the "values?"... and is there a more 'appropriate' way of doing what Im aiming for?

ArrayList poles;
if (polesAttachedToFloor.ContainsKey(floor))
{
poles = dictionary[floor];
}
if(poles!=null)
{
for (int i = 0; i <= 4; i++)
{
poles.Add(pole);
}
}
Try that inside you AddPole function.

There is how you should encapsulate that...Dont have unity running so may be some typos.
public class FloorManager:MonoBehaviour
{
public gameObject floorPrefab;
private List<Floor> floors;
void Start()
{
floors = new List<Floor>();
}
public void AddFloor()
{
//instantiate prefab // gameObject floorGo = Instantiate....
Floor floorScript = floorGo.getComponent<Floor>();
floors.Add(floorScript);
floorScript.AddPoles();
}
public void RemoveFloor(Floor floor)
{
floors[floors.IndexOf(floor)].gameObject.Destory();
floors.Remove(floor);
}
}
public class Floor : MonoBehaviour
{
public gameObject polePrefab;
public Pole [] poles = new Pole[4];
public void AddPoles()
{
for (int i = 0; i < 4; i++)
{
//instantiate prefab // gameObject poleGo = Instantiate....
Pole poleScript = poleGo.getComponent<Pole>();
poles[i]=poleScript;
}
}
}
public class Pole : MonoBehaviour
{
//some logic here if needed...Destroy...Damage...
}

Play with Enumerator :D Have fun
public void AddPole(GameObject floor, GameObject pole)
{
var enumerator = polesAttachedToFloor.GetEnumerator ();
for (int i = 0; i <= 4; i++)
{
if (enumerator.MoveNext ()) {
var item = enumerator.Current;
}
}
}

Related

Exclude items in an array in unity 2021

I've begun working on an early alpha menu for my game and I've was wondering how to exclude items in an array, specifically in unity. I'm trying to make every item except the currently used one. I don't know how I should go about it, if anyone could help, that would be amazing.
here's my current code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class CS
{
public List<GameObject> CanvasButtons;
}
public class CanvasSwitcher : MonoBehaviour
{
public List<CS> Screen = new List<CS>();
static int switcher;
public static void ScreenSwitchPlus()
{
switcher += 1;
}
public static void ScreenSwitchMinus()
{
switcher -= 1;
}
public void Update()
{
foreach(GameObject l in Screen[switcher].CanvasButtons)
{
l.SetActive(true);
}
}
}
It would be wiser to use for loop instead of foreach loop here:
public void Update()
{
int ignore = 2;
for(int i = 0; i < Screen[switcher].CanvasButtons.Count; i++)
{
if(i != ignore)
Screen[switcher].CanvasButtons[i].SetActive(true);
else
Screen[switcher].CanvasButtons[i].SetActive(false);
}
}
It could be even shorter without if (admit less readable):
public void Update()
{
int ignore = 2;
for(int i = 0; i < Screen[switcher].CanvasButtons.Count; i++)
{
Screen[switcher].CanvasButtons[i].SetActive(i != ignore);
}
}
... and even shorter with taking CanvasButtons out of loop:
public void Update()
{
int ignore = 2;
var collection = Screen[switcher].CanvasButtons;
for(int i = 0; i < collection.Count; i++)
{
collection[i].SetActive(i != ignore);
}
}
I got it! I was a bit null-brained for a while there, I messed up a few values in the second for statement, but I got it. I'll post the code here. I keep forgetting little things in the math. Like I always say, I don't solve problems, I make them.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class CS
{
public List<GameObject> CanvasButtons;
}
public class CanvasSwitcher : MonoBehaviour
{
public List<CS> Screen = new List<CS>();
static int switcher;
public static void ScreenSwitchPlus()
{
switcher += 1;
}
public static void ScreenSwitchMinus()
{
switcher -= 1;
}
public void FixedUpdate()
{
List<CS> csco = Screen;
for(int i1 = 0; i1 < csco.Count;)
{
List<GameObject> collection = csco[i1].CanvasButtons;
for (int i = 0; i < collection.Count; i++)
{
collection[i].SetActive(i1 == switcher);
switch(i == collection.Count - 1)
{
case true:
i1++;
break;
}
}
}
}
}
I think you are making things too complicated.
It could simply be
public void Update()
{
for(var i = 0; i < Screen.Count; i++)
{
foreach(var button in Screen[i].CanvasButtons)
{
button.SetActive(i == switcher);
}
}
}
Two more points though.
First I would make sure that switcher is actually a valid value. You either want to clamp the value to stay within the index range like
public static void ScreenSwitchPlus()
{
switcher = Mathf.Clamp(switcher + 1, 0, Screen.Count);
}
public static void ScreenSwitchMinus()
{
switcher = Mathf.Clamp(switcher - 1, 0, Screen.Count);
}
or you could implement wrap around at the ends according to your needs like
public static void ScreenSwitchPlus()
{
switcher = (switcher + 1) % Screen.Count;
}
public static void ScreenSwitchMinus()
{
switcher -= 1;
if(switcher < 0) switcher = Screen.Count - 1;
}
and then finally as mentioned I wouldn't do this poll fetching the value in Update every frame at all but rather event driven.
If you really need to (I would claim it is just lazyness ;) ) have that value and methods static you could attach to an event like
private static event Action<int> OnSwitcherChanged;
public static void ScreenSwitchPlus()
{
switcher = (switcher + 1) % Screen.Count;
OnSwitcherChanged?.Invoke(switcher);
}
public static void ScreenSwitchMinus()
{
switcher -= 1;
if(switcher < 0) switcher = Screen.Count - 1;
OnSwitcherChanged?.Invoke(switcher);
}
and then listen to that event like
private void OnEnable()
{
OnSwitcherChanged += HandleSwitchChanged;
}
private void OnDisable()
{
OnSwitcherChanged -= HandleSwitchChanged;
}
private void HandleSwitchChanged(int newIndex)
{
for(var i = 0; i < Screen.Count; i++)
{
foreach(var button in Screen[i].CanvasButtons)
{
button.SetActive(i == switcher);
}
}
}
Try this
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class CS {
public List<GameObject> CanvasButtons;
}
public class CanvasSwitcher : MonoBehaviour {
public List<CS> Screen = new List<CS>();
private static bool m_changed = false;
private static int m_lastSwitcher = 0;
private static int m_switcher = 0;
static int switcher {
get {
return m_switcher;
}
set {
if ( switcher != value ) {
m_lastSwitcher = m_switcher;
m_changed = true;
m_switcher = value;
}
}
}
public static void ScreenSwitchPlus() {
switcher += 1;
}
public static void ScreenSwitchMinus() {
switcher -= 1;
}
private void Update() {
if ( m_changed ) {
UpdateCS();
m_changed = false;
}
}
void UpdateCS() {
if ( m_lastSwitcher < Screen.Count ) {
var canvasBtns = Screen[ m_lastSwitcher ].CanvasButtons;
for ( int i = 0; i < canvasBtns.Count; i++ ) {
canvasBtns[ i ].SetActive( false );
}
}
if ( switcher < Screen.Count ) {
var canvasBtns = Screen[ switcher ].CanvasButtons;
for ( int i = 0; i < canvasBtns.Count; i++ ) {
canvasBtns[ i ].SetActive( true );
}
}
}
}

Scene save&load works fine when playing scene directly,but when i load from main menu it's null exception

when i starting my game on the game scene,everything is fine,but when i load from menu,first time is ok,then there is saving data to json,and when i come back to main menu,and then again press play it's " Object reference not set to an instance of an object " for my saveScript which is attached to empty gameObject on game scene.
loading just
SceneManager.LoadSceneAsync("game");
SAVE SCRIPT
public void PopulateSaveData(SaveData sd)
{
//character
sd.s_XP = XP;
respawnScript.instance.PopulateSaveData(sd);
sd.s_x = gameObject.transform.position.x;
sd.s_y = gameObject.transform.position.y;
sd.s_z = gameObject.transform.position.z;
playerHealth.instance.PopulateSaveData(sd);
//sword
playerSword.instance.PopulateSaveData(sd);
//inventory
Inventory.instance.PopulateSaveData(sd);
//sd.s_allItemsPositions = allItemsPositions;
//sd.s_allPotionInteractions = GameObject.FindObjectsOfType<potionInteraction>().ToList();
if (allPotionInteractionO.Count > 0)
{
Debug.Log("ALL POTIONS COUNT " + allPotionInteractionO[0]);
sd.s_allPotionInteractions = allPotionInteractionO;
}
sd.s_allWeaponInteractions = all_swords;
sd.s_allWeaponInteractionsGO = all_swordsGO;
for (int i = 0; i < all_swordsGO.Count; i++)
{
sd.s_allSwordsRotation.Add(all_swordsGO[i].transform.rotation);
}
for (int i = 0; i < all_swordsGO.Count; i++)
{
//because some objects can be destroyed thats why im initializing list again
//allInteractableGameObjects = GameObject.FindGameObjectsWithTag("interactable object").ToList();
// sd.s_allItemsPositions.Add(allInteractableGameObjects[i].transform.position);
sd.s_allSwordsPositions.Add(all_swordsGO[i].transform.position);
}
for (int i = 0; i < allPotionInteractionO.Count; i++)
{
sd.s_allPotionsPositions.Add(allPotionInteractionO[i].transform.position);
}
///going through list and check if there is used item,then saving its bool to another list at same position
for (int i = 0; i < allPotionInteractionO.Count; i++)
{
if (allPotionInteractionO[i].isUsed)
{
allPotionsIsUsed[i] = true;
}
}
sd.s_allPotionsIsUsed = allPotionsIsUsed;
//quest part
for (int i = 0; i < allNPCS.Count; i++)
{
if (allNPCS[i].quest == null)
{
allNpcQuests[i] = null;
}
}
sd.s_allQuests = allNpcQuests;
if(MarieleQuest.instance.currentMarieleQuest!=null)
{
sd.s_currentQuest = MarieleQuest.instance.currentMarieleQuest;
}
foreach (Slot slot in slotsToSave)
{
slot.PopulateSaveData(sd);
}
//enemies
foreach (EnemyStats enemy in all_enemies)
{
enemy.PopulateSaveData(sd);
}
//procedural enemies
foreach (ProceduralStats enemy in all_procedural_enemies)
{
enemy.PopulateSaveData(sd);
}
}
LOAD
public void LoadFromSaveData(SaveData sd)
{
if (SceneManager.GetActiveScene().name == "game")
{
//character
XP = sd.s_XP;
if (sd.s_HP > 0)
{
playerHealth.instance.LoadFromSaveData(sd);
}
else if (sd.s_HP == 0)
{
playerHealth.instance.currentHealth = 100;
}
if (sd.s_respawnObject != null)
{
respawnScript.instance.LoadFromSaveData(sd);
}
if (sd.s_x != 0 && sd.s_y != 0 && sd.s_z != 0)
{
gameObject.transform.position = new Vector3(sd.s_x, sd.s_y, sd.s_z);
}
//sword
if (sd.s_sword != null && sd.s_temp != null && sd.s_currentSword != null && sd.s_currentSwordGO != null)
{
playerSword.instance.LoadFromSaveData(sd);
}
else
{
playerSword.instance.currentSwordGameObject = GameObject.Find("character/mixamorig:Hips/mixamorig:Spine/mixamorig:Spine1/" + playerSword.instance.currentSwordGameObject.name);
playerSword.instance.temp = playerSword.instance.currentSwordGameObject;
}
//potions
if (sd.s_allPotionsIsUsed.Count > 0)
{
allPotionsIsUsed = sd.s_allPotionsIsUsed;
}
//quest
if (sd.s_allQuests.Count > 0)
{
Debug.Log("SD ALL QUESTS" + sd.s_allQuests);
allNpcQuests = sd.s_allQuests;
}
if (sd.s_allQuests.Count > 0)
{
for (int i = 0; i < allNPCS.Count; i++)
{
allNPCS[i].quest = allNpcQuests[i];
}
}
if (sd.s_currentQuest != null)
{
MarieleQuest.instance.currentMarieleQuest = sd.s_currentQuest;
}
if (sd.s_allPotionInteractions.Count > 0)//second pattern in if is changed(FOR REMEMBER)
{
Debug.Log("SD ALL POTIONS > 0");
if (sd.s_allPotionInteractions[0] != null)
{
allPotionInteractionO = sd.s_allPotionInteractions;
}
else
{
allPotionInteractionO = GameObject.FindObjectsOfType<potionInteraction>().ToList();
}
for (int b = 0; b < allPotionInteractionO.Count; b++)
{
allPotionInteractionO[b].isUsed = allPotionsIsUsed[b];
}
for (int i = 0; i < allPotionInteractionO.Count; i++)
{
if (allPotionInteractionO[i].isUsed)
{
allPotionInteractionO[i].gameObject.SetActive(false);
}
}
}
Inventory.instance.LoadFromSaveData(sd);
if (sd.s_allWeaponInteractions.Count > 0)
{
//all_swords = sd.s_allWeaponInteractions;
// all_swordsGO = sd.s_allWeaponInteractionsGO;
for (int i = 0; i < all_swordsGO.Count; i++)
{
if (!Inventory.instance.itemsGameObjects.Contains(all_swordsGO[i])
&& all_swordsGO[i] != playerSword.instance.currentSwordGameObject)
{
all_swordsGO[i].SetActive(true);
all_swordsGO[i].transform.rotation = sd.s_allSwordsRotation[i];
}
}
for (int j = 0; j < sd.s_allSwordsPositions.Count; j++)
{
//Debug.Log(sd.s_allItemsPositions[j] + " " + allInteractableGameObjects[j].name);
all_swordsGO[j].transform.position = sd.s_allSwordsPositions[j];
allPotionInteractionO[j].transform.position = sd.s_allPotionsPositions[j];
}
}
foreach (Slot slot in slotsToSave)
{
slot.LoadFromSaveData(sd);
}
//enemies
foreach (EnemyStats enemy in all_enemies)
{
enemy.LoadFromSaveData(sd);
}
foreach (string id in dead_enemies_ids)
{
SaveData.EnemyData enemyData = new SaveData.EnemyData();
enemyData.e_Health = 0;
enemyData.e_id = id;
sd.enemyData.Add(enemyData);
}
//procedural enemies
foreach (ProceduralStats enemy in all_procedural_enemies)
{
enemy.LoadFromSaveData(sd);
}
foreach (string id in all_procedural_ids)
{
SaveData.ProceduralEnemyData enemyData = new SaveData.ProceduralEnemyData();
enemyData.e_ProcHealth = 0;
enemyData.e_ProcId = id;
sd.proceduralEnemyData.Add(enemyData);
}
}
}
these two scripts just writing data to lists,and reading it from saved file,
saving is called once OnApplicationQuit()
load called at the end of Start()
when i open scene game just from itself and close and load again,everything work fine,because its destroying objects and load them again,but
once i start from main menu,from there do LoadScene("game") i'm getting error that some fields are not exist anymore,but it's like unreal
SaveData script which have all info and store it to file,then read
public class SaveData : MonoBehaviour
{
private void Awake()
{
}
private void Start()
{
s_inventoryGO = new List<GameObject>();
Debug.Log("s_inventoryGO" + s_inventoryGO.Count);
}
//character saving
public int s_XP;
public GameObject s_respawnObject;
public float s_x;
public float s_y;
public float s_z;
//inventory
public List<Item> s_inventory = new List<Item>();
public List<GameObject> s_inventoryGO = new List<GameObject>();
public List<GameObject> s_allGameObjectInventory = new List<GameObject>();
public List<GameObject> s_allInteractableObjects = new List<GameObject>();
public List<potionInteraction> s_allPotionInteractions = new List<potionInteraction>();
public List<weaponInteract> s_allWeaponInteractions = new List<weaponInteract>();
public List<GameObject> s_allWeaponInteractionsGO = new List<GameObject>();
public List<Quaternion> s_allSwordsRotation = new List<Quaternion>();
public List<Vector3> s_allSwordsPositions = new List<Vector3>();
public List<Vector3> s_allPotionsPositions = new List<Vector3>();
public List<bool> s_allPotionsIsUsed = new List<bool>();
public List<Quest> s_allQuests = new List<Quest>();
public Quest s_currentQuest;
public int s_HP;
[System.Serializable]
public struct SlotsData
{
public Item s_slotItem;
public string s_id;
//public Sprite s_icon ;
}
public List<SlotsData> s_slots = new List<SlotsData>();
//sword
public Transform s_sword;
public GameObject s_currentSwordGO;
public GameObject s_temp;
public swordEquipping s_currentSword;
//enemy saving
[System.Serializable]
public struct EnemyData
{
public int e_Health;
public string e_id;
}
public List<EnemyData> enemyData = new List<EnemyData>();
//procedural enemy saving
[System.Serializable]
public struct ProceduralEnemyData
{
public int e_ProcHealth;
public string e_ProcId;
}
public List<ProceduralEnemyData> proceduralEnemyData = new List<ProceduralEnemyData>();
public string toJson()
{
return JsonUtility.ToJson(this);
}
public void LoadFromJson(string json)
{
JsonUtility.FromJsonOverwrite(json, this);
}
}
When using DontDestroyOnLoad wherever you want this object to exist, make a copy of it in your scene if you want the data stored to persist between your game session.
Here is a snippet from the docs
void Awake()
{
GameObject[] objs = GameObject.FindGameObjectsWithTag("music");
if (objs.Length > 1)
{
Destroy(this.gameObject);
}
DontDestroyOnLoad(this.gameObject);
}
It will search for other objects in the scene with the same tag. If it finds it, it will destroy itself. What you can do here is have a public Init() function on your script. When a new scene is loaded with the object and your object already finds an instance of itself, it can pass the local references to the existing object. Something like...
public GameObject objRef1;
public GameObject objRef2;
public void Init(GameObject obj1, GameObject obj2)
{
objRef1 = obj1;
objRef2 = obj2;
...
etc.
}
Inside of the Awake() of the new object, you would call the existing objects Init with the local references it has, which work as it loaded with your scene.
void Awake()
{
// make the tag unique so you only grab objects of this save type
GameObject[] objs = GameObject.FindGameObjectsWithTag("yourObjectsTag");
if (objs.Length > 1)
{
objs[0].GetComponent<YourScriptName>().Init(obj1, obj2, ..., etc.);
Destroy(this.gameObject);
}
DontDestroyOnLoad(this.gameObject);
}
In this approach it means you have a local copy of your DontDestroyOnLoad object in every scene so when the existing one loads in, it can just grab the references from it.

Issue in Unity, NullReferenceException: Object reference not set to an instance of an object [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 5 years ago.
thanks for reading, I am working on a small memory card game in C# using Unity. When I run a certain scene I am receiving constant errors.
The errors are as follows:
"NullReferenceException: Object reference not set to an instance of an object
Card.SetUpArt () (at Assets/Scripts/Card.cs:31)
Pairs.SetUpDeck () (at Assets/Scripts/Pairs.cs:62)
Pairs.Update () (at Assets/Scripts/Pairs.cs:23)"
My code is:
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;
public class Card : MonoBehaviour {
public static bool NO_TURN = false;
[SerializeField]
private int cardState; //state of card
[SerializeField]
private int cardNumber; //Card value (1-13)
[SerializeField]
private bool _setUp = false;
private Sprite cBack; //card back (Green square)
private Sprite cFace; //card face (1-10 JQKA)
private GameObject pairsManager;
void Begin()
{
cardState = 1; //cards face down
pairsManager = GameObject.FindGameObjectWithTag("PairsManager");
}
public void SetUpArt()
{
cBack = pairsManager.GetComponent<Pairs>().GetBack(); //<--error
cFace = pairsManager.GetComponent<Pairs>().GetFace(cardNumber);
turnCard();//turns the card
}
public void turnCard() //handles turning of card
{
if (cardState == 0)
{
cardState = 1;
}
else if(cardState == 1)
{
cardState = 0;
}
if (cardState == 0 && !NO_TURN)
{
GetComponent<Image>().sprite = cBack; // shows card back
}
else if (cardState == 1 && !NO_TURN)
{
GetComponent<Image>().sprite = cFace; // shows card front
}
}
//setters and getters
public int Number
{
get {return cardNumber;}
set { cardNumber = value;}
}
public int State
{
get { return cardState; }
set { cardState = value; }
}
public bool SetUp
{
get { return _setUp; }
set { _setUp = value; }
}
public void PairCheck()
{
StartCoroutine(pause ());
}
IEnumerator pause()
{
yield return new WaitForSeconds(1);
if (cardState == 0)
{
GetComponent<Image>().sprite = cBack;
}
else if (cardState == 1)
{
GetComponent<Image>().sprite = cFace;
}
}
}
And:
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using UnityEngine;
public class Pairs : MonoBehaviour {
public Sprite[] cardFace; //array of card faces
public Sprite cardBack;
public GameObject[] deck; //array of deck
public Text pairsCount;
private bool deckSetUp = false;
private int pairsLeft = 13;
// Update is called once per frame
void Update () {
if (!deckSetUp)
{
SetUpDeck();
}
if (Input.GetMouseButtonUp(0)) //detects left click
{
CheckDeck();
}
}//Update
void SetUpDeck()
{
for(int i = 0; i <deck.Length; i++)//resets cards
{
deck[i].GetComponent<Card>().SetUp = false;
}
for (int ix = 0; ix < 2; ix++) //sets up cards twice,
{
for(int i = 1; i < 14; i++)//sets up card value (2-10 JQKA)
{
bool test = false;
int val = 0;
while (!test)
{
val = Random.Range(0, deck.Length);
test = !(deck[val].GetComponent<Card>().SetUp);
}//while
//sets up cards
deck[val].GetComponent<Card>().Number = i;
deck[val].GetComponent<Card>().SetUp = true;
}//nested for
}//for
foreach (GameObject crd in deck)
{
crd.GetComponent<Card>().SetUpArt();
}
if (!deckSetUp)
{
deckSetUp = true;
}
}//SetUpDeck
public Sprite GetBack()
{
return cardBack;
}//getBack
public Sprite GetFace(int i)
{
return cardFace[i - 1];
}//getFace
void CheckDeck()
{
List < int > crd = new List<int>();
for(int i = 0; i < deck.Length; i++)
{
if(deck[i].GetComponent<Card>().State == 1)
{
crd.Add(i);
}
}
if(crd.Count == 2)
{
CompareCards(crd);
}
}//CheckDeck
void CompareCards(List<int> crd)
{
Card.NO_TURN = true; //stops cards turning
int x = 0;
if(deck[crd[0]].GetComponent<Card>().Number ==
deck[crd[1]].GetComponent<Card>().Number)
{
x = 2;
pairsLeft--;
pairsCount.text = "PAIRS REMAINING: " + pairsLeft;
if(pairsLeft == 0) // goes to home screen when game has been won
{
SceneManager.LoadScene("Home");
}
}
for(int j = 0; j < crd.Count; j++)
{
deck[crd[j]].GetComponent<Card>().State = x;
deck[crd[j]].GetComponent<Card>().PairCheck();
}
}//CompareCards
}
Any help anyone can offer would be greatly appreciated. Thank you in advance.
Link to GitHub Repository
I don't have knowledge about C#, as I'm working with java. You should initialize your variables. For more information I found this link What is a NullReferenceException, and how do I fix it?

Scriptable object doesn't work on build

I'm hoping this might be something simple I'm missing.
I have a ScriptableObject script that looks like this:
using UnityEngine;
using System.Collections;
[CreateAssetMenu]
public class Item: ScriptableObject
{
public string iname;
public int iindex;
public Sprite sprite;
public GameObject itemObject;
public int value;
public string description;
public itemType itemtype;
public enum itemType
{
Consumable,
Equippable,
}
}
This works great in the editor, but if I publish to Android or Windows any script that references the ScriptableObject, it does not work. What am I missing?
For example the following block of code does not seem to execute at all:
for (int i = 0; i < 3; i++)
{
int lootnum = Random.Range(0, 4);
slot1 = itemdb[lootnum];
tlist[i] = itemdb[lootnum];
slotlist[i].transform.GetChild(0).GetComponent<Image>().sprite = itemdb[lootnum].sprite;
slotlist[i].transform.GetChild(0).GetComponent<Image>().enabled = true;
}
Those lists in the code are of the type Item defined in the above script. I'm not sure how to debug this as I get no errors or warnings in the editor.
Here is the script which populates the inventory. There's a bit of junk in there but it definitley works fine pressing play in the editor. Just not on build.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
public class Inventory : MonoBehaviour {
public int invSize;
public Item slot1;
public Item tslot1;
public Item tslot2;
public Item tslot3;
public GameObject t1;
public GameObject t2;
public GameObject t3;
public Sprite itemsprite;
public List<Item> itemdb = new List<Item>();
public List<Item> items = new List<Item>();
public List<Item> tlist = new List<Item>();
public Text stext;
public Text description;
public Item selectItem;
public GameObject selectSlot;
public Object test2;
public List<GameObject> slotlist = new List<GameObject>();
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public void addItem(Item itemToAdd)
{
//items.Add(itemdb[0]);
for (int i = 0; i < 5; i++)
{
if (items[i] == null)
{
items[i] = itemToAdd;
itemsprite = itemToAdd.sprite;
return;
}
}
}
public void GenTreasure()
{
for (int i = 0; i < 3; i++)
{
int lootnum = Random.Range(0, 4);
slot1 = itemdb[lootnum];
tlist[i] = itemdb[lootnum];
slotlist[i].transform.GetChild(0).GetComponent<Image>().sprite = itemdb[lootnum].sprite;
slotlist[i].transform.GetChild(0).GetComponent<Image>().enabled = true;
}
}
public void Uptext(int indexx)
{
stext.text = tlist[indexx].iname;
selectItem = tlist[indexx];
selectSlot = slotlist[indexx];
description.text = selectItem.description;
}
public void Take(int index)
{
//items.Add(selectItem);
for (int i = 0; i < invSize; i++)
{
if (items[i] == null)
{
items[i] = selectItem;
// itemsprite = itemToAdd.sprite;
selectItem = null;
// tlist[i] = null;
// slotlist[i].transform.GetChild(0).GetComponent<Image>().sprite = null;
selectSlot.transform.GetChild(0).GetComponent<Image>().enabled = false;
return;
}
}
}
}
If the script is not in the scene, how does it get loaded? Is it using an asset bundle? If that is the case, then it's possible that the class is being stripped from the build. You can include the class in your link.xml to make sure it's included. Another option is to simply reference the script in an included scene anywhere.

Random Shuffle Listing in Unity 3D

I'm in a little bit of a pickle. I have this script of an array that shows a listing of items. Now the thing is I only want this list to have five items shown out of ten and also shuffled, so you cant have the same list every time you start a new game. I was thinking if there should be a Random.Range implemented but I dont know where. Please Help and Thanks. Heres the script: `
public class RayCasting : MonoBehaviour
{
public float pickupDistance;
public List<Item> items;
#region Unity
void Start ()
{
Screen.lockCursor = true;
}
void Update ()
{
RaycastHit hit;
Ray ray = new Ray(transform.position, transform.forward);
if (Physics.Raycast(ray, out hit, pickupDistance))
{
foreach(Item item in items)
{
if(Input.GetMouseButtonDown(0)) {
if (item.gameObject.Equals(hit.collider.gameObject))
{
numItemsCollected++;
item.Collect();
break;
}
}
}
}
}
void OnGUI()
{
GUILayout.BeginArea(new Rect(130,400,100,100));
{
GUILayout.BeginVertical();
{
if (numItemsCollected < items.Count)
{
foreach (Item item in items)
GUILayout.Label(string.Format("[{0}] {1}", item.Collected ? "X" : " ", item.name));
}
else
{
GUILayout.Label("You Win!");
}
}
GUILayout.EndVertical();
}
GUILayout.EndArea();
}
#endregion
#region Private
private int numItemsCollected;
#endregion
}
[System.Serializable]
public class Item
{
public string name;
public GameObject gameObject;
public bool Collected { get; private set; }
public void Collect()
{
Collected = true;
gameObject.SetActive(false);
}
}
`
To get a random 5 items from your 10 item list you can use:
List<Items> AllItems = new List<Items>();
List<Items> RandomItems = new List<Items>();
Random random = new Random();
for(int i = 0; i < 5; i++)
{
RandomItems.Add(AllItems[random.Next(0, AllItems.Count + 1)]);
}
The AllItems list contains your 10 items.
After the loop you will have 5 random items inside the RandomItems list.
Just figured it out, this is my solution for shuffle any kind of List
public class Ext : MonoBehaviour
{
public static List<T> Shuffle<T>(List<T> _list)
{
for (int i = 0; i < _list.Count; i++)
{
T temp = _list[i];
int randomIndex = Random.Range(i, _list.Count);
_list[i] = _list[randomIndex];
_list[randomIndex] = temp;
}
return _list;
}
}
With your example it should work like this:
AllItems = Ext.Shuffle<Items>(AllItems);
Debug.Log(AllItems[0]); // Will be always random Item
If you need 5 random Items, you can just call
Debug.Log(AllItems[0]); // Random Item
Debug.Log(AllItems[1]); // Random Item
Debug.Log(AllItems[2]); // Random Item
Debug.Log(AllItems[3]); // Random Item
Debug.Log(AllItems[4]); // Random Item

Categories

Resources