Unity want to get gameobjects from another array - c#

I have an array that gets all the gameobjects with the enemyMelee tag and i want to put the ones that have the idEnemy equal to the idDestination in another array.
How can i do this?
The maybeBlobsEnemy is the array that has all of them and blobsEnemy is the array that i want with only the condition above
Here is my code
void Update()
{
maybeBlobsEnemy = GameObject.FindGameObjectsWithTag("blobMelee");
for (int i = 0; i < maybeBlobsEnemy.Length; i++)
{
if (maybeBlobsEnemy[i].GetComponent<BlobBehavior>().idBlob == idDestination)
{
blobsEnemy[i] = maybeBlobsEnemy[i];
}
}
Thank you for you time

Related

Check for numbers as string in two gameObjects

I have a list of GameObjects that have names like
cube 1
cube 2
cube 3
Now I have another list of GameObjects that also have names like
sphere 4
sphere 2
sphere 8
Now I am comparing these two lists, I want the statement to be true if the numbers match. That is, if cube "2" == sphere "2", how do I do this? Also the Count of both lists remain equal.
public List<GameObject> cube = new List<GameObject>();
public List<GameObject> sphere = new List<GameObject>();
void Start(){
for(int i=0; i<cube.Count; i++){
//Check if the string in their names for numbers match
}
}
void Start(){
// step 1: store indices of cubes in dictionary
Dictionary<int, int> cubeIdToIndex = new Dictionary<int, int>();
for (int cubeIndex = 0; cubeIndex < cube.Count; cubeIndex++) {
string name = cube[cubeIndex].name;
int id = int.Parse(name.Substring(name.LastIndexOf(' ')));
cubeIdToIndex[id] = cubeIndex;
}
// step 2: check spheres
for (int sphereIndex = 0; sphereIndex < sphere.Count; sphereIndex++) {
string name = sphere[sphereIndex].name;
int id = int.Parse(name.Substring(name.LastIndexOf(' ')));
if(cubeIdToIndex.TryGetValue(id, out int cubeIndex)) {
// here cube[cubeIndex] matches sphere[sphereIndex]
}
}
}
There are more efficient ways to do this, but IMHO this one is a good tradeoff between performance and understandability.
However you should think about reorganizing your data structure, because matching based on naming convention is inefficient and error prone.

Expensive GetComponent<CanvasGroup>() call, unsure how to cache

I am getting a performance warning from my IDE that the GetComponent() call is expensive, especially since I am calling MoveCards() in Update(). I understand why it's expensive and usually know how to fix with caching in Awake() but since it's prefixed with cards[i], I am unsure how to go about it.
private void MoveCards()
{
// This loop moves the cards.
for (var i = 0; i < cards.Length; i++)
{
cards[i].localPosition = Vector3.Lerp(cards[i].localPosition, cardPositions[i + cardArrayOffset],
Time.deltaTime * cardMoveSpeed);
if (!(Mathf.Abs(cards[i].localPosition.x - cardPositions[i + cardArrayOffset].x) < 0.01f)) continue;
cards[i].localPosition = cardPositions[i + cardArrayOffset];
// This disables interaction with cards that are not on top of the stack.
cards[i].gameObject.GetComponent<CanvasGroup>().interactable = cards[i].localPosition.x == 0;
}
}
What I would do is make the card GameObject have it’s own MonoBehaviour to store a reference to those components. Then, change the cards collection to store a reference to the card MonoBehaviour.
You would store cards[] as a CanvasGroup instead of a GameObject.
You would declare it like this in Awake():
GameObject[] cardObjects = new GameObject[10];
CanvasGroup[] cards = new CanvasGroup[cardObjects.Length];
for (int i = 0; i < cardObjects.Length; i++)
{
cards[i] = cardObjects[i].GetComponent<CanvasGroup>();
}
We loop through all of the card objects, and assign that component to a certain object in an array.
In your function you showed in the question, you would change it to this:
private void MoveCards()
{
for (int i = 0; i < cardObjects.Length; i++)
{
cardObjects[i].transform.localPosition = Vector3.Lerp(cardObjects[i].transform.localPosition, cardPositions[i + cardArrayOffset], Time.deltaTime * cardMoveSpeed);
if (!(Mathf.Abs(cardObjects[i].transform.localPosition.x - cardPositions[i + cardArrayOffset].x) < 0.01f)) continue;
cardObjects[i].localPosition = cardPositions[i + cardArrayOffset]
cards[i].interactable = cardObjects[i].transform.localPosition.x == 0;
}
}
We change all of the cards variables to cardObjects. On the GetComponent<>() line, we keep cards and remove the .gameObject.GetComponent<CanvasGroup>().
Important: You didn’t show us where some of the variables were created. Like cardPositions. If this is created using cards, make sure to use the cardObjects variable.

How to insert data into a 2D array of objects from a csv file?

I am trying to insert data into a 2D array of objects from a csv file but I have problems with initializing the 2D array of objects, and I get this error message:
IndexOutOfRangeException: Index was outside the bounds of the array.
UPDATE:
I think the problem is with Initializing the array of object , because I tried to insert data manually without using CSV file like this code below and still having the same error message :
UPDATE No.2 :
I tried to Simplify the code by making 1 object only but still cant insert data
Simplified code :
public CoreManager mng = new CoreManager();
void Start()
{
mng.actual_words[1] = "n"; //-> the problem I'm facing is on this line
Debug.Log(mng.actual_words[1]);
}
Here is my code trying to insert data from csv file :
public class NewBehaviourScript : MonoBehaviour
{
int sentenceNumber = 0;
int storynumber = 0;
public CoreManager[][] mng = new CoreManager[5][];
void Start()
{
TextAsset questdata = Resources.Load<TextAsset> ("first_storytest");
string[] data = questdata.text.Split(new char[] { '\n' });
Debug.Log(data.Length);
for (int i = 1; i < data.Length - 1; i++)
{
string[] row = data[i].Split(new char[] { ',' });
for(int x = 0; x < row.Length; x++)
{
if (row[x] != "")
{
if (row[x] == "***")
{
storynumber++;
sentenceNumber = 0;
}
else
{
mng[storynumber][sentenceNumber].actual_words[x] = row[x];
}
}
}
sentenceNumber++;
}
}
}
Here is my code trying to insert one item manually :
int sentenceNumber = 0;
int storynumber = 0;
public CoreManager[][] mng = new CoreManager[5][];
void Start()
{
mng[storynumber][sentenceNumber].actual_words[1]="test1";
}
public class CoreManager
{
[Tooltip("Write these words in actual sequence of the sentence")]
public string[] actual_words;
[Tooltip("Write these words in any sequence of the sentence")]
public string[] mixed_words;
}
This line of code only allows 5 entries in one dimension but doesn't allocate any space for the other direction. If you're using arrays, you need to provide the size up front.
public CoreManager[][] mng = new CoreManager[5][];
For testing purposes, I'd set the mng to [100][100] and use a small csv and see if this fixes your problem. If it does, then that's definitely the problem. If it doesn't, then something else is wrong.
Edit: After reviewing this some more, I'd suggest changing your data structure to use Dictionaries instead. This will provide more flexibility at runtime.
2nd Edit:
Or you can go with a multidemensional array which has a different syntax.
Feel free to run this example for yourself:
public static void Main()
{
Console.WriteLine("Lets get started!");
int[,] mng = new int[5,5];
mng[0,0] = 5;
Console.WriteLine(mng[0,0]);
}
// Output:
// Lets get started!
// 5

How do you add multiple elements in a list at once or with a loop?

I am trying to add a non-constant value of elements by either looping through x times or just adding x nr of elements directly.
I've tried looping for x amount of times and add an element every iteration, but it only ends up with one element. I've also tried adding a collection, but the same result occurred.
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class tileMapDepth
{
public List<bool> tileMapWidth;
public tileMapDepth(List<bool> realWidth)
{
this.tileMapWidth = realWidth;
}
}
public class TestListTypeAndSuch : MonoBehaviour
{
public List<tileMapDepth> tileMap = new List<tileMapDepth>(1);
public int width = 5;
public int depth = 5;
void Start()
{
for (int i = 0; i < depth; i++)
{
tileMap.Add(new tileMapDepth(new List<bool>(new List<bool>(width))));
foreach (tileMapDepth tile in tileMap)
{
for (int j = 0; j < width; j++)
{
tile.tileMapWidth.Add(false);
}
}
}
}
}
The expected result is to add a nr of elements into a list and not just one element.
When i try and add booleans with a constant value as the amount it works fine. But i need to add it with a dynamic variable. The code below is the only one that is working.
for (int i = 0; i < depth; i++)
{
tileMap.Add(new tileMapDepth(new List<bool>(new List<bool>(new bool[13]))));
}
Try
List<T>.AddRange(IEnumerable<T>) Method
Adds the elements of the specified collection to the end of the List.
You are trying to add false value to a list 5 times i.e in tileMapWidth. To add same value n times to list you can use Enumerable.Repeat()
List<bool> tileMapWidth = Enumerable.Repeat(false, 5).ToList();
This list you can pass as a parameter to tileMapDepth() class
something like
tileMap.Add(new tileMapDepth(tileMapWidth));

Strange behavior adding objects to Array Unity3d C#

I am seeing some odd behavior, when adding objects to an array of GameObjects. Here is my sudo code:
public class GameController : MonoBehaviour {
public GameObject[] MyArray;
void Awake() {
Application.runInBackground = true;
MyArray= new GameObject[144];
}
//some code that calls myFunction
public IEnumerator myFunction(float time)
{
int counter = 0;
GameObject card= AnotherArrayOfGameObjects[0];
for (int j = 0; j < 144; j++)
{
card.name = "BLANK_" + (j+1);
Instantiate(card, cardVector, Quaternion.Euler(0, rotateAdujust, 180));
MyArray[counter] = card;
yield return new WaitForSeconds(time);
counter++;
}
}
}
This function kind of works ok. It creates my object and instantiates it. But, when it adds the object "card" to the array MyArray, it does not add it correctly. I.e, as this is in a loop, 0-143, I would expect the array to look like this:
MyArray[0] = "BLANK_1"
MyArray[1] = "BLANK_2"
....
MyArray[143] = "BLANK_144"
Instead, it looks like this:
MyArray[0] = "BLANK_144"
MyArray[1] = "BLANK_144"
....
MyArray[143] = "BLANK_144"
I can see all this, by the way, because MyArray is a public variable in my code, so I can see it in Unity's Inspector. If I debug, I can see each iteration overwrite the previous. So, in the first iteration of the loop, i get:
MyArray[0] = "BLANK_1"
Then in the second iteration of the loop, I get:
MyArray[0] = "BLANK_2"
MyArray[1] = "BLANK_2"
In the Third:
MyArray[0] = "BLANK_3"
MyArray[1] = "BLANK_3"
MyArray[2] = "BLANK_3"
Until it completes the full loop and all items in the array say "BLANK_144"
Can anyone explain why this is happening?
You are adding same card object to array on each iteration. And you are changing name of this object on each iteration. Thus you end up with array, all items of which are pointing to same card instance. And that card instance whill have latest name which you have assigned (on last iteration):
MyArray[counter] = card;
Remember - Instantiate method returns cloned object, but it does not change the object which you are cloning. So you instantiate new clone on each iteration, but you don't save it anywhere.
You should add to array card clones which you are instantiating:
GameObject card = AnotherArrayOfGameObjects[0];
for (int j = 0; j < 144; j++)
{
var cardClone = Instantiate(card, cardVector, Quaternion.Euler(0, rotateAdujust, 180));
cardClone.name = "BLANK_" + (j+1);
MyArray[j] = cardClone;
yield return new WaitForSeconds(time);
}

Categories

Resources