- Home /
How to collect items once ?
Basically i am making a game which has three levels which connect to a homeworld each level has for example 100 items to collect. when the player collects an item in the level and i leave the level and return i want that item to not be there.
so basically my problem is when i collect items in a level, go to home, come back all the items reappear which i dont want. when an item is collected i want them to be gone and not come back when switching between levels.
like ive placed 100 items in my scene could i assign a unique id to each item and then kindv save the collected items ids in a array so when the scene is loaded again items with that id are destroyed
sorry if thats confusing. if you could point me in the right direction that would be good or give an example thanks im new to this. Im writting in c# if that matters.
You need to save the ones collected. No other easy way to do so.
I would suggest looking into using playerprefs as its the easiest
When collected say an item called coin
Playerprefs.setint("coin1", 1)
Then on load level
If (Playerprefs.getint("coin1") == 1) Destroy (game object.find("coin1")
Can also use bools
Please excuse my case sensitive. Am typing using iPad
So in level one i have say 100 coins, i have to name them all? also how do you name them is it the name in the hierarcy or the tag name or something else.
sorry im new to this.
You just need an array to identify each one, how does your game work do you just place the coins on the scene individually or do you instantiate a prefab?
Also 2D or 3D?
Answer by Mmmpies · Feb 15, 2015 at 02:37 PM
If your player is don't destroy on load then the easiest is to have an array of bools for each level in a script attached to the player, call it something like levelOnePickedUp, when the level loads access the player script and load only those items that are still false. When you pick one up set the corresponding array item to true.
You will need to save in player prefs as @Klarax says but for that you want this:
Both C# and Javascript/boo examples in that page.
EDIT
OK so I created 64 empty GameObjects, highlighted them all and tagged them as Coin.
using UnityEngine;
using System.Collections;
public class PlayerPrefsXTest : MonoBehaviour{
private Vector3[] coinPos = new Vector3[64]; // Assumes you have exactly 100 objects
private Quaternion[] coinRot = new Quaternion[64];
private bool[] coinCollected = new bool[64];
private int countCoins;
void Start()
{
countCoins = 0;
foreach(GameObject go in GameObject.FindGameObjectsWithTag("Coin"))
{
coinPos[countCoins] = go.transform.position;
coinRot[countCoins] = go.transform.rotation;
coinCollected[countCoins] = false;
go.name = countCoins.ToString();
countCoins ++;
}
PlayerPrefsX.SetVector3Array("levelOnePos", coinPos);
PlayerPrefsX.SetQuaternionArray("levelOneRot", coinRot);
PlayerPrefsX.SetBoolArray("levelOneCollected", coinCollected);
// coinCollected = PlayerPrefsX.GetBoolArray("levelOneCollected");
// coinPos = PlayerPrefsX.GetVector3Array("levelOnePos");
// coinRot = PlayerPrefsX.GetQuaternionArray("levelOneRot");
for (int i = 0; i < coinCollected.Length; i++)
{
Debug.Log("Coin Number " + i + " Position = " + PlayerPrefsX.GetVector3Array("levelOnePos")[i] +
" Rotation = " + PlayerPrefsX.GetQuaternionArray("levelOneRot")[i] +
" Collected = " + PlayerPrefsX.GetBoolArray("levelOneCollected")[i]);
}
}
}
This script uses that PlayerPrefsX script to store all the Coin positions and quaternion rotations. as well as renames all the coins to a number. It also stores if that number has been collected already in a bool[] Array.
Really you only need the last one if you want to just use set active to show or hide the coins but, it makes a lot of sense to instantiate the coins when the level loads.
That call is yours though, just make sure you understand what the above script does, you'll need to change the number from 64 to however many you want.
Feel free to ask questions, and I don't expect this to be the last update for this just want to make sure I don't give too much info in one go.
Just be careful to rename the leveOneRot, levelOnePos and levelOneCollected to something different for each level so you dont overwrite other levels entries in playerPrefs.
Ultimately we want the ability to remove all the coins in your scene(s) and instantiate only the uncollected from a single prefab.
Once you've got all levels coins stored then we switch so we get the coin location/rotation from player prefs when the level starts and store the 3 arrays locally. We only set the player prefs when we exit the level or game.
EDIT
I posted the link to the page above in the ArrayPrefs link. Scroll down that page until you get to C# - PlayerPrefsX.cs then copy that script and save it as that file.
what goes in the PlayerPrefsX script? is it just get and set methods
i get an error at line 18 it says index out of range exception : array index is out of range. Edit: I fixed that error :D
so i can see the individual position and that is set to false in the log but when i collect go to a different level come back it resets. i think i need to add dont destroy on load somehow? is that it
No the player prefs for the level you're on need to be saved when you exit the level, so if you go to a different level you load the local array from the player prefs. I commented out how you do that in the script I posted above:
// coinCollected = PlayerPrefsX.GetBoolArray("levelOneCollected");
// coinPos = PlayerPrefsX.GetVector3Array("levelOnePos");
// coinRot = PlayerPrefsX.GetQuaternionArray("levelOneRot");
so you have 3 local arrays for each level and when you open that level you put the above (without the //) in Start. Remember in level/scene 2 you change all three names to levelTwoCollected, levelTwoPos & levelTwoRot and so on for all your levels.
So when you exit a level use this (no need to resave coinPos/Rot as they don't change)
PlayerPrefsX.SetBoolArray("levelXXXCollected");
and when you enter a level use this (replace XXX for the level number)
coinCollected = PlayerPrefsX.GetBoolArray.("levelXXXCollected);
coinPos = PlayerPrefsX.GetVector3Array("levelXXXPos");
coinRot = PlayerPrefsX.GetQuaternionArray("levelXXXRot");
Player Prefs are stored outside the individual scenes so they remain persistant so no need for don't destroy on load.
When you pick up a coin all you have to do is set the local coinCollected[THE COIN NU$$anonymous$$BER] to true, so when you exit the level, as long as you SetBoolArray as above, it'll save those already collected.
Idealy you'll get the player prefs when you load the level then loop through all the coinCollect array and only instantiate those not already collected.
When you start a new game all you have to do is set all levelXXXCollected to false and all coins will magically reappear.
Let me know when you have all levels saved in their individual Player Prefs localtions and I'll post the code to instantiate the objects.
Answer by awplays49 · Feb 15, 2015 at 02:27 PM
unfortunately you'll have to make a playerpref for each one. Unless this might work:
PlayerPrefs.SetInt ("CoinPref" + CoinID [Number], 1);
Answer by Kiwasi · Feb 19, 2015 at 09:31 AM
There are a bunch of other ways to save data that don't involve player prefs. See the tutorial for more details.
One approach I have used in the past is to serialise an array, then converted the resulting bits to a string. That string can then be saved to player prefs, a file or a server and reloaded again at will.
I would then recommend the UnitySerializer from the Asset store. It is free and has a video tutorial.
True @Bored$$anonymous$$ormon, in fact the OP has already mentioned DontDestoryOnLoad. I wanted to make sure we had a save location for the coins as they are currently just placed in the scene and PlayerPrefs had already been mentioned so seemed like a good path to go down. Hopefully we're not that far from a working solution.
Effectivly the free PlayerPrefsX converts to a string and saves in player prefs.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Don't Load Collected items 1 Answer
UnitySerializer Only Saving one Game Problem 0 Answers
C# Issues with either PlayerPrefs.SetVariable or UnityEvent.Invoke 1 Answer