Check a value exist in array in unity 3d - c#

I have two script.
Script1
Script2
In Script1 i declared a arraylist it contains value 2, 4, 6, etc...
public static ArrayList aArray= new ArrayList();
function update(){
if(bool1)
{
aArray.Add(i);
}
}
I have to check a value 5 exist in arraylist from Script2.
if value exists i have to get its key.
How to get it?

First, i would recommand using a generic List<T> instead of the non-generic ArrayList, which enables you to specify the type of objects that go into that list (for better type safety).
Also, declaring a variable readonly prevents you from accidently overwriting it, which is often the case with Lists (after all, you can always just Clear them):
public static readonly List<int> items = new List<int>();
Now to answer your actual question, if you want to check if a value exists in the list, you can use the method Contains.
To check if the value does not exist, just put an ! in front of the expression:
if (!Script1.items.Contains(i)) {
// This will only execute if the list does not contain i.
items.Add(i);
}

Try using Contains. This code will detect if you have already the value in the ArrayList and will stop code from adding it a second time.
public static ArrayList aArray= new ArrayList();
function update()
{
if(aArray.Contains(i)==false)
{
aArray.Add(i);
}
}
If you want to remove a value it is just as easy as aArray.Remove(i)

if I understood correctly, Script1 is in your camera, and Script2 is in a Character. For the sake of this example we'll call them MainCamera and Character respectively.
Now, unless I understood wrong, you're trying to access an Array in Script1 from Script2. While the other answers are very much correct, unity3D has a bit of a workaround needed to access it.
Anyway, within Script2 use this:
if(GameObject.Find("MainCamera").GetComponent<Script1>().aArray.Contains(5))
{
//Do your code here
}

Related

C# getting array with a string name?

So here's a hypothetical. From someone fairly new to the whole C# and Unity thing:
Suppose for a moment that I have a series of string[] arrays. All of which have similar naming convention. For example:
public string[] UndeadEntities =
{
// stuff
};
public string[] DemonEntities =
{
// stuff
};
Now suppose I want to call one of them at random, I have another list that contains the names of all of those arrays and I return it at random.
My problem is that I grab the name from the array and it's a string, not something I can use. So my question is this:
is there any way for me to use this string and use it to call the above mentioned arrays.
Something like this is what I'm up to but unsure where to go from here and I really would like to avoid making a massive series of If Else statements just for that.
public string[] EnemiesType = { // list of all the other arrays }
public string enemiesTypeGeneratedArrayName = "";
public void GenerateEncounterGroup()
{
enemiesTypeGeneratedArrayName = EnemiesType[Random.Range(0, 12)];
}
Can I nest arrays inside of other arrays? Is there another alternative?
I'm not sure if it is possible at all but if it is, I'll take any pointers as to where to go from there. Thanks.
There are several solutions to your specific problem, an easy one is using Dictionaries:
A Dictionary is a data structure wher you have a key (usually a string) and a value (whatever type you may want to store).
What you can do is at start, initialized a Dictionary were each key is your enemy type, and the value it store is your array, something like:
Dictionary<string, string[]> enemyArrays= new Dictionary<string, string[]>();
.
void Start()
{
enemyArrays["typeA"] = myArrayA;
enemyArrays["typeB"] = myArrayB;
}
Then when you need to get that array, just:
enemiesTypeGeneratedArrayName = EnemiesType[Random.Range(0, 12)];
string[] myRandomArray =enemyArrays[enemiesTypeGeneratedArrayName];
string randomEnemy = myRandomArray[index];
Here you can read more about Dictionary class if you want.
There are other ways to do it, but I think this one is pretty easy to implement in the code you already made, and Dicionaries are cool haha.
I hope is clear:)

Code is modifying the wrong variable... why?

I have a strange thing where some code I am doing is modifying both the copy and the original List.. I have boiled the problem down as much as I can to only show the error in a single file. Though my real world example us a lot more complex.. but at the root of it all this is the problem.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestingRandomShit
{
class Program
{
private static string rawInput;
private static List<string> rawList;
private static List<string> modifiedList;
static void Main(string[] args)
{
rawInput = "this is a listing of cats";
rawList = new List<string>();
rawList.Add("this");
rawList.Add("is");
rawList.Add("a");
rawList.Add("listing");
rawList.Add("of");
rawList.Add("cats");
PrintAll();
modifiedList = ModIt(rawList);
Console.WriteLine("\n\n**** Mod List Code has been run **** \n\n");
PrintAll();
}
public static List<string> ModIt(List<string> wordlist)
{
List<string> huh = new List<string>();
huh = wordlist;
for (int i = 0; i < huh.Count; i++)
{
huh[i] = "wtf?";
}
return huh;
}
//****************************************************************************************************************
//Below is just a print function.. all the action is above this line
public static void PrintAll()
{
Console.WriteLine(": Raw Input :");
Console.WriteLine(rawInput);
if (rawList != null)
{
Console.WriteLine("\n: Original List :");
foreach (string line in rawList)
{
Console.WriteLine(line);
}
}
if (modifiedList != null)
{
Console.WriteLine("\n: Modified List :");
foreach (string wtf in modifiedList)
{
Console.WriteLine(wtf);
}
Console.ReadKey();
}
}
}
}
Basically, I have three variables.... a string and two List. The original code dose some tokenisation on the string but for this demo I simple use the List.Add() to fake it to make it simple to read.
So I now have a string and a List with a single word in each element.
This is the confusing part that I do not understand.. I know it has something to do with references but I can not work out how to fit it.
There is a method I have called ModIt()... it simple takes in a List then makes a completely new List called huh, copies the original list over the new list and then changes every line in huh to "wtf?".
Now as I understand it.. I should end up with 3 variables...
1) a string
2) a List with a different word in each element
3) a List of the same length as the other with each element being "wtf?"
But, what happens is that is I try to print out both List they BOTH have every element set to "WTF?".... so yeah.. wtf man? I am super confused. I mean in the ModIt I even build a entire new string rather than modding the one being passes but it doesn't seem to effect anything.
This is the output...
: Raw Input : this is a listing of cats
: Original List : this is a listing of cats
**** Mod List Code has been run ****
: Raw Input : this is a listing of cats
: Original List : wtf? wtf? wtf? wtf? wtf? wtf?
: Modified List : wtf? wtf? wtf? wtf? wtf? wtf?
huh = wordlist; doesn't copy the items of wordlist into a new list, it copies the reference to the same object occupied by wordlist (i.e. huh and wordlist then point at the same object in memory).
If you want a copy, the simplest way to produce one is using LINQ:
List<string> huh = wordlist.ToList();
Note that this will be a "shallow copy". If your list stores reference objects, both the old and new lists will store references to the same objects.
See here for more reading on value vs reference types, and then here if you need a deep copy.
Since all you're doing is replacing the value at an index of the list, I imagine a shallow copy is fine.
John's already commented on the faulting code:
List<string> huh = new List<string>();
huh = wordlist;
Here you make a new list, then throw it away and attach your reference huh to your old list, so both huh and wordlist refer to the same thing..
I just wanted to point out the non LINQ way of copying a list:
List<string> huh = new List<string>(wordlist);
Pass the old list into the new list's constructor; list has a constructor that takes a collection of objects to store in the new list
You now have two lists, and initially they both refer to the same strings, but because strings cannot be altered, if you start to change the strings inside the list (rather than just shufffling or removing them from the list) new ones will be created
If a worthy point though; you'll have 2 lists pointing to the same objects so if you have, in the future, the same scenario with objects that can be changed and you change the object in one list it will also change in the other list:
//imagine the list stores people, the age of the first
//person in the list is 27, and we increment it
List1[0].PersonAge++;
//list2 is a different list but refers to the same people objects
//this will print 28
Console.Out.WriteLine(list2[0].PersonAge);
That's what we mean by a shallow copy
Your problem comes from the fact that in C# we have reference types and value types.
Value types can be assigned values by the direct assignment operator (=), but for reference types it is different. Reference types do not store the actual data itself, they store a location in memory where the data is held. Like pointers, if you come from the C world.
Have a look into IClonable. Also read Parameter passing by Jon Skeet, it gives a good description of value and reference types.

Why do I get an error when List<object>.Add(int)

I have an array of List types:
List<object>[] vector = new List<object>[3];
The first List contains strings:
// Get word lists together, remove duplicates
var words = tableA.ToList().Union(tableB.ToList());
// Sort words
words = words.OrderBy(s => s, StringComparer.CurrentCultureIgnoreCase);
// Add words to the vector first slot
vector[0] = words.ToList<object>();
Now, I want to add ints to the second and third lists, but I get an error here:
vector[1].Add(tableA.GetValue(keyword));
vector[2].Add(tableB.GetValue(keyword));
GetValue() returns an int. But when I add these ints to the vector Lists it throws error:
ERROR Caught: Object reference not set to an instance of an object.
How should I add the ints to the List? Or is there some other data structure I should use instead for the vector? I feel there is some trivial cast I'm missing but I haven't been able find a solution.
I'm not an expert in C#, but i think i understand.
When you write :
List<object> vector = new List<object>[3];
you create a table of List with a size of 3.
You can put something into each slot of this array, but each "slot" still refers to no instance after this first line of code.
When you write
vector[0] = words.ToList<object>();
You put somehting into the first slot of vector list. But [1] and [2] are still empty. And
vector[1]
refers to a reference not set to an instance of an object. In short terms, it refers to nothing.
You must initialize each vector index value before add value. Thanks
When writing var a = new List<object> you´re only declaring that a is a list holding some (in your case three) items. However you don´t determine what stands in those three elements. You´d have to out some values into every single item, before you can anything with it (e.g. call any method).
You´re allready putting a list into the first item, however the elements on index one and two remain null causing a NullReferenceException when calling a method like the following:
vector[1].Add(...);
So you should initialize the value at index oe and two before:
vector[1] = new List<int>();
vector[2] = new List<int>();
But still you can´t do much with the list, because it is of type object, so you´d have to cast every element to the actual type:
((List<int>)vector[1]).Add(myInt);
Anyway I doubt storing three completely different lists within one single list alltogether is a good idea. Maybe you should define a class with the three lists as members instead:
class MyClass
{
public List<string> Words { get; set; }
public List<int> NumbersA { get; set; }
public List<int> NumbersB { get; set; }
}

Can I GET and SET an array in C#?

HOMEWORK QUESTION:
I need to create a simple trivia game that reads from a CSV file. My data for a particular question is structured as follows: "Question;AnswerA;AnswerB;AnswerC;AnswerD;CorrectAnswerLetter".
We're using a series of getters and setters to hold all the relevant data for a single question object, and I'm running into a problem with the array I've created to hold the four answers.
In my constructor, I'm using this code--which I believe instantiates the Answer array in question:
class TriviaQuestionUnit
{
...
const int NUM_ANSWERS = 4;
string[] m_Answers = new String[NUM_ANSWERS];
public string[] Answer
{
get { return m_Answers[]; }
set { m_Answers = value[];
}
...
// Answer array
public string[] GETAnswer(int index)
{
return m_Questions[index].Answer;
}
...
}
I'm accessing the getter and setter from my TriviaQuestionBank method, which includes this code:
...
const int NUM_QUESTIONS = 15;
TriviaQuestionUnit[] m_Questions = new TriviaQuestionUnit[NUM_QUESTIONS];
...
// Answer array
public string[] GETAnswer(int index)
{
return m_Questions[index].Answer;
}
...
I'm using using StreamReader to read a line of input from my file
...
char delim = ';';
String[] inputValues = inputText.Split(delim);
...
parses the input in an array from which I create the question data. For my four answers, index 1 through 4 in the inputValues array, I populate this question's array with four answers.
...
for (int i = 0; i < NUM_ANSWERS; i++)
{
m_Questions[questionCounter].Answer[i] = inputValues[i + 1];
}
...
I'm getting errors of Syntax code, value expected on the getters/setters in my constructor, and if I change the variable to m_Answers[NUM_QUESTIONS] I get an error that I can't implicitly convert string to String[].
Hopefully I've posted enough code for someone to help point me in the right direction. I feel like I'm missing something obvious, but I just cannot make this work.
Your code has some errors that will cause compilation errors, so my first lesson for you is going to be: listen to the compiler. Some of the errors might seem a bit hard to understand sometimes, but I can ensure you that a lot of other people have had the same problems before; googling a compiler error often gives you examples from other people that are similar to your issue.
You say "In my constructor", but the problem is that your code does not have a constructor. You do however initialize fields and properties on your class and surely enough, the compiler will create a default constructor for you, but you have not defined one yourself. I am not saying that your code does not work because you do not have a constructor, but you might be using the wrong terms.
The first problem is in your first code snippet inside TriviaQuestionUnit. Your first two lines are working correctly, you are creating a constant integer with the value 4 that you use to determine how large your array is going to be and then you initialize the array with that given number.
When you do new string[NUM_ANSWERS] this will create an array, with default (empty) values.
The first problem that arises in your code is the getters and setters. The property expects you to return an array of strings which the method signature in fact is telling us:
public string[] Answer
However, looking at the getter and setter, what is it that you return?
m_Answers is a "reference" to your array, hence that whenever you write m_Answers you are referring to that array. So what happens when we add the square brackets?
Adding [] after the variable name of an array indicates that we want to retrieve a value from within the array. This is called the indexer, we supply it with an index of where we want to retrieve the value from within the array (first value starts at index 0). However, you don't supply it with a value? So what is returned?
Listen to the compiler!
Indexer has 1 parameter(s) but is invoked with (0) argument(s)
What does this tell you? It tells you that it doesn't expect the empty [] but it would expect you to supply the indexer with a number, for instance 0 like this: [0]. The problem with doing that here though, is that this would be a miss-match to the method signature.
So what is it that we want?
We simply want to return the array that we created, so just remove [] and return m_Answers directly like this:
public string[] Answer
{
get { return m_Answers; }
set { m_Answers = value; }
}
Note that you were also missing a curly bracket at the end if the set.
When fixing this, there might be more issues in your code, but trust the compiler and try to listen to it!

Alternate name for object instances stored in array, C#

I have 2 object instances of same type. (To be precise this is Unity3D's AudioSource) I need to apply some action like initializing, destroying, etc to both, so I think storing them in an array would be a good idea so I can iterate.
AudioSource[] audioSources = new AudioSource[2];
With this I can foreach on the array and write initializing code and other common tasks only once.
But these two instances serves different purpose, say, the first is an AudioSource for BGM and the second is for SFX. This way the code will be more readable and I can still iterate over two instances by using the array.
So I think I should give an alternate names for each instance like bgmSource and sfxSource. I'd like to ask that is this the correct approach?
AudioSource bgmSource = audioSources[0];
AudioSource sfxSource = audioSources[1];
Another solution is using a Dictionary, its not very suitable for such small arrays
but it can help you distinct between objects without using second variable to store reference
to the one in the array.
For example:
Dictionary< string, AudioSource > audioSources;
audioSources = new Dictionary<string, AudioSource>
{
"BGM_SOURCE", new AudioSource(),
"SFX_SOURCE", new AudioSource()
};
Then you can also use enum for keeping track of dictionary keys instead of using string/constant values:
// Enum declaration
enum AudioSourceNames
{
BGM_SOURCE,
SFX_SOURCE
}
// Called before first update
public void Start()
{
// Dictionary declaration
Dictionary< int, AudioSource > audioSources;
audioSources = new Dictionary< int, AudioSource >
{
( int )BGM_SOURCE, new AudioSource(),
( int )SFX_SOURCE, new AudioSource()
};
// Accessing the dictionary
audioSources[ ( int )AudioSourceNames.BGM_SOURCE ].Play();
}
BTW: You can use the enumarator technique with array, this way you won't have to remember each AudioSource index in the array
From my point of view your solution seem good.
initializing code and other common tasks only once
The code for these things is hopefully in AudioSource, isn't it?
Well, it's legal. It's just a matter of preference/design. I would say that you could put them in a Dictionary of some sort. So you can properly label them through a key. That way you won't need to remember that [0] is bgmSource and [1] is sfxSource.

Categories

Resources