copying custom class list to another list - c#

I have figured out (or at least it feels like I have figured out) a way to make a list of weapons without having to hardcode everything like I was last trying.
So I have got my custom class for a weapon specifying type name attribute etc.
I have created another script will show a list in Unity's inspector that I can keep adding weapons to and changing the values to what I see fit.
I also have a game manager script that is the route of everything to from player stats game state etc..
I want to have this list now transferred to the game manager as a new list in that script.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[System.Serializable]
public class GameManager {
public static GameManager GM;
public static int FileIndex;
public static List<Weapons> WeaponM = new List<WeaponDB>();
public PlayerData Player;
public bool SaveEnabled;
public bool IsPaused;
public int TimeHour;
public int TimeMinute;
public GameManager(){
Player = new PlayerData();
}
}
that would be my game manager. Would it not be as easy as typing
public static List<Weapons> WeaponM = new List<WeaponDB>();
and have all the list entries stored in there copied over to the list entry in my gamemanager?
Here is my WeaponDB script so you can see and I have another script but it just sets all the different attributes.
using UnityEngine;
using System.Collections.Generic;
using System.Collections;
public class WeaponDB : MonoBehaviour{
public List<Weapons> Weapon;
public WeaponDB(){
}
public WeaponDB(List<Weapons> wpl){
Weapon = wpl;
}
void Start(){}
void Update(){}
}
I am getting an error of
CS0246 the type or namespacename "weaponsdb" could not be found"

Related

Saving a list of ScriptableObject into json

My Item script
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName ="Newitems",menuName ="Inventory/Items")]
[Serializable]
public class Item : ScriptableObject
{
new public string name = "New items";
//public Sprite Icon = null; dealt with this later
public bool isDefaulet = false;
...}
And here is my inventory script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;
[Serializable]
public class Inventory : MonoBehaviour
{
[SerializeField]
public List<Item> items = new List<Item>();
void Save()
{
string json = JsonUtility.ToJson(items);
Debug.Log(json);
File.WriteAllText(Application.dataPath + "/saveFile.json", json);
}
public void Load()
{
string json = File.ReadAllText(Application.dataPath + "/saveFile.json");
List<Item> List = JsonUtility.FromJson<List<Item>>(json);
Debug.Log(List);
}
...
}
Ok, i will try with the sprite later, but when saving, the console return {}, i have no idea now, please help.
The first things to save your scriptable in json is to add the class attribute Serializable on each scriptable you want to serialize in json.
But here I think it will be hard to serialize the Icon field. In a json you really can save only number or string and there is a reference.
A way to serialize a Sprite ( or any reference) is to serialize the name or the id of the object. If you look how unity serialize a scene it’s exactly how it’s done.
And then when you read your json you replace that id by your asset.
Some json library can help on that, NewtonSoft Json.Net can help, specially on the special serialization for reference I describe.
Try it without the Sprite first and add complexity after ;)
EDIT
To be more precise, I think the better way to do what your try, is to not serialize a ScriptableObject, but instead a class hold by the scriptable.
class MyScriptable : ScriptableObject
{
private MySerializableClass data;
}
[Serializable]
class MySerializableClass
{
private string name;
private float data1;
private float data2;
}
Then serialize the MySerializableClass, and use the name, or some id field to link each instance of scriptable with the good MySerializableClass :)

Set Time Selection in Unity

I am doing a Unity project.
I have two scenes in my project.
In the first scene. I set three buttons texted "1 min", "2 mins" and "3 mins".
And I want to have the corresponding game duration in my second scene (game scene).
I have countdown function in my script.
now I am using singleton pattern following the steps of this tutorial. https://www.youtube.com/watch?v=CPKAgyp8cno
Problem is when I run the game, three texts of time start simultaneously.
And my buttons in Scene one could control load scenes but not choose time.
The following are the codes. In the PersistentManager Script which attached to the PersistentManager game object:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PersistentManagerScript : MonoBehaviour
{public static PersistentManagerScript Instance { get; private set; }
public int Value;
// Start is called before the first frame update
private void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
}
In the SceneManager Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SceneManagerScript : MonoBehaviour
{
public GameObject CountDownIn1;
public GameObject CountDownIn2;
public GameObject CountDownIn3;
public Text ValueText;
public Text ValueText1;
public Text ValueText2;
private void Start()
{
switch (this.gameObject.name)
{
case "Button1min":
SetGameTimeEqualOne();
break;
case "Button2mins":
SetGameTimeEqualTwo();
break;
case "Button3mins":
SetGameTimeEqualThree();
break;
}
}
public void SetGameTimeEqualOne()
{
CountDownIn1.SetActive(true);
ValueText.text = PersistentManagerScript.Instance.Value.ToString();
Debug.Log("COUNTDOWN1 active");
//DontDestroyOnLoad(this.CountDownIn1);
}
public void SetGameTimeEqualTwo()
{
CountDownIn2.SetActive(true);
Debug.Log("COUNTDOWN2 active");
ValueText1.text = PersistentManagerScript.Instance.Value.ToString();
DontDestroyOnLoad(this.gameObject);
}
public void SetGameTimeEqualThree()
{
CountDownIn3.SetActive(true);
Debug.Log("COUNTDOWN3 active");
ValueText2.text = PersistentManagerScript.Instance.Value.ToString();
DontDestroyOnLoad(this.gameObject);
}
Any suggestions will be appreciated.
There are multiple ways to pass data between scenes. The most common recommendation is to use a Singleton pattern that is consumed by other scripts in each scene. However, this can be overly complicated.
Interestingly enough, Unity's newer ScriptableObjects can be used for a similar strategy. Since ScriptableObjects are persisted at a higher scope than scenes, you can use them to hold data between scenes without having to utilize statics and singletons. Unity even markets them as more than just data containers! I prefer to pass data between objects and scenes by creating a common scriptable object, and referencing that asset in each script that needs to share data (regardless of scene).
Here's an example using your requirement:
GameData.cs
[CreateAssetMenu(fileName = "GameData", menuName = "Game Data")]
public class GameData: ScriptableObject
{
float gameDuration; //This is where you will store and read your selected game duration
}
GameSelection.cs This script exists on Scene 1
public class GameSelection : Monobehaviour
{
public GameData gameData;
public void SetDuration(float time) //Call this method from each button with a different parameter
{
gameData.gameDuration = time;
}
}
Countdown.cs This script exists in Scene 2
public class Countdown: Monobehaviour
{
public GameData gameData;
float countdownTimer;
public void Start()
{
countdownTimer = gameData.gameDuration;
}
//... rest of your countdown script
}
Now you can create a GameData asset in your project folder and drag it into the inspector in Scene1, and the inspector in Scene2. If Scene1 changes the value of the timer, Scene2 will know about it. Additionally, you can set a default value for gameDuration on the GameData asset and run/test Scene2 without having to run Scene1 first!

Changing Player Sprite through Shop

I'm trying to create a shop where you can buy a different player sprite from in-game currency. (The shop is a separate scene from the level) I was told that using scriptableobject is the way to go, so I made the following:
[CreateAssetMenu(fileName = "New Sprite", menuName = "Player Sprites")]
public class PlayerSprites : ScriptableObject
{
public string spriteName;
public int cost;
public Sprite sprite;
}
And I just added to the player script
public SpriteRenderer spriteRenderer;
void Start()
{
spriteRenderer = GetComponent<SpriteRenderer>();
}
I'm not really sure where to go from here... how to render the sprite on to the player from a different scene when the sprite button is pressed... Any help is greatly appreciated thank you!
Though your question is quite hazy and I don't really see what you tried so far:
As you have it right now you will need one ScriptableObject for each Sprite item ... I don't think that's what you want. You should rather use one ScriptableObject storing the information of all Sprite items.
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "Assets/New Store", menuName = "Sprites-Store")]
public class SpriteStoreContainer : ScriptableObject
{
public List<StoreSpriteItem> SpriteItems = new List<StoreSpriteItem>();
// you can/should also implement methods here as in any usual component!
}
Also make sure your fileName starts with Assets/
And a separate class for the Items which uses [System.Serializable] so you can display it in the Inspector.
using UnityEngine;
[System.Serializable]
public class StoreSpriteItem
{
public string spriteName;
public int cost;
public Sprite sprite;
public bool IsAvailable;
// also here you could/should implement some methods e.g.
public void BuyItem()
{
IsAvailable = true;
}
}
And back in Unity:
Now you first have to Instantiate the ScriptableObject asset:
Go to the Project View (Assets) -> right mouse click -> in the menu click on Create -> click on Sprites-Store
This should create a new asset called New Store(.asset) under Assets
Now in the Inspector of this created asset you fill in the information you need. You should see our List SpriteItems with Size = 0.
To create elements just increase the Size value and hit enter(Carefull: Unity doesn't ask if you change this value => take care you don't delete items by reducing this value accidently later)
Now you can adjust all information for those SpriteItems
Later wherever you need access to the information of this Asset you can just use the reference as any other Component => you can assign it e.g. via the Inspector using a public field e.g.
using UnityEngine;
public class ScriptThatUsesStore : MonoBehaviour
{
public SpriteStoreContainer Store;
public void DoSomthingWithStore()
{
// example: just get the first List element
Sprite someSprite = Store.SpriteItems[0].sprite;
}
}
and than access the data in it. Though I strongly recommend you rather implement some methods in the ScriptableObject like e.g. BuyItem, GetSprite, etc.

Access public static variable from another script Unity

I am trying to access and change of the value of a variable from another script, I have watched various different tutorial on youtube but cannot seems to do it. It always come up with an error as following:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GlobalValues : MonoBehaviour
{
public static bool c2u;
}
And the other script
public class Choosing : MonoBehaviour {
private void Start()
{
GlobalValues.c2u = false;
}
}
In the "Choosing" script, the GlobalValues always shows "'GlobalValues' does not exist in this current context". What can i do to fix this problem
That code should work fine. The only way I could see it not working is if you haven't saved one of the scripts.

Unity3D - Editor Window that can save data to an array that isn't cleared when you play

I'm trying to create an editor window that's able to create in game items.
It's supposed to add the item to a list of items that doesn't get cleared every time you play the game.
Is it possible to do this without an external XML/JSON file to save the data in.
I currently have this in my editor window script, ItemEquipable(type, price) is a basic class that just has a type and a price variable:
if(GUILayout.Button("Create"))
ItemList.items.Add(new ItemEquipable(type, price));
And the ItemList class, ItemEquipable extends the base Item class.
using UnityEngine;
using System.Collections.Generic;
public class ItemList:MonoBehaviour {
public static List<Item> items;
}
I've attached the ItemList to a GameObject that's in the scene.
I've seen Custom editor: How to initialise a new array element? but that script extends Editor and I'm extending EditorWindow, so I don't have access to a target variable.
Update:
Okay so I've tried making the ItemList class serializable
using UnityEngine;
using System;
using System.Collections.Generic;
[Serializable]
public class ItemList:MonoBehaviour {
public static List<Item> items;
}
And making a singleton out of it
using UnityEngine;
using System.Collections.Generic;
public class ItemList:Singleton<ItemList> {
public List<Item> items;
}
With the Singleton being your basic singleton class/code
Buth neither one is working.
The item array is not marked as Serializable so Unity can't save it when you launch the game. The solution is to mark ItemList with the attribute [Serializable], or you can just use a List<Item> directly.
So the way I solved it is by saving the array to a prefab every time you create an item.
UnityEngine.Object prefab = PrefabUtility.CreateEmptyPrefab("Assets/Resources/Prefabs/Items/Item Manager.prefab");
PrefabUtility.ReplacePrefab(Selection.activeGameObject, prefab);
AssetDatabase.Refresh();
I've split up the ItemList classes into multiple lists:
[Serializable]
public class ItemList:MonoBehaviour {
[SerializeField] private List<ItemEquipable> equipableItems = new List<ItemEquipable>();
[SerializeField] private List<ItemWeapon> weaponItems = new List<ItemWeapon>();
[SerializeField] private List<ItemPower> powerItems = new List<ItemPower>();
[SerializeField] private List<ItemSpecial> specialItems = new List<ItemSpecial>();
public List<ItemEquipable> EquipableItems { get { return equipableItems; } }
public List<ItemWeapon> WeaponItems { get { return weaponItems; } }
public List<ItemPower> PowerItems { get { return powerItems; } }
public List<ItemSpecial> SpecialItems { get { return specialItems; } }
}
And every item is serialized, as well as it's fields:
[Serializable]
public class Item {
public static Item item = new Item();
[SerializeField] private ItemType itemType;
[SerializeField] private string itemName;
[SerializeField] private string itemDescription;
}
The static item variable is used in the editor to prevent cluttering my editor script with hundreds of variables:
Item.item.Type = (Item.ItemType)EditorGUILayout.EnumPopup("Item Type", Item.item.Type);
To set these variables I've just used getters and setters for each field in the item classes.
This might not be the most efficient way of doing it, but it works.

Categories

Resources