can't change sprite on an object of dictionary - c#

I am trying to change sprite of an object of dictionary when i click a key on keyboard. But i can't do that. this my code
using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
public class plantingScript : MonoBehaviour {
public float plantV = 0f;
public float coordX = 0f;
public float coordY = 0f;
public float koordX = 0f;
public float koordY = 0f;
public walkingScript ws = new walkingScript();
public loadGame loadLand ;
public GameObject gameObj;
//public SpriteRenderer spriteObj;
public Dictionary<string,Tanah> tempTanah = new Dictionary<string, Tanah>();
public Dictionary<string,GameObject> tempObjTanah = new Dictionary<string, GameObject>();
void Awake(){
//spriteObj = gameObj.AddComponent<SpriteRenderer>();
loadLand = GameObject.Find ("loadGameObject").GetComponent<loadGame>();
tempTanah = loadLand.myTanah;
tempObjTanah = loadLand.objTanah;
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if(Input.GetKeyDown(KeyCode.V))
cekLokasi();
}
void cekLokasi(){
Debug.Log ("V pressed!");
GameObject temp = null;
coordX = (int)(gameObject.transform.localPosition.x / 0.8f + gameObject.transform.localPosition.y / 0.4f) / 2;
coordY = (int)(gameObject.transform.localPosition.y / 0.4f - (gameObject.transform.localPosition.x / 0.8f)) / 2;
if(ws.hadapAtas == true && ws.hadapKanan == true)
{
koordY = (int) coordY;
koordX = (int) coordX + 1;
}
else if(ws.hadapAtas == false && ws.hadapKanan == true)
{
koordY = (int) coordY;
koordX = (int) coordX - 1;
}
else if(ws.hadapAtas == false && ws.hadapKanan == false)
{
koordY = (int) coordY + 1;
koordX = (int) coordX;
}
else if(ws.hadapAtas == true && ws.hadapKanan == false)
{
koordY = (int) coordY + 1;
koordX = (int) coordX;
}
if(tempObjTanah.TryGetValue("land-"+koordY.ToString("0#")+"-"+koordX.ToString("0#"),out temp))
{
Sprite mySprite = null;
Debug.Log ("Land found!");
mySprite = loadLand.myTanah["land-"+koordY.ToString("0#")+"-"+koordX.ToString("0#")].spriteTanah["Garap"];
Debug.Log ("Sprite found!");
gameObj = tempObjTanah["land-"+koordY.ToString("0#")+"-"+koordX.ToString("0#")];
gameObj.AddComponent<SpriteRenderer>();
gameObj.GetComponent<SpriteRenderer>().sprite = mySprite;
/*
Sprite mySprite = null;
Debug.Log ("Land found!");
mySprite = loadLand.myTanah["land-"+koordY.ToString("0#")+"-"+koordX.ToString("0#")].spriteTanah["Garap"];
Debug.Log ("Sprite found!");
tempObjTanah["land-"+koordY.ToString("0#")+"-"+koordX.ToString("0#")].AddComponent<SpriteRenderer>();
SpriteRenderer mySpriteRend = tempObjTanah["land-"+koordY.ToString("0#")+"-"+koordX.ToString("0#")].GetComponent<SpriteRenderer>();
mySpriteRend.sprite = mySprite;
}
*/
}
}
}
this is how that dictionary of gameObject was made
using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
public class loadGame : MonoBehaviour {
public static loadGame loadSave;
public GameObject objPrince;
public Pangeran charPrince;
public Transform prefPrince;
public Sprite[] spriteTanah;
public Dictionary<string, Tanah> myTanah = new Dictionary<string, Tanah>();
public Dictionary<string, GameObject>objTanah = new Dictionary<string, GameObject>();
public Tanah tempTanah;
public GameObject tempObjTanah;
public Transform prefTanah;
public float mapX;
public float mapY;
public int i = 0;
public int j = 0;
public int rows = 9;
public int column = 9;
void Awake(){
if(loadSave == null)
{
DontDestroyOnLoad(gameObject);
loadSave = this;
}
else if(loadSave != this)
Destroy(gameObject);
}
// Use this for initialization
void Start () {
Load ();
}
// Update is called once per frame
void Update () {
}
public void Load(){
if(File.Exists(Application.persistentDataPath + "/playerInfo.dat"))
{
}
else
{
charPrince = new Pangeran ("Prince", "04Okt1993", 0, 0, 0, 0, 0, false, false);
objPrince = GameObject.Instantiate (prefPrince, new Vector3 (0, 0, 0), Quaternion.identity) as GameObject;
//objPrince.name = "Prince";
charPrince.locationY = 0f;
charPrince.locationX = 0f;
charPrince.hadapAtas = false;
charPrince.hadapKanan = true;
charPrince.stamina = 100f;
charPrince.exp = 0f;
charPrince.speed = 0f;
for(i = 0 ; i < rows ; i ++)
{
for(j = 0; j<column ; j++)
{
mapX = (i-j) * 0.8f;
mapY = (i+j) * 0.4f;
if(i>=1 && j>=1 && i<=5 && j<=5)
{
prefTanah.name = "land-"+j.ToString("0#")+"-"+i.ToString("0#");
tempTanah = new Tanah("land-"+j.ToString("0#")+"-"+i.ToString("0#"),mapX,mapY,"land",spriteTanah[0],spriteTanah[1],spriteTanah[2]);
myTanah.Add("land-"+j.ToString("0#")+"-"+i.ToString("0#"),tempTanah);
tempObjTanah = GameObject.Instantiate(prefTanah, new Vector3(mapX,mapY,0),Quaternion.identity)as GameObject;
objTanah.Add("land-"+j.ToString("0#")+"-"+i.ToString("0#"),tempObjTanah);
}
else
{
prefTanah.name = "snow-"+j.ToString("0#")+"-"+i.ToString("0#");
tempTanah = new Tanah("snow-"+j.ToString("0#")+"-"+i.ToString("0#"),mapX,mapY,"snow");
myTanah.Add("snow-"+j.ToString("0#")+"-"+i.ToString("0#"),tempTanah);
tempObjTanah = GameObject.Instantiate(prefTanah, new Vector3(mapX,mapY,0),Quaternion.identity)as GameObject;
objTanah.Add("snow-"+j.ToString("0#")+"-"+i.ToString("0#"),tempObjTanah);
}
}
}
}
}
}
and it made an error that said
NullReferenceException: Object reference not set to an instance of an
object plantingScript.cekLokasi () (at
Assets/Scripts/plantingScript.cs:78)
line 78 is
tempObjTanah["land-"+koordY.ToString("0#")+"-"+koordX.ToString("0#")].GetComponent<SpriteRenderer>().sprite = mySprite;
I am trying to change the sprite with other ways, but i didn't work.
please Help me. Thank you.

If Unity says it doesn't have a SpriteRenderer, then it doesn't have a SpriteRenderer.
gameObj.GetComponent<SpriteRenderer>() is what's null, and when you try to access the sprite property from it, you get the NullReferenceException.
Check how you've created your objects and make sure they have the right components attached. SpriteRenderer is not a default component.
EDIT: After reading your new code sample, I have a few more comments but unfortunately not a definite solution to your problem.
Your code is extremely difficult to read and understand, mostly due to the use of common variable names describing different things.
prefTanah.name = ...
tempTanah = ...
myTanah.Add(...);
tempObjTanah = ...
objTanah.Add(
prefTanah is a prefab, but you're changing its name to something that is dynamically generated. This name makes sense, but changing the name like this does not.
Then you create a Tanah object which I assume is some kind of data model. Then you add this to a dictionary of Tanah objects called myTanah.
But you're also maintaining a separate dictionary of GameObjects which appear to be related to the Tanah objects.
Also, tempObjTanah is assigned a GameObject in the second code sample, but it is referred to as a dictionary in the first one. Even if these are in different scopes, it's hard to understand for an outside observer.
Unfortunately, I don't see a direct solution to your original problem, but I'm certain that it is a result of your script being very messy and hard to understand. If the prefab referred to by prefTanah does indeed have a SpriteRenderer, my only guess is that your dictionary does not contain what you think it contains. My advice is to go over your script and make sure it's doing what you think it's doing. You can also try posting the entire script to pastebin or something so we can have more context about what's going on.

Related

Getting error with creating objects in Unity

I have an error in the script. At first, when the program starts, everything is fine, all InputFields have coordinates Y -200. But when I delete objects, and then re-create already the Y coordinate -800.
Where is the error?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SpawnText : MonoBehaviour
{
public int text_number = 20;
public GameObject TextPanel;
public GameObject toggle;
public GameObject ct;
private int k;
public GameObject[] obj;
public GameObject[] obj1;
public GameObject textTime;
public GameObject textPrice;
public GameObject InputFieldTime;
public GameObject InputFieldPrice;
private RectTransform rt;
private bool isSettings = false;
// Start is called before the first frame update
void Start()
{
CreateProgram();
}
// Update is called once per frame
//Клик на кнопку настроек
public void SettingsOnClick()
{
switch (isSettings)
{
case false:
isSettings = true;
textTime.SetActive(false);
textPrice.SetActive(false);
InputFieldTime.SetActive(false);
InputFieldPrice.SetActive(false);
for(int i = 0;i < text_number; i++)
{
Destroy(obj[i]);
Destroy(obj1[i]);
}
break;
case true:
isSettings = false;
textTime.SetActive(true);
textPrice.SetActive(true);
InputFieldTime.SetActive(true);
InputFieldPrice.SetActive(true);
CreateProgram();
break;
}
}
private void CreateProgram()
{
rt = ct.GetComponent<RectTransform>();
int height;
k = -60;
height = text_number * 72;
rt.sizeDelta = new Vector2(0, height);
for (int i = 0; i < text_number; i++)
{
obj[i] = Instantiate(TextPanel, new Vector2(0, 0), Quaternion.identity) as GameObject;
obj1[i] = Instantiate(toggle, new Vector2(0, 0), Quaternion.identity) as GameObject;
obj[i].transform.SetParent(ct.transform);
obj1[i].transform.SetParent(ct.transform);
obj[i].transform.localPosition = new Vector2(-200, k);
obj1[i].transform.localPosition = new Vector2(-420, k);
k -= 70;
obj[i].transform.localScale = new Vector2(1, 1);
obj1[i].transform.localScale = new Vector2(1, 1);
obj1[i].GetComponentInChildren<Text>().text = (i + 1).ToString();
}
}
}
When program starts
When delete and create objects
It is not Y but X actually
But note that the RectTransform is not the same as Transform.
What you see there in the Inspector is afaik the RectTransform.anchoredPosition not the transform.localPosition!
Not 100% sure but you should try and use
obj[i].GetComponent<RectTransform>().anchoredPosition = new Vector2(-200, k);
obj1[i].GetComponent<RectTransform>().anchoredPosition = new Vector2(-420, k);

Why does the script ignore the part after the first WaitForSeconds()?

I am trying to use WaitForSeconds() in my game to perform a scene.
I would love to here improvements and answers to the not working WaitForSeconds() (Its just ignores the part after I start to use WaitForSeconds())
The script:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class FoodManager : MonoBehaviour
{
public bool[] isFull;
public GameObject[] slots;
public GameObject[] itemNames;
public GameObject[] itemImages;
public GameObject[] itemAmounts;
public GameObject foodObject;
public GameObject mainPanel;
public string[] foodNames;
public Sprite[] foodImages;
public Sprite[] foodHalfImages;
public GameObject foodPanel;
public GameObject bird;
private int _lastFood;
private int _hunger;
void Update()
{
_hunger = PlayerPrefs.GetInt("_hunger");
for(int i = 0; i < 6; i++)
{
if (isFull[i] == true)
slots[i].SetActive(true);
if (isFull[i] == false)
slots[i].SetActive(false);
}
}
private void addItem(int max, string itemName, GameObject itemImage, int addingAmount)
{
for (int j = 0; j < max; j++)
{
if (isFull[j] == true && itemNames[j].GetComponent<Text>().text == itemName)
{
itemAmounts[j].GetComponent<Text>().text = (int.Parse(itemAmounts[j].GetComponent<Text>().text) + addingAmount).ToString();
_lastFood = j;
return;
}
if (isFull[j] == false)
{
isFull[j] = true;
itemNames[j].GetComponent<Text>().text = itemName;
itemAmounts[j].GetComponent<Text>().text = addingAmount.ToString();
itemImages[j].GetComponent<Image>().sprite = foodImages[j];
_lastFood = j;
return;
}
if (isFull[j] == true && int.Parse(itemAmounts[j].GetComponent<Text>().text) == 0)
{
isFull[j] = false;
return;
}
}
}
public void foodButtonsBehavior(int a)
{
if(a >= 0 && a <= 5)
{
StartCoroutine(foodEat(slots[a]));
}
if (a == 7) //add food button
{
addItem(7, "Special Seeds", itemImages[1], 2);
}
}
public void closeFoodMenu()
{
foodPanel.SetActive(false);
}
public IEnumerator foodEat(GameObject slot)
{
mainPanel.SetActive(false);
foodPanel.SetActive(false); // Start Of Animation
itemAmounts[_lastFood].GetComponent<Text>().text = (int.Parse(itemAmounts[_lastFood].GetComponent<Text>().text) - 1).ToString();
moveFood(-1f, -1f); // Resetting Position for the food
foodObject.GetComponent<SpriteRenderer>().sprite = foodImages[_lastFood];
yield return new WaitForSeconds(1.1f);
print("Continuing");
foodObject.SetActive(true);
//bird.transform.Rotate(0, 0, 0);
bird.transform.position = new Vector2(0, -2.4f);
yield return new WaitForSeconds(0.7f);
moveFood(-1f, -2f);
bird.transform.Rotate(0, 0, 0);
bird.transform.position = new Vector2(0, -2.4f);
yield return new WaitForSeconds(0.7f);
moveFood(-1f, -2.7f);
bird.transform.Rotate(0, 0, 0);
bird.transform.position = new Vector2(0, -2.4f);
yield return new WaitForSeconds(0.4f);
foodObject.GetComponent<SpriteRenderer>().sprite = foodHalfImages[_lastFood];
bird.transform.Rotate(0, 0, 0);
bird.transform.position = new Vector2(0, -2.4f);
yield return new WaitForSeconds(0.4f);
foodObject.SetActive(false);
bird.transform.Rotate(0, 0, 0);
bird.transform.position = new Vector2(0, -2.4f);
yield return new WaitForSeconds(0.8f);
PlayerPrefs.SetInt("_hunger", _hunger + 24);
foodPanel.SetActive(true); // End Of Animation
mainPanel.SetActive(true);
}
private void moveFood(float x, float y)
{
foodObject.transform.position = new Vector2(x, y);
}
public void changeBird(GameObject x)
{
bird = x;
}
}
I would love to get some help here, as this is critical for my game and I couldn't find my answer online, so I would appreciate if someone decides to help with the problem. (Srry stackOverFlow wouldn't let me post without the last lines.)
Something important to note is that Coroutines only run when the the gameobject it is attached to remains active. From the Coroutine documentation:
A coroutines also stops when the GameObject
it is attached to is disabled with SetActive(false)
This behaviour is consistent with the error you are seeing, albeit a little confusing because the code appears to continue running after you disable the object. There's a very nuanced explanation, but for a simplified version: SetActive(false) waits until the end of the frame to stop MonoBehaviours running on the gameobject.

Array inaccessible only at certain times

I am currently building a parallax background effect in Unity and starting with some starter code that I'm trying to work though. The code works for the most part, with some small issues I'm slowly getting through.
I have been testing out various stats of public vs. private, etc. but can't seem to work out exactly why and where the issue I'm facing is occurring.
When I run the same script and it calls Update() every frame, I would expect to have the same size "poolObjects" length. However, when I call it with a starting pool size of 10, I get 10, then 2, then 0, then 10, 2, 0, etc.
I am truncating it but posting what I think to be relevant here. Hope you can help me see what is likely obvious!
I do see "In GetPool Object" but because the length is never > 0, I never see within the For Loop, which is essential. I can't figure out why the poolObjects length would be showing up as 0.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Parallaxer : MonoBehaviour {
class PoolObject {
public Transform transform;
public bool inUse;
public PoolObject(Transform t) { transform = t; }
public void Use() { inUse = true; }
public void Dispose() { inUse = false; }
}
...
public int poolSize;
public float shiftSpeed;
public float spawnRate;
...
float spawnTimer;
PoolObject[] poolObjects;
float targetAspect;
GameManager game;
void Awake() {
Configure();
}
void Start() {
game = GameManager.Instance;
}
...
void Update() {
Debug.Log(poolObjects.Length + "Len here of pool objects");
if (game.GameOver) return;
Shift();
spawnTimer += Time.deltaTime;
if (spawnTimer > spawnRate) {
Spawn();
spawnTimer = 0;
}
}
void Configure() {
//spawning pool objects
targetAspect = targetAspectRatio.x / targetAspectRatio.y;
// targetAspect = Camera.main.aspect;
// Debug.Log(targetAspectRatio.x +" " + targetAspectRatio.y);
poolObjects = new PoolObject[poolSize];
for (int i = 0; i < poolObjects.Length; i++) {
GameObject go = Instantiate(Prefab) as GameObject;
Transform t = go.transform;
t.SetParent(transform);
t.position = Vector3.one * 1000;
poolObjects[i] = new PoolObject(t);
}
if (spawnImmediate) {
SpawnImmediate();
}
}
void Spawn() {
//moving pool objects into place
Transform t = GetPoolObject();
Debug.Log("In to Spawn" + t);
if (t == null) return;
Vector3 pos = Vector3.zero;
pos.y = Random.Range(ySpawnRange.minY, ySpawnRange.maxY);
pos.x = (defaultSpawnPos.x * Camera.main.aspect) / targetAspect;
// Debug.Log("Spwaning");
// Debug.Log(Camera.main.aspect);
// Debug.Log(immediateSpawnPos.x + " " + immediateSpawnPos.y + " " + targetAspect);
t.position = pos;
// Debug.Log(pos);
}
void SpawnImmediate() {
Transform t = GetPoolObject();
if (t==null) return;
Vector3 pos = Vector3.zero;
pos.y = Random.Range(ySpawnRange.minY, ySpawnRange.maxY);
pos.x = (immediateSpawnPos.x * Camera.main.aspect) / targetAspect;
t.position = pos;
Spawn();
}
void Shift() {
//loop through pool objects
//moving them
//discarding them as they go off screen
Debug.Log(poolObjects.Length + "Finding Length");
for (int i = 0; i < poolObjects.Length; i++) {
poolObjects[i].transform.position += -Vector3.right * shiftSpeed * Time.deltaTime;
Debug.Log(poolObjects[i].transform.position);
CheckDisposeObject(poolObjects[i]);
}
}
void CheckDisposeObject(PoolObject poolObject) {
//place objects off screen
if (poolObject.transform.position.x < (-defaultSpawnPos.x * Camera.main.aspect) / targetAspect) {
poolObject.Dispose();
poolObject.transform.position = Vector3.one * 1000;
}
}
Transform GetPoolObject() {
//retrieving first available pool object
Debug.Log("In GetPool Object" + poolObjects.Length);
for (int i = 0; i < poolObjects.Length; i++) {
Debug.Log("This is not showing up "+ poolObjects[i].inUse);
if (!poolObjects[i].inUse) {
poolObjects[i].Use();
return poolObjects[i].transform;
}
}
return null;
}
}

Why sometimes when generating a new grid i'm getting exception of missing renderer component?

This is the exception message:
MissingComponentException: There is no 'Renderer' attached to the
"Bottom Wall" game object, but a script is trying to access it. You
probably need to add a Renderer to the game object "Bottom Wall". Or
your script needs to check if the component is attached before using
it.
I have 3 scripts attached to the same GameObject in the Hierarchy.
The first script generate a grid:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GridGenerator : MonoBehaviour
{
public GameObject gridBlock;
public int gridWidth = 10;
public int gridHeight = 10;
public List<Vector3> positions = new List<Vector3>();
public List<GameObject> blocks = new List<GameObject>();
private GameObject[] wallsParents = new GameObject[4];
void Start()
{
wallsParents[0] = GameObject.Find("Top Wall");
wallsParents[1] = GameObject.Find("Left Wall");
wallsParents[2] = GameObject.Find("Right Wall");
wallsParents[3] = GameObject.Find("Bottom Wall");
GenerateGrid();
var testing = GetComponent<tester>();
tester.Test();
}
public void AutoGenerateGrid()
{
for (int i = 0; i < blocks.Count; i++)
{
DestroyImmediate(blocks[i]);
}
GenerateGrid();
var testing = GetComponent<tester>();
tester.Test();
}
public void GenerateGrid()
{
for (int x = 0; x < gridWidth; x++)
{
for (int z = 0; z < gridHeight; z++)
{
GameObject block = Instantiate(gridBlock, Vector3.zero, gridBlock.transform.rotation) as GameObject;
block.transform.parent = transform;
block.transform.tag = "Block";
block.transform.localScale = new Vector3(1, 0.1f, 1);
block.transform.localPosition = new Vector3(x * 1.5f, 0, z * 1.5f);
block.GetComponent<Renderer>().material.color = new Color(241, 255, 0, 255);
if (x == 0)//TOP
{
positions.Add(block.transform.localPosition);
block.transform.parent = wallsParents[0].transform;
block.transform.name = "TopWall";
blocks.Add(block);
}
else if (z == 0)//LEFT
{
positions.Add(block.transform.localPosition);
block.transform.parent = wallsParents[1].transform;
block.transform.name = "LeftWall";
blocks.Add(block);
}
else if (z == gridHeight - 1)//RIGHT
{
positions.Add(block.transform.localPosition);
block.transform.parent = wallsParents[2].transform;
block.transform.name = "RightWall";
blocks.Add(block);
}
else if (x == gridWidth - 1)//BOTTOM
{
positions.Add(block.transform.localPosition);
block.transform.parent = wallsParents[3].transform;
block.transform.name = "BottomWall";
blocks.Add(block);
}
}
}
}
}
The second script pick randomly two objects from any two walls:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public class tester : MonoBehaviour
{
private GameObject[] wallsParents = new GameObject[4];
public void Test()
{
try
{
wallsParents[0] = GameObject.Find("Top Wall");
wallsParents[1] = GameObject.Find("Left Wall");
wallsParents[2] = GameObject.Find("Right Wall");
wallsParents[3] = GameObject.Find("Bottom Wall");
var wallsList = wallsParents.ToList();
// remove random 2 times
for (int i = 0; i < 2; i++)
{
wallsList.Remove(wallsList[Random.Range(0, wallsList.Count)]);
}
var childsWall0 = wallsList[0].GetComponentsInChildren<Transform>();
var childsWall1 = wallsList[1].GetComponentsInChildren<Transform>();
var randomBlock = childsWall0[Random.Range(0, childsWall0.Length)];
var randomBlock1 = childsWall1[Random.Range(0, childsWall1.Length)];
randomBlock.GetComponent<Renderer>().material.color = Color.red;
randomBlock1.GetComponent<Renderer>().material.color = Color.red;
}
catch(MissingComponentException missing)
{
var mis = missing;
}
}
}
The third script add a button to the inspector and should generate each time a new grid with picked two random blocks from two random walls:
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(GridGenerator))]
public class GenerateGridButton : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
GridGenerator myScript = (GridGenerator)target;
if (GUILayout.Button("Generate New Grid"))
{
myScript.AutoGenerateGrid();
}
}
}
The problem is when i make some clicks on the button it's working fine but then after some clicks the exception is throw each time on another wall. Sometime on the Bottom Wall sometime on Left Right or Top. Sometimes after two clicks sometimes after 10 clicks on the button.
Before i added the button and the AutoGenerateGrid method it was working fine i was running the game and it was creating each time a new grid with two picked random walls and two picked blocks from the two walls.
After all when i click the button and destroying the all existing cubes and then create new cubes the new cubes should have renderer component.
I can't figure out what make this exception. i added try and catch but it didn't give me much more help.
I know the question is a bit long but each script is connected to each other so it's hard to narrow the question.
Your code is actually doing what you mentioned to it.
var childsWall0 = wallsList[0].GetComponentsInChildren<Transform>();
var childsWall1 = wallsList[1].GetComponentsInChildren<Transform>();
var randomBlock = childsWall0[Random.Range(0, childsWall0.Length)];
var randomBlock1 = childsWall1[Random.Range(0, childsWall1.Length)];
randomBlock.GetComponent<Renderer>().material.color = Color.red;
randomBlock1.GetComponent<Renderer>().material.color = Color.red;
If you read carefully this thread what is happening is you are getting the Transform component in your parent gameobject along with child game objects. Ofcourse if your parent game object wont have any Renderer if you are using it as a holder for group of objects. So for that you will have to get all the child of the gameobject and not parent gameobject itself.
And because you are doing Random with all objects tranform it will sometimes give the error if its parent was selected in the range. What I would suggest is romove the reference of parents in your childWall0 and childWall1 or another method is
foreach (Transform child in transform) {
//Add this child to your childsWall0 & childsWall1
}
But this will work only with intermediate objects and not nested. If you have nested elements better use your method but just remove parent that should solve your problem.
Also here are reference thread for finding child transfrom

Unity what's wrong with my instantiating algorithm?

I dont know if I can call this algorithm. But I am working on a game in which player will move in a circular path.
As you can see in the picture player is suppose to orbit the circle. And obstacle shall be instantiated in the circle.I am trying to first create the obstacle in first half(left to the long cube) and then in the second half. But things are getting created in the next half too when code is not supposed to do that. Also, it is showing argument exception error. Please have a look at my code and tell me whether my method is wrong or my formulas are wrong or anything else.
public class ObjectInstantiater : MonoBehaviour {
DataHolder dataholder;
GameObject Obstacle;
LevelData leveldata;
private int currentlevel=0; // default level starts from 0
private List<GameObject> Inactivegameobject = new List<GameObject>(); // this object can be used
private List<GameObject> Activegameobject = new List<GameObject>();
private int totalgameobjects;
private int firsthalfgameobjects, secondhalfgameobjects;
public float outerradius;
public float innerradius;
private bool shallspawnouterradiues = true;
// Use this for initialization
void Awake () {
dataholder = (Object)GameObject.FindObjectOfType<DataHolder>() as DataHolder;
Obstacle = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
leveldata = dataholder.Leveldata[0];
}
void Start()
{
Updateleveldata();
FirstHalf();
}
public int Currentlevel
{
get { return currentlevel; }
set { currentlevel = value;
leveldata = dataholder.Leveldata[currentlevel];//sets the level data
}
}
private void Updateleveldata() // this function gets called after a round
{
totalgameobjects = Random.Range(leveldata.MinimumObstacle, leveldata.MaximumObstacle);
firsthalfgameobjects = Mathf.RoundToInt(totalgameobjects / 2);
secondhalfgameobjects = totalgameobjects - firsthalfgameobjects;
}
private void FirstHalf()
{
Debug.Log(firsthalfgameobjects);
Vector3 pos;
if (Inactivegameobject.Count < firsthalfgameobjects)
{
for (int x = 0; x <= (firsthalfgameobjects - Inactivegameobject.Count); x++)
{
GameObject obs = Instantiate(Obstacle) as GameObject;
obs.SetActive(false);
Inactivegameobject.Add(obs);
}
}
float spawnangledivision = 180 / firsthalfgameobjects;
float spawnangle = 180f;
for(int x = 0; x < firsthalfgameobjects; x++)
{
float proceduralRandomangle = spawnangle;
proceduralRandomangle = Random.Range(proceduralRandomangle , proceduralRandomangle + 2f);
if (shallspawnouterradiues)
{
pos = new Vector3(outerradius * Mathf.Cos(spawnangle), outerradius * Mathf.Sin(spawnangle), 0f);
shallspawnouterradiues = false;
}else
{
pos = new Vector3(innerradius * Mathf.Cos(spawnangle), innerradius * Mathf.Sin(spawnangle), 0f);
shallspawnouterradiues = true;
}
spawnangle += spawnangledivision;
Inactivegameobject[0].SetActive(true); // set it to 0
Inactivegameobject[0].transform.position = pos;
Activegameobject.Add(Inactivegameobject[0]);
Inactivegameobject.RemoveAt(0);
}
}
private void SecondHalf()// No need to check this
{
if (Inactivegameobject.Count < firsthalfgameobjects)
{
GameObject obs = Instantiate(Obstacle) as GameObject;
obs.SetActive(false);
Inactivegameobject.Add(obs);
}
}
}

Categories