How to save and load selected Dropdown values in unity - c#

I am trying to make a dropdown that allows you to select different ways to display time. I got it all working except I need to find a way to save and load the option the player selected.
private void Start() {
timeDropdown.options.Clear();
List < string > items = new() {
"",
DateTime.Now.ToString(),
DateTime.Now.ToLongDateString(),
DateTime.Now.ToLongTimeString()
};
foreach(var item in items) {
timeDropdown.options.Add(new TMP_Dropdown.OptionData() {
text = item
});
}
DropdownItemSelected(timeDropdown);
timeDropdown.onValueChanged.AddListener(delegate {
DropdownItemSelected(timeDropdown);
});
}
void DropdownItemSelected(TMP_Dropdown timeDropdown) {
int index = timeDropdown.value;
timeText.text = timeDropdown.options[index].text;
}
I think you would use an int to save it but I don't know how to do that. Thank you.

You could use unity's player prefs system below is a link to documentation on how it works.
Unity player prefs documentaion
Alternatively you could create your serialisation system here's a Brackey's video which shows how to make a basic class serialisations system
YouTube tutorial
For what your trying to do the fastest and quickest approach would be to just use player prefs for saving and loading the int value.

Related

Organizing inventory by alphabetical order

So I created a method to populate the inventory system I have created in Unity, however I can't seem to figure out a way to order them in alphabetical order. Each button is created as a child of the button holder panel which is a game object variable. This method is called whenever the player picks something up.
private void Populate_Inventory ( )
{
Button btn_CurrentItem;
int int_Count;
for ( int_Count = int_PreviousCount; int_Count < strList_Inventory.Count; int_Count++ )
{
btn_CurrentItem = Instantiate ( btn_Item, pnl_ButtonHolder.transform );
btn_CurrentItem.name = strList_Inventory [ int_Count ];
btn_CurrentItem.GetComponentInChildren<Text> ( ).text = strList_Inventory [ int_Count ];
btn_CurrentItem.gameObject.AddComponent<Inventory_Item> ( );
btn_CurrentItem.GetComponent<Inventory_Item> ( ).str_Name = cls_Pickup.str_PickupName;
btn_CurrentItem.GetComponent<Inventory_Item> ( ).str_Information = cls_Pickup.str_PickupInformation;
int_PreviousCount = int_Count;
}
int_PreviousCount++;
}
If anyone can help it would be very appreciated.
Jonathan Palmer
The primary issue with this approach is that you're adding single buttons at a time whenever you pick up an item, and those buttons are created as children of the pnl_ButtonHolder object, but your method has no knowledge of previous buttons that have been created.
Option 1 (Bad)
You can use the GetComponentsInChildren<Button>() method on the pnl_ButtonHolder object to get all of the button components that have been previously created once you've added a new button, and then sort your buttons according to their name.
This isn't ideal as GetComponentsInChildren<>() is an expensive method, and doesn't make use of the idea of an Inventory very well.
Option 2 (Good)
Create an Inventory class that manages your actual inventory, including sorting items. It might look something like this:
public class Inventory_Button : MonoBehaviour
{
public Button button = default;
public void Initialize(Intenvory_Item item)
{
button.name = item.name;
// Other work here.
}
}
public class Inventory : MonoBehaviour
{
public GameObject inventoryItemPrefab = default;
public Transform inventoryParent = default;
private List<Inventory_Item> _inventory = new List<Inventory_Item>();
private List<Inventory_Button> _inventoryButtons = new List<Inventory_Button>();
public void AddItem(Intenvory_Item item)
{
_inventory.Add(item);
Inventory_Button button = GameObject.Instantiate(inventoryItemPrefab, inventoryParent).GetComponent<Inventory_Button>();
button.Initialize(item);
_inventoryButtons.Add(button);
_inventoryButtons.Sort((x, y) => x.name.CompareTo(y.name));
}
public void RemoveItem(Inventory_Item item)
{
// Do work to remove the item.
}
}
This kind of setup is useful for several reasons:
Your inventory management is now handled by a single class rather than a collection of objects. This makes it easy to interact with.
It will make removing items much easier in the future. With your current implementation, it looks like you'd have a difficult time removing an item from the player's inventory.
It separates responsibility between an Inventory class, an Inventory_Item class, and an Inventory_Button class, each of which stands on its own and works together.
A few final notes:
I've left out some details in the two classes above. You should fill them in to fit the needs of your game.
You can be more efficient with sorting by using something like Insertion Sort. This solution will get the job done.
Using prefixes for naming your variables can be quite confusing to people trying to read your code. I recommend you check out a style guide. There's a great one here.

Using a listbox to display a list across different classes

I have implemented a list system which records the users name, the total amount of points which they have scores and the amount of time it took to do this. Im now having problems with trying to display the list "players" from another class. So within my HighScoresMenu form when trying to display the content of the players list within a the list box, the list box only displays "Game.Player".
Is there any possible solutions to this issue. Any Help would be appreciated.
public partial class MainMenu : Form
{
public static List<Player> GetPlayers(float newScore, float newPoints,
string PlayersName)
{
var players = new List<Player>();
var newPlayer = new Player
{
Name = PlayersName,
Points = newPoints,
Timer = newScore
};
players.Add(newPlayer);
var TopTenLevel1 = players.OrderByDescending(x => x.Timer).Take(10);
return players;
}
}
public partial class HighScoresMenu : Form
{
foreach (var players in MainMenu.GetPlayers(newScore, newPoints,
PlayersName))
{
ListBoxLevel1.Items.Add(players);
}
}
Ok, so to begin, I might not understand your question correctly. What I get from it is that your list view is displaying the name of the object, hence the "Game.Player". So you would have to change the following:
ListBoxLevel1.Items.Add(players);
to something like the following:
ListBoxLevel1.Items.Add($"Player: {players.Name}, Score: {players.Points}");
I'm not sure what your list box is taking as a parameter in the Items.Add(); method, so this answer is assuming it's a string.
I had this problem also few years ago: The function GetPlayers is static, that means that the content (value) or the variable isn't accessible from other classes.
You need to remove 'static' and initiate the MainMenu in the HighScoresMenu class like this:
//MainMenu
public static List<Player> GetPlayers(float newScore, float newPoints, string PlayersName)
//HighScoreMenu
MainMenu main = new MainMenu();
menu.GetPlayers(newScore, newPoints, PlayersName);
I hope this will fix the problem (removing keyword 'static' from the function and initiating the MainMenu class)
I would glad to hear if the current situation is solved or not. :) I hope I did remember it good.
Edit
After I took a second look you are foreach looping it as var player.
But loop it as Player player. Because you putted in in the other class as Player object inside a list of Players. Now you are retrieving it as a var.**
So the final conclusion:
public partial class HighScoresMenu : Form
{
foreach (Player players in MainMenu.GetPlayers(newScore, newPoints,
PlayersName))
{
ListBoxLevel1.Items.Add(players.getName());
}
}
I am curious let me know :D
Edit 2
Also letting you know in case of you never know. You are always making just one Player so there isn't actually a list needed and this piece of code:
var TopTenLevel1 = players.OrderByDescending(x => x.Timer).Take(10);
This will order it but you aren't doing anything with it (var 'TopTenLevel1'). Just letting you know :) You could save the ordered list by returning it (overwriting variable also possible).

Programmatically change Dropdown Menu Options in Unity3D

i got Unity3D 5.2 and use the Dropdown GUI element for the first time. It is easy to use in the insepctor but i want the Options to show, be dependent of my files in Resources/Shapes/
So the dropdown should show all filenames i got in Resources/Shapes/ but i can not get a hold of this property in the attached C# script.
After reading the manual on Dropdown, there should be a property with the name "Options" and it should have a string and an image variable. (So for my understanding its a two dimensional array-ish type)
Unfortunately i cant use the following script (pseudo code since it doesnt work)
GameObject obj = GameObject.Find("Dropdown");
var info = new DirectoryInfo("Assets/Resources/Shapes");
var fileInfo = info.GetFiles();
foreach (var file in fileInfo)
{
//Add OptionsString Pseudo-Code
obj.Options += file; // Options doesnt exist
}
Can anyone explain to me how i can manipulate the Options property on my Dropdown menu pls, i cant find anything in google. Only old ways from before the time Unity had a built in Dropdown menu
Thanks in advance
List<string> list = new List<string> { "option1", "option2" };
var dropdown = GetComponent<Dropdown>();
dropdown.options.Clear();
foreach (string option in list)
{
dropdown.options.Add(new Dropdown.OptionData(option));
}
Found the answer:
Dropdown.OptionData list = new Dropdown.OptionData("Name");
obj.GetComponent<Dropdown>().options.Add(list);
The answares are correct, but are missing one line of code:
dropdown.RefreshShownValue();
After you add the values and set the selected option, you should refresh whats shown.
The full code for a TextMesh Pro Dropdown would be like:
List<string> list = new List<string> { "option1", "option2" };
dropdown.options.Clear();
foreach (string option in list)
{
dropdown.options.Add(new TMP_Dropdown.OptionData(option));
}
dropdown.value = 0;
dropdown.RefreshShownValue();

Return the Next Item in a ListView with a twist

I've been working on the past couple of days on a ListView based Music player using NAudio in C#. It's now time for me to start working on the forward/previous functions but I've come to a bit of a bump in the road. I need to select whatever the next item in the listView I have is. However, it is not selected by the user but instead is marked as now playing by a checkmark next to it with the default ListView checkboxes.
Here's what it looks like:
I've got a public string that's accessible by anything; it has the filename of the currently playing track in it. Whenever I click to play a track, I've got a foreach loop that loops through all of the items in this listView (I've got a second listview in another tab that has all the music I click to play from) and if the filename subitem and currentlyPlaying string match, then it checks it. If not, it unchecks.
I've got an event handler in my mainclass for when the playback stops on the track. What's going to go in there will be the logic for the next track. I've got a general idea of what to do but I'm not sure how to go about doing it
Get the index of the item with the check mark next to it
Get the item after it
Retrieve its fileName subitem
Play it
So what would be the way to go about doing this? I'm still a bit confused with listViews and such.
Update: Also, how possible is it to disable the user checking the check box, I've got it down for when it's a double click but what about when the user checks the checkbox themselves?
Update 2: Here's the eventhandler with some scratch code I was working on
public void waveOutDevice_PlaybackStopped(object sender, StoppedEventArgs e)
{
string fileName;
foreach (ListViewItem lvi in playListView.Items)
{
fileName = lvi.SubItems[1].Text;
if(lvi.Checked == true)
{
int finIndex;
lvi.Checked = false;
finIndex = lvi.Index;
//finIndex + 1;
}
}
}
I think you are just about there. all you need to do is something like this:
public void waveOutDevice_PlaybackStopped(object sender, StoppedEventArgs e)
{
string fileName;
foreach (ListViewItem lvi in playListView.Items)
{
fileName = lvi.SubItems[1].Text;
if(lvi.Checked == true)
{
int finIndex;
lvi.Checked = false;
finIndex = lvi.Index;
finIndex++;
if(finIndex < playListView.Count())
{
var nextGuy = playListView.Items[finIndex];
nextGuy.Checked = true;
//Play the file and what not.
}
}
}
}

How to alias Xbox 360 buttons in C#?

I'm new to C Sharp, and writing a game w/ the XNA Framework.
I'm trying to establish variables for the buttons on the XBox 360 controller, so I can reconfigure the buttons' game functions in one place and not have to change direct references to the buttons everywhere.
So if I want to assign a button to "attack", instead of this:
if (gamePadState.IsButtonDown(Buttons.B)
{
// do game logic
}
I want to do this:
if (gamePadState.IsButtonDown(MyAttackButton)
{
// do game logic
}
Any ideas? I'm sure it's a very simple solution, but I've tried several approaches and none have worked yet. Thanks!
Buttons is just an enum, so you just need to create a variable with that name like
Buttons MyAttackButton = Buttons.B;
An alternative would be to define an enum somewhere:
public enum MyButtons
{
AttackButton = Buttons.B,
DefendButton = Buttons.A
}
Then to test it:
if (gamePadState.IsButtonDown((Buttons)MyButtons.DefendButton))
You could also create a dictionary:
enum MyButtons { ShootButton, JumpButton }
Dictionary<MyButtons, Buttons> inputMap = new Dictionary<MyButtons, Buttons>()
{
{ MyButtons.ShootButton, Buttons.Y },
{ MyButtons.JumpButton, Buttons.B },
}
...
if (gamePadState.IsButtonDown(inputMap[MyButtons.ShootButton]))
{
// Shoot...
}
The advantage of this method is that the button map can be modified at runtime, so you can use it to implement customizable control settings.

Categories

Resources