I have a game developed with unity, this is the code of a button. It should take the public List of the script "BoardScript" and add a number to this list, but, for some reason it isn't working.
I have checked that the Button click is working (as you can see, in the code the debug.log yes prints), but clicking it is not adding the number to my list.
In the "BoardScript" I added some numbers just to try, and the value adds to the list successfully, so, I guess that the error is somewhere in this script, but I can't figure what can be wrong.
Can you please help me?
private Button B;
void Start()
{
B = GetComponent<Button>();
B.onClick.AddListener(Clicker);
}
void Clicker()
{
BoardScript boardScript = new BoardScript();
int Two = 2;
boardScript.UserList.Add(Two);
Debug.Log("Added);
}
// Update is called once
EDIT
I almost forgot to tell a detail. I have write Debug.Log(UserList.Count) and The value is 1, even if I added 1 several times as the button script suggests (Its the same script but with different object).
So, As Steve Said This is the BoardScript code, it is a little long.
private int[] PreList = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
private List<int> ButtonList = new List<int>();
public List<int> UserList = new List<int>();
private System.Random Rnd = new System.Random();
public List<int> EndList = new List<int>();
void Randomizer()
{
PreList = PreList.OrderBy(C => Rnd.Next()).ToArray();
foreach (var item in PreList)
{
Debug.Log(item.ToString());
if (item == 1)
{
OneMethod();
}
if (item == 2)
{
TwoMethod();
}
if (item == 3)
{
ThreeMethod();
}
if (item == 4)
{
FourMethod();
}
if (item == 5)
{
FiveMethod();
}
if (item == 6)
{
SixMethod();
}
if (item == 7)
{
SevenMethod();
}
if (item == 8)
{
EightMethod();
}
if (item == 9)
{
NineMethod();
}
}
EndList = PreList.ToList();
}
void OneMethod()
{
//yield return new WaitForSeconds(1);
ButtonList.Add(1);
}
void TwoMethod()
{
ButtonList.Add(2);
}
void ThreeMethod()
{
ButtonList.Add(3);
}
void FourMethod()
{
ButtonList.Add(4);
}
void FiveMethod()
{
ButtonList.Add(5);
}
void SixMethod()
{
ButtonList.Add(6);
}
void SevenMethod()
{
ButtonList.Add(7);
}
void EightMethod()
{
ButtonList.Add(8);
}
void NineMethod()
{
ButtonList.Add(9);
}
void Start ()
{
Randomizer();
string[] the_array = ButtonList.Select(i => i.ToString()).ToArray();
string OrderString = string.Join(", ", the_array);
GameObject.Find("Order").GetComponent<Text>().text = OrderString;
UserList.Add(1);
UserList.Add(5);
}
IEnumerator Waiter()
{
yield return new WaitForSeconds(10);
}
// Update is called once per frame
void Update()
{
string[] the_array = UserList.Select(i => i.ToString()).ToArray();
string OrderString = string.Join(", ", the_array);
Debug.Log(OrderString);
if (UserList.Count == 8)
{
if (UserList == ButtonList)
{
//Sound
BehaviourModel B = new BehaviourModel();
B.Counter++;
if (B.Counter < 10)
{
SceneManager.LoadScene(B.SceneArray[B.Counter]);
}
else if (B.Counter > 10)
{
SceneManager.LoadScene("MainMenuScene");
}
}
else if (UserList != ButtonList)
{
UserList.Clear();
Debug.Log("Fail");
}
}
}
Each time you click the button you create a new instance of BoardScript. You should store the boardScript variable as a variable in your class or separate component to ensure the data will persist.
You can do either create only one Instance, like:
private Button B;
BoardScript boardScript = new BoardScript();
then in your void Clicker() method:
add item to UserList.
Or:
You can create a static variable in your BoardScript class and check for null. If its null, then create a new instance else return an old instance.
The following code will help:
private static BoardScript _uniqueBoardScript;
private BoardScript()
{}
public static BoardScript GetInstance()
{
if(_uniqueBoardScript==null)
{
_uniqueBoardScript = new BoardScript();
}
return _uniqueBoardScript;
}
and from your void Clicker()
{
BoardScript boardScript = BoardScript.GetInstance();
int Two = 2;
boardScript.UserList.Add(Two);
Debug.Log("Added);
}
Related
I have this really weird bug where I cannot seem to delete an object from a list. I am using an Injector class to pass the same object(thus the same list) around into multiple forms. The Delete() function is just a generic delete, really nothing special. However in my unit test it keeps failing and I'm unsure why.
Injector class:
[Serializable]
public class InjectorClass
{
public OrderAdministration Administration { get; private set; }
public WareHouse WareHouse { get; private set; }
public InjectorClass()
{
Administration = new OrderAdministration(this);
WareHouse= new WareHouse();
}
}
Constructor of the WareHouse class:
public List<Part> Catalogus { get; private set; }
public List<Part> PartsInStock { get; private set; }
public WareHouse()
{
PartsInStock = new List<Part>();
AddStandardStockToCatalogus();
AddStockPartsToStock();
}
private void AddStandardStockToCatalogus()
{
Body body1 = new Body("Body7zk", 1, "Ebony", "Blue");
Body body2 = new Body("SuperXtrem368", 2, "Maple", "Red");
Neck neck1 = new Neck("Heavy-Slider", 3, "Juniper", true);
Neck neck2 = new Neck("SlickFingerBoard", 4, "Oak", false);
Fretboard fretboard1 = new Fretboard("PrettySlamFinger", 5, "Oak", false);
Fretboard fretboard2 = new Fretboard("GentleToucher", 6, "Ebony", true);
Pickups pickups1 = new Pickups("TubeScreamers", 7, Pickups.PickupType.P90);
Pickups pickups2 = new Pickups("BluesBrothers", 8, Pickups.PickupType.Humbucker);
Bridge bridge1 = new Bridge("MetalGearRipper", 9, false);
Bridge bridge2 = new Bridge("BridgeOfLove", 10, true);
Catalogus = new List<Part> { body1, body2, neck1, neck2, fretboard1, fretboard2, pickups1, pickups2, bridge1, bridge2};
}
private void AddStockPartsToStock()
{
foreach(Part p in Catalogus)
{
PartsInStock.Add(p);
}
}
The Delete() function in the same Warehouse class:
public int GetStock(Part neededPart)
{
if(neededPart == null)
{
throw new ArgumentNullException();
}
int numberInStock = 0;
foreach(Part p in PartsInStock)
{
if(p.Id == neededPart.Id)
{
numberInStock++;
}
}
return numberInStock;
}
public bool AddToStock(Part arrivedPart)
{
if(arrivedPart == null)
{
throw new ArgumentNullException();
}
if(FindByName(arrivedPart.Name).Name == arrivedPart.Name)
{
PartsInStock.Add(arrivedPart);
return true;
}
return false;
}
public bool RemovePart(Part usedPart)
{
if (GetStock(usedPart) >= 1)
{
PartsInStock.Remove(usedPart);
return true;
}
return false;
}
The unit test I run:
Neck neck1 = new Neck("Heavy-Slider", 3, "Juniper", true);
InjectorClass injector = new InjectorClass();
Assert.AreEqual(10, injector.WareHouse.PartsInStock.Count);
injector.WareHouse.RemovePart(neck1);
Assert.AreEqual(9, injector.WareHouse.PartsInStock.Count);
The output on both the assert functions is 10
Edit:
I have re-written my search and delete function to the following:
Search function:
public Part FindByNameStock(Part neededPart)
{
if (neededPart == null)
{
throw new ArgumentNullException();
}
foreach (Part p in PartsInStock)
{
if (p.Name == neededPart.Name)
{
return p;
}
}
return null;
}
Delete function:
public bool RemovePart(Part usedPart)
{
Part part = FindByNameStock(usedPart);
if (part != null)
{
PartsInStock.Remove(part);
return true;
}
return false;
}
The code now works and the unit test too.
This line PartsInStock.Remove(usedPart); will try to remove the following object
new Neck("Heavy-Slider", 3, "Juniper", true);
which is not in your list. The reason is that reference type equality is not based on the properties, but on the actual reference. Whenever you run new a new reference is created.
var neck1 = new Neck("Heavy-Slider", 3, "Juniper", true);
var neck2 = new Neck("Heavy-Slider", 3, "Juniper", true);
Console.WriteLine(neck1 == neck2); //This is false
Check the code here for an example: https://dotnetfiddle.net/7gAWID
Check here for the IEquatable implementation that will make your code work.
Two separate objects of Neck although having the same ID are different objects and hence the item is never removed.
Moreover, you can return the value of List.Remove as it also returns a bool if an item was actually removed. So if no item was removed, it returns false:
public bool RemovePart(Part usedPart)
=> GetStock(usedPart) >= 1 ?
PartsInStock.Remove(usedPart);
: false;
Use RemoveAll() to remove the item by ID. RemoveAll() returns an int representing the number of items removed:
public bool RemovePart(Part usedPart)
{
if (GetStock(usedPart) >= 1)
{
PartsInStock.RemoveAll(part => part.Id == usedPart.Id);
return true;
}
return false;
}
Also, since your RemovePart returns a bool. You can add a check to ensure if it was removed.
if (injector.WareHouse.RemovePart(neck1))
{
Assert.AreEqual(9, injector.WareHouse.PartsInStock.Count);
}
GetStock uses the Id of the part to find it, whereas PartsInStock.Remove tries to remove the part by reference - and the reference you have is different to the item in the collection you're trying to remove from.
public bool RemovePart(Part usedPart)
{
if (GetStock(usedPart) >= 1) // item is found here
{
PartsInStock.Remove(usedPart); // but usedPart is a different reference - nothing is removed
return true;
}
return false;
}
The main idea is to each member on team1 attack a random enemy on team2. The damage dealt is based on a spell casted at random from a Grimoire book.
My Code:
using System;
namespace simple_test
{
class Program
{
public class IceLance : Hechizo //hechizo == spell
{
public IceLance(uint d) : base(20)
{
danio = d; // danio == damage
return;
}
public override void Castear() // castear == cast
{
Console.WriteLine("Ice Lance");
}
protected uint danio = 5; // danio == damage
}
public abstract class Hechizo
{
protected Hechizo(uint c)
{
costo = c; // costo == cost
}
public abstract void Castear();
protected uint costo = 1;
public uint Costo
{
get { return costo; }
}
}
public class Personaje // personaje == character
{
public Personaje()
{ }
public Personaje(uint s)
{
salud = s;
}
public void RecibirDanio(uint d) // RecibirDanio == RecieveDamage
{
salud -= d; // salud = salud - d // salud == Health
}
public virtual void Ataque() // Ataque == Attack
{
Console.WriteLine("Ataque melee");
return;
}
public bool IsVivo() // IsVivo == IsAlive
{
return salud > 0;
}
protected uint salud = 100;
}
public class Humano : Personaje // Humano == Human
{
public Humano() : base()
{ }
public Humano(uint s, uint m) : base(s)
{
mana = m;
}
public void CastearGrimorio(int idx)
{
if ((grimorio == null) ||
(idx >= grimorio.Length) || (grimorio[idx] == null))
return;
uint c = grimorio[idx].Costo;
if (mana >= c)
{
mana -= c;
grimorio[idx].Castear();
}
}
public void AprenderHechizo(Hechizo h) // AprenderHechizo == LearnSpell
{
if (grimorio == null)
{
grimorio = new Hechizo[1];
}
else
{
Hechizo[] nuevoGrimorio = new Hechizo[grimorio.Length + 1];
for (uint i = 0; i < grimorio.Length; ++i)
{
nuevoGrimorio[i] = grimorio[i];
}
grimorio = nuevoGrimorio;
}
grimorio[grimorio.Length - 1] = h;
}
public override void Ataque()
{
if (grimorio == null)
Console.WriteLine("Sin mana :(");
else
CastearGrimorio(rnd.Next(0, grimorio.Length));//con esto lanza hechizos al azar
return;
}
private uint mana = 10;
private Hechizo[] grimorio;
private Random rnd = new Random();
}
static public bool TodosMuertos(Personaje[] team) // TodosMuertos == AllDead
{
for (int i = 0; i < team.Length; ++i)
{
if (team[i].IsVivo())
{
return false;
}
}
return true;
}
static void Main(string[] args)
{
Personaje[] team1 = new Personaje[41];
for (int i = 0; i < 3; ++i)
{
Humano mage = new Humano(80, 100);
mage.AprenderHechizo(new IceLance(20));
mage.AprenderHechizo(new IceLance(10));
mage.AprenderHechizo(new IceLance(0));
team1[i] = mage;
}
Personaje[] team2 = new Personaje[41];
for (int i = 0; i < 3; ++i)
{
Humano mage = new Humano(80, 100);
mage.AprenderHechizo(new IceLance(20));
mage.AprenderHechizo(new IceLance(10));
mage.AprenderHechizo(new IceLance(0));
team2[i] = mage;
}
while (!TodosMuertos(team1) && !TodosMuertos(team2)) // turnos
{
Console.WriteLine("team1");
for (int i = 0; i < team1.Length; ++i)
{
if (team1[i].IsVivo())
{
team1[i].Ataque();
// Here should go the RecieveDamage funtion
}
Console.ReadKey();
}
}
}
}
}
This one is a simplified version of the code, i.e. it only has one class and one spell.
I'm not sure how to write the part of how to select a member of the opposite team and in base of the spell casted receiveDamage according to its damage.
PS: I added some references to the spanish language used in the code
You can use the Random class to get a random number between 0 and the number of alive mages on the other team, and use that number to attack. Modify your attack function to take a target mage as a parameter and get them to take damage from there.
using System.Linq; // Add to top of page to use linq functions - .Where()
....
public class Humano : Personaje // Humano == Human
{
...
public override void Ataque(Personaje personaje)
{
if (grimorio == null)
Console.WriteLine("Sin mana :(");
else
{
// Modify CastearGrimoiro to return spell damage. Use person parameter to inflict damage on that person
uint damage = CastearGrimorio(rnd.Next(0, grimorio.Length));//con esto lanza hechizos al azar
personaje.RecibirDanio(damage);
}
}
...
static Random _random = new Random();
static void TakeTeamTurn(Personaje[] team, Personaje[] enemyTeam)
{
var aliveMages = team.Where(m => m.IsVivo()).ToList();
foreach(var mage in aliveMages)
{
// Get team to attack
var attackableMages = enemyTeam.Where(m => m.IsVivo()).ToList(); // Get a list of alive mages on the other team
var mageAttackIndex = _random.Next(attackableMages.Count); // Get a random number between 0 and the number of attackable mages
// (Not written here) Modify your Ataque method to take a mage parameter.
// In the Ataque method or some other method you can use this parameter to do damage to the target mage
var mageToAttack = attackableMages[mageAttackIndex];
mage.Ataque(mageToAttack);
}
}
static void Main(string[] args)
{
...
while (!TodosMuertos(team1) && !TodosMuertos(team2)) // turnos
{
Console.WriteLine("team1");
TakeTeamTurn(team1, team2);
Console.WriteLine("team2");
TakeTeamTurn(team2, team1);
Console.ReadKey();
}
....
Working example here - https://pastebin.com/kSregt24
First of all, here's my script:
using UnityEngine;
using System.Collections;
using Steamworks;
public class Achievements : MonoBehaviour {
public static int currentScore=0;
public static int score300 = 300;
public static int score1000 = 1000;
public static int score3600 = 3600;
public static int score18000 = 18000;
public static int score72000 = 72000;
public static int score180000 = 180000;
void Start() {
if(SteamManager.Initialized) {
string name = SteamFriends.GetPersonaName();
Steamworks.SteamUserStats.SetAchievement("NEW_ACHIEVEMENT_1_0");
Steamworks.SteamUserStats.StoreStats();
Debug.Log(name);
}
}
void Update()
{
currentScore = PlayerPrefs.GetInt("highscore");
if (currentScore == score300 && SteamManager.Initialized){
Steamworks.SteamUserStats.SetAchievement("NEW_ACHIEVEMENT_5_0");
Steamworks.SteamUserStats.StoreStats();
}
if (currentScore == score1000 && SteamManager.Initialized) {
Steamworks.SteamUserStats.SetAchievement("NEW_ACHIEVEMENT_6_0");
Steamworks.SteamUserStats.StoreStats();
}
if (currentScore == score3600 && SteamManager.Initialized) {
Steamworks.SteamUserStats.SetAchievement("NEW_ACHIEVEMENT_7_0");
Steamworks.SteamUserStats.StoreStats();
}
if (currentScore == score18000 && SteamManager.Initialized) {
Steamworks.SteamUserStats.SetAchievement("NEW_ACHIEVEMENT_8_0");
Steamworks.SteamUserStats.StoreStats();
}
}
}
As you can see, I have public integers that hold variety of numbers. I am also using current steamworks.net, and I'm trying to see if I can match both "highscore" (which is already set up and working properly) with scoreXXX. If that happens, I want script to drop an achievement.
Am I executing if(x=x) function wrong? Can someone please help?
The problem is you arent checking if the score is greater than the score benchmarks, only that its equal.
You could simplify your code a bit by putting these values into a Dictionary<int, string>:
private static Dictionary<int, string> highScoreDictionary = new Dictionary<int, string>()
{
{ 300, "NEW_ACHIEVEMENT_5_0" },
{ 1000, "NEW_ACHIEVEMENT_6_0" },
{ 3600, "NEW_ACHIEVEMENT_7_0" },
{ 18000, "NEW_ACHIEVEMENT_8_0" },
{ 72000, "NEW_ACHIEVEMENT_9_0" },
{ 180000, "NEW_ACHIEVEMENT_10_0" }
};
void Update()
{
currentScore = PlayerPrefs.GetInt("highscore");
if(SteamManager.Initialized)
{
//Order by high score, descending
foreach(var score in highScoreDictionary.OrderByDescending(x => x.Key))
{
//If the score is greater than or equal to the benchmark
//Then add the achievement
if(currentScore >= score.Key)
{
Steamworks.SteamUserStats.SetAchievement(score.Value);
Steamworks.SteamUserStats.StoreStats();
break;
}
}
}
}
I made a fiddle here. Its obviously modified a bit since I dont have access to Unity libraries there, but you can see the logic in action.
I'm developing an application in ASP.NET with C# and I'm trying to figure out the best way to implement a logic statement that will stop the system from allowing another reservation to be taken if the trailer for canoes and kayaks is full. The issue is the trailer will hold canoes and kayaks, but there's a lot of different combinations.
There are 5 "rows" on the trailer that count upwards vertically, and 2 "columns" that dissect the 5 rows in the middle. I will draw you a diagram to show you what it looks like, and what boats can go where. "C" will stand for Canoe and "K" will stand for Kayak. The trailer looks like this:
C only|C only }
______|______ } BOAT TRAILER
1C\2K|1C\2K }
______|______ }
1C\2K|1C\2K }
______|______ }
1C\2K|1C\2K }
______|______ }
C only| C only }
______|______ }
So my question is, what's the best option as far as coding and logic is concerned to not take any more "reservations" when the trailer is full? This application will be a .aspx form that will do an insert command to SQL server taking customer information.
public enum BoatType : int
{
Kayak = 1,
Canoe = 2
}
public class BoatReservation
{
public int ReservationID { get; set; }
public BoatType ReservationBoatType { get; set; }
}
public class BoatTrailer
{
public List<BoatReservation> CanoeSlots = new List<BoatReservation>();
public List<BoatReservation> RegularSlots = new List<BoatReservation>();
public BoatTrailer()
{
}
public bool AddBoat(BoatReservation b)
{
bool boatAdded = false;
switch (b.ReservationBoatType)
{
case BoatType.Canoe:
if (CanoeSlots.Count() < 4)
{
CanoeSlots.Add(b);
boatAdded = true;
}
else
{
var reg = RegularSlots.Sum(x => Convert.ToInt16(x.ReservationBoatType));
if (reg <= 10)
{
RegularSlots.Add(b);
boatAdded = true;
}
}
break;
case BoatType.Kayak:
{
var reg = RegularSlots.Sum(x => Convert.ToInt16(x.ReservationBoatType));
if (reg <= 11)
{
RegularSlots.Add(b);
boatAdded = true;
}
}
break;
}
return boatAdded;
}
public void RemoveBoat(BoatReservation b)
{
switch (b.ReservationBoatType)
{
case BoatType.Kayak:
if (RegularSlots.Contains(b))
{
RegularSlots.Remove(b);
}
break;
case BoatType.Canoe:
if (RegularSlots.Contains(b))
{
RegularSlots.Remove(b);
}
else
{
if (CanoeSlots.Contains(b))
{
CanoeSlots.Remove(b);
if (RegularSlots.Where(fb => fb.ReservationBoatType == BoatType.Canoe).Count() > 0)
{
//Move Reservation From Regular to Canoe Only With Opening
BoatReservation mv = RegularSlots.FindLast(fb => fb.ReservationBoatType == BoatType.Canoe);
RegularSlots.Remove(mv);
CanoeSlots.Add(mv);
}
}
}
break;
}
}
public string AvailableSlots()
{
string Output = string.Empty;
int AvailableCanoeCnt = (4 - CanoeSlots.Count()) + ((12 - RegularSlots.Count()) / 2);
int AvailableKayakCnt = (12 - RegularSlots.Count());
Output = string.Format("Canoe Slots Left: {0} Kayak Slots Left {1} ", AvailableCanoeCnt, AvailableKayakCnt);
return Output;
}
}
Quick class that handles reservations (both adding and deleting) of canoes/kayaks to fit a trailer.
Not the best question for this site but I will provide a pseudo structure for this.
Trailer Object
JustCanoes int
CanoeKayakBlend int
When reserving...
If the reservation is for a canoe, and the JustCanoes value is < 4, then increase JustCanoes by 1
If JustCanoes is >= 4
If CanoeKayakBlend <= 10
increase CanoeKayakBlend by 2
else
Sorry no reservation available
If the reservation is for a kayak
If CanoeKayakBlend <= 11
increase CanoeKayakBlend by 1
else
Sorry no reservation available
A very quick and simplistic implementation: Here's the Compartment class
class Compartment
{
private readonly int _maxCanoe;
private readonly int _maxKayak;
private int _currentCanoe;
private int _currentKayak;
private readonly int _id;
private bool _fullCanoe;
private bool _fullKayak;
public Compartment(int id, int maxC, int maxK)
{
_id = id;
_maxCanoe = maxC;
_maxKayak = maxK;
_currentCanoe = _currentKayak = 0;
UpdateCapacityStatus();
}
private void UpdateCapacityStatus()
{
_fullCanoe = _maxCanoe == _currentCanoe;
_fullKayak = _maxKayak == _currentKayak;
}
private string Status
{
get { return IsFull() ? "FULL" : "Space available"; }
}
public bool IsFull()
{
return _fullKayak && _fullCanoe;
}
public void AddCanoe()
{
_fullKayak = true; // disable adding kayak
_currentCanoe = _currentCanoe + 1;
_fullCanoe = _maxCanoe == _currentCanoe; //update canoe status
}
public void AddKayak()
{
_fullCanoe = true; //disable adding canoe
_currentKayak = _currentKayak + 1;
_fullKayak = _maxKayak == _currentKayak; //update kayak status
}
public override string ToString()
{
return string.Format("Id: {5}, Status: {0}, with {1} of {2} canoes or {3} of {4} kayaks", Status, _currentCanoe, _maxCanoe, _currentKayak, _maxKayak, _id);
}
public bool CanAddCanoe()
{
return !_fullCanoe;
}
public bool CanAddKayak()
{
return !_fullKayak;
}
}
And here's the driver console app to test, to use it you should refactor it of course.
`class Program
{
static void Main(string[] args)
{
var trailer = new List
{
new Compartment(1, 1, 0),
new Compartment(2, 1, 0),
new Compartment(3, 1, 2),
new Compartment(4, 1, 2),
new Compartment(5, 1, 2),
new Compartment(6, 1, 2),
new Compartment(7, 1, 2),
new Compartment(8, 1, 2),
};
foreach (var compartment in trailer)
{
Console.WriteLine(compartment.ToString());
}
Console.WriteLine("Press c for canoe or k for kayak");
var keepGoing = true;
while (keepGoing)
{
var input = Console.Read();
if (input == 99 || input == 107) //99 c, 107 k
{
if (trailer.All(c => c.IsFull()))
{
keepGoing = false;
}
else
{
if (input == 99)
{
if(!trailer.Any(t=>t.CanAddCanoe()))
{
Console.WriteLine("Cannot add a canoe!!!!");
}
else
{
var firstAvailable = trailer.First(c => c.CanAddCanoe());
firstAvailable.AddCanoe();
}
}
else if (input == 107)
{
if (!trailer.Any(t => t.CanAddKayak()))
{
Console.WriteLine("Cannot add a kayak!!!!");
}
else
{
var firstAvailable = trailer.First(c => c.CanAddKayak());
firstAvailable.AddKayak();
}
}
else
{
Console.WriteLine("Press c for canoe or k for kayak");
}
}
foreach (var compartment in trailer)
{
Console.WriteLine(compartment.ToString());
}
}
}
Console.ReadKey();
}
}`
Like said above how would I, I have some code using linq and except and any(). Currently I use items(a class), to be identified and such, but this is causing problems, so I would like them to be identified by strings instead, but im not sure how. The two functions with the code are: ContainsAllItems, and the other one is in the craft function.
Thanks!
EDIT; To make more clear just in case, right now it checks the items in two lists, instead of that what im asking is how to make it that it checks the itemname of the items in the lists instead, but still make it have the same effect, so it would destroy items and check items and make sure when destroying that not more than needed are destroyed.
If you would not want to look through the code here are the two lines:
public static bool ContainsAllItems(List<Item> a, List<Item> b)
{
return !b.Except(a).Any();
}
and
List<Item> list = new List<Item>();
list = InventoryItems.Except(Recipe.InputItem).ToList();
InventoryItems = list;
Code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class PlayerInventory : MonoBehaviour {
public int MaxInventory = 26;
public List<Item> InventoryItems = new List<Item>();
void OnGUI(){
if (GUILayout.Button ("+5 Wood")) {
AddItem(ItemConstructors.Wood());
AddItem(ItemConstructors.Wood());
AddItem(ItemConstructors.Wood());
AddItem(ItemConstructors.Wood());
AddItem(ItemConstructors.Wood());
}
if (GUILayout.Button ("Craft Wall")) {
Craft(CraftingRecipes.WoodenWall());
}
}
public void AddItem(Item _item){
if (InventoryItems.Count < MaxInventory) {
InventoryItems.Add(_item);
//SaveItems();
}
}
public void RemoveItem(Item _item){
InventoryItems.Remove (_item);
}
public void UseItem(Item _item){
if (_item.ItemType == "Food") {
ConsumeItem(_item);
}
SaveItems();
}
public void ConsumeItem(Item _item){
if (_item.ItemDur > 1) {
_item.ItemDur--;
}
else if(_item.ItemDur <= 1){
RemoveItem(_item);
}
}
public void SaveItems(){
for (int i = 0; i<MaxInventory; i++) {
PlayerPrefs.SetString("Itemn"+i,InventoryItems[i].ItemName);
PlayerPrefs.SetString("Itemt"+i,InventoryItems[i].ItemType);
PlayerPrefs.SetInt("Itemv"+i,InventoryItems[i].ItemValue);
PlayerPrefs.SetInt("Itemd"+i,InventoryItems[i].ItemDur);
}
//LoadItems ();
}
public void LoadItems(){
InventoryItems.Clear();
for (int i = 0; i<MaxInventory; i++) {
Item it = new Item();
it.ItemName = PlayerPrefs.GetString("Itemn"+i);
it.ItemType = PlayerPrefs.GetString("Itemt"+i);
it.ItemValue = PlayerPrefs.GetInt("Itemv"+i);
it.ItemDur = PlayerPrefs.GetInt("Itemd"+i);
if(it.ItemName.Length <= 2 && it.ItemType.Length <= 2){
}
else{
InventoryItems.Add(it);
}
}
}
public void Craft(CraftingItem Recipe){
bool canCraft = ContainsAllItems (InventoryItems,Recipe.InputItem);
if(canCraft){
if(InventoryItems.Count < MaxInventory){
List<Item> list = new List<Item>();
list = InventoryItems.Except(Recipe.InputItem).ToList();
InventoryItems = list;
AddItem(Recipe.OutputItem);
}
else{
Debug.Log("Not enough space!");
}
}
else{
Debug.Log("Invalid Items.");
}
}
public static bool ContainsAllItems(List<Item> a, List<Item> b)
{
return !b.Except(a).Any();
}
}