3D infinite runner game platform generation gives an exception - c#

Situation: I am referring to tutorial for my project,and there is an object pooling concept within the code.
Problem: What happens is , after I scripting the generation platform(PlatformManager.cs), I get an exceptions saying,
InvalidOperationException: Operation is not valid due to the current
state of the object
System.Collections.Generic.Queue`1[UnityEngine.Transform].Peek ()
PlatformManager.Update () (at Assets/Platform/PlatformManager.cs:35)
PlatformManager.cs script:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class PlatformManager : MonoBehaviour {
public Transform prefab;
public int numberOfObjects;
public float recycleOffset;
public Vector3 startPosition;
public Vector3 minSize, maxSize,minGap, maxGap;
public float minY, maxY;
private Vector3 nextPosition;
private Queue<Transform> objectQueue;
void Start () {
objectQueue = new Queue<Transform>(numberOfObjects);
for (int i = 0; i < numberOfObjects; i++) {
objectQueue.Enqueue((Transform)Instantiate(prefab));
}
nextPosition = startPosition;
for (int i = 0; i < numberOfObjects; i++) {
Transform o = (Transform)Instantiate(prefab);
o.localPosition = nextPosition;
nextPosition.x += o.localScale.x;
objectQueue.Enqueue(o);
}
}
void Update () {
if (objectQueue.Peek().localPosition.x + recycleOffset < Runner.distanceTraveled)//THIS IS THE 35TH LINE WHICH CAUSE THE ERROR
{
Transform o = objectQueue.Dequeue();
o.localPosition = nextPosition;
nextPosition.x += o.localScale.x;
objectQueue.Enqueue(o);
Recycle();
}
}
private void Recycle () {
Vector3 scale = new Vector3(
Random.Range(minSize.x, maxSize.x),
Random.Range(minSize.y, maxSize.y),
Random.Range(minSize.z, maxSize.z));
Vector3 position = nextPosition;
position.x += scale.x * 0.5f;
position.y += scale.y * 0.5f;
Transform o = objectQueue.Dequeue();
o.localScale = scale;
o.localPosition = position;
nextPosition.x += scale.x;
objectQueue.Enqueue(o);
nextPosition += new Vector3(
Random.Range(minGap.x, maxGap.x) + scale.x,
Random.Range(minGap.y, maxGap.y),
Random.Range(minGap.z, maxGap.z));
if(nextPosition.y < minY){
nextPosition.y = minY + maxGap.y;
}
else if(nextPosition.y > maxY){
nextPosition.y = maxY - maxGap.y;
}
}
}
Thanks in advance.

Make sure the queue is not empty.
if(objectQueue.Count != 0)
{
if (objectQueue.Peek().localPosition.x + recycleOffset < Runner.distanceTraveled)//THIS IS THE 35TH LINE WHICH CAUSE THE ERROR
{
Transform o = objectQueue.Dequeue();
o.localPosition = nextPosition;
nextPosition.x += o.localScale.x;
objectQueue.Enqueue(o);
Recycle();
}
}

Related

Instantiating Custom Object in Unity MonoBehaviour Scripts

I'm trying to programm my own little game in Unity, I'm not new to programming but new to Unity and C#. The problem is that I wrote my own classes to handle the game map and I am trying to connect these classes to the MonoBehaviour Scripts in Unity.
I have a script called InputManager, which is supposed to handle the input via mouse and keyboard etc. and in this script I want to create an object of the class MapManager which has access to my tiles and stuff. The problem I'm getting is that I can't seem to create an instance of MapManager in InputManager, not with the common new MapManager() anyway. When I use this a NullPointer of some sort is created, I guess?
I do not get a compiling error but an error once the game is launched which is:
NullReferenceException: Object reference not set to an instance of an object
InputManager.Update () (at Assets/Scripts/InputManager.cs:55)
Thank you for your help!
!UPDATE!:
I tried using a workaround so that it does not matter if Start() or Update() is called first, meaning that I just instantiate MapManager in the first Update() call. However, when I run the program the error is still the same. My conclusion is that somehow my constructor is not working or the Monobehaviour script somehow does not allow using the standard constructor... Any ideas?
Here is my code:
InputManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public class InputManager : MonoBehaviour
{
public int mapRightBorder = 10;
public int mapLeftBorder = -10;
public int mapTopBorder = 8;
public int mapBottomBorder = -4;
public double camSpeed = 0.2;
public double mouseSensitivity = 0.3;
public double scrollSensitivity = 2;
public double maxZoomIn = -3;
public double maxZoomOut = -12;
public Tilemap ground, overlays, buildings;
public Tilemap selected;
public AnimatedTile animatedTile;
private double detectionBorder;
private double leftRightCorrection;
private MapManager mapManager;
// Start is called before the first frame update
void Start()
{
detectionBorder = 50;
leftRightCorrection = 1.2;
mapManager = new MapManager();
mapManager.ground = ground;
mapManager.overlays = overlays;
mapManager.buildings = buildings;
mapManager.selected = selected;
mapManager.animatedTile = animatedTile;
Cursor.lockState = CursorLockMode.Confined;
}
// Update is called once per frame
void Update()
{
moveCam();
checkMouse();
mapManager.updateTilemaps();
}
private void moveCam()
{
double moveX = Camera.main.transform.position.x;
double moveY = Camera.main.transform.position.y;
double moveZ = Camera.main.transform.position.z;
double xPos = Input.mousePosition.x;
double yPos = Input.mousePosition.y;
double zDelta = Input.GetAxis("Mouse ScrollWheel");
if (Input.GetKey(KeyCode.LeftArrow))
{
moveX -= camSpeed * leftRightCorrection;
}
else if (xPos >= 0 && xPos < detectionBorder)
{
moveX -= camSpeed * mouseSensitivity * leftRightCorrection;
}
else if (Input.GetKey(KeyCode.RightArrow))
{
moveX += camSpeed * leftRightCorrection;
}
else if (xPos <= Screen.width && xPos > Screen.width - detectionBorder)
{
moveX += camSpeed * mouseSensitivity * leftRightCorrection;
}
if(moveX > mapRightBorder || moveX < mapLeftBorder)
{
moveX = Camera.main.transform.position.x;
}
if (Input.GetKey(KeyCode.DownArrow))
{
moveY -= camSpeed;
}
else if (yPos >= 0 && yPos < detectionBorder)
{
moveY -= camSpeed * mouseSensitivity;
}
else if (Input.GetKey(KeyCode.UpArrow))
{
moveY += camSpeed;
}
else if (yPos <= Screen.height && yPos > Screen.height - detectionBorder)
{
moveY += camSpeed * mouseSensitivity;
}
if(moveY > mapTopBorder || moveY < mapBottomBorder)
{
moveY = Camera.main.transform.position.y;
}
if (!(moveZ + zDelta * scrollSensitivity > maxZoomIn || moveZ + zDelta * scrollSensitivity < maxZoomOut))
{
moveZ += zDelta * scrollSensitivity;
}
Vector3 newPos = new Vector3((float)moveX, (float)moveY, (float) moveZ);
Camera.main.transform.position = newPos;
}
private void checkMouse()
{
if (Input.GetMouseButtonDown(0))
{
mapManager.selectTile(Input.mousePosition);
}
}
}
MapManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public class MapManager
{
public int mapWidth = 16;
public int mapHeight = 16;
public Tilemap ground, overlays, buildings;
public Tilemap selected;
public AnimatedTile animatedTile;
private Vector3Int currentlySelected;
private OwnTilemap tilemap;
public MapManager()
{
tilemap = new OwnTilemap(mapWidth, mapHeight, ground, overlays, buildings);
currentlySelected = new Vector3Int(-1, -1, 0);
}
private Vector3Int mouseToTilemap(Vector3 mousePosition)
{
Ray ray = Camera.main.ScreenPointToRay(mousePosition);
// create a plane at 0,0,0 whose normal points to +Y:
Plane hPlane = new Plane(Vector3.forward, Vector3.zero);
// Plane.Raycast stores the distance from ray.origin to the hit point in this variable:
float enter = 0.0f;
if (hPlane.Raycast(ray, out enter))
{
//Get the point that is clicked
Vector3 hitPoint = ray.GetPoint(enter);
Vector3Int cell = ground.WorldToCell(hitPoint);
return cell;
}
return new Vector3Int(-1, -1, 0);
}
private bool isInBorders(Vector3Int p)
{
if (p.z != 0) return false;
if (p.x < 0 || p.x >= mapWidth) return false;
if (p.y < 0 || p.y >= mapHeight) return false;
return true;
}
public void updateTilemaps()
{
tilemap.updateTilemaps();
}
public void previewBuilding()
{
}
public void selectTile(Vector3 mousePosition)
{
if(currentlySelected != new Vector3Int(-1, -1, 0))
{
selected.SetTile(currentlySelected, null);
}
if (isInBorders(mouseToTilemap(mousePosition)))
{
selected.SetTile(mouseToTilemap(mousePosition), animatedTile);
currentlySelected = mouseToTilemap(mousePosition);
}
}
}

Drawing a Turkey in unity2d using Verlet method

This is a homework problem(Do not copy, copy is not smart): We need to draw a 2d turkey in unity 2d using Verlet method to update the positions of the vertices. However, We don't know the forces involved to trace the Turkey. Here is a picture of the Turkey. Is there a trick?
Here is the codes that we started:
public class GenerateTurkeys : MonoBehaviour
{
LineRenderer lineRenderer = gameObject.AddComponent<LineRenderer>();
// Start is called before the first frame update
int numberOfTurkeys;
int NUM_PARTICLES;
float fTimeStep;
Vector3[] m_position = new Vector3[NUM_PARTICLES];
Vector3[] m_acceleration = new Vector3[NUM_PARTICLES];
Vector3[] m_oldPosition = new Vector3[NUM_PARTICLES];
void Start()
{
NUM_PARTICLES = 100;
numberOfTurkeys = 0;
}
// Verlet integration step void ParticleSystem::
Verlet()
{
for (int i=0; i<NUM_PARTICLES; i++)
{
Vector3 x = m_position[i];
Vector3 temp = x;
Vector3 oldx = m_oldPosition[i];
Vector3 a = m_acceleration[i];
x += x-oldx+a* fTimeStep*fTimeStep;
oldx = temp;
}
}
void DrawLine(float[] heights)
{
LineRenderer lineRenderer = GetComponent<LineRenderer>();
var t = Time.time;
for (int i = 0; i < NUM_PARTICLES; i++)
{
lineRenderer.SetPosition(i, );
}
}
// Update is called once per frame
void Update()
{
}
}
I'm not sure that I correctly decided, due to the fact that the contour does not match, but in the solution the speed is exactly iterative. I think this is a small error of physics in Unity, Because if you use the resulting accelerations, you can draw the graph very accurately.
Here is code:
public class Drawer : MonoBehaviour
{
[SerializeField]
private Transform[] m_Dots;
private Rigidbody2D m_Dot;
private Vector2[] m_Acceler;
float deltaT = 0.5f;//for example
private void Start()
{
m_Acceler = GetAcceler();
var go = new GameObject("Tracer");
var tr = go.AddComponent<TrailRenderer>();
tr.widthMultiplier = 0.1f;
tr.time = 50f;
m_Dot = go.AddComponent<Rigidbody2D>();
m_Dot.bodyType = RigidbodyType2D.Kinematic;
m_Dot.gravityScale = 0;
StartCoroutine(VerletCoroutine());
}
private Vector2[] GetAcceler()
{
Vector2[] result = new Vector2[m_Dots.Length];
float T = deltaT;
int len = m_Dots.Length;
result[0] = An(m_Dots[1].position, m_Dots[0].position, m_Dots[0].position, T);
for (int i = 1 ; i < len - 1 ; i++, T += deltaT)
{
result[i] = An(m_Dots[i + 1].position, m_Dots[i].position, m_Dots[i].position, T);
}
result[len - 1] = An(m_Dots[0].position, m_Dots[len - 1].position, m_Dots[len - 1].position, T);
return result;
}
private Vector2 An(Vector2 Xnext, Vector2 Xn, Vector2 Xprev, float t)
{// a[n] = (x[n+1] - 2*x[n]+x[n-1])/t^2
return (Xnext - 2 * Xn + Xprev) / t * t;
}
private IEnumerator VerletCoroutine()
{
m_Dot.transform.position = m_Dots[0].position;
Vector2 Vprev = Vector2.zero;
int len = m_Acceler.Length - 1;
float t = 0;
int i = 0;
while (true)
{
t += Time.deltaTime;
if (t >= deltaT)
{
i++;
if (i > len)
{
break;
}
t = 0;
Vprev = Vector2.zero;
}
Vprev = Vnext(Vprev, m_Acceler[i], m_Acceler[i], t);
m_Dot.velocity = Vprev;
yield return new WaitForEndOfFrame();
}
m_Dot.velocity = Vector3.zero;
yield return null;
}
private Vector2 Vnext(Vector2 Vn, Vector2 Anext, Vector2 An, float t)
{//v[n+1]= v[n]+0,5(a[n+1] +a[n]) * t
var v = Vn + 0.5f * (Anext + An) * t;
return v;
}
}

For some reason when I reactivate objects in my object pool they are static?

I'm currently working on a game and I ran into a small issue. I'm currently trying to create an object pool for objects that will reappear constantly in my game in order to improve the framerate of my game. However when creating this object pool whenever the game starts and the pool of objects is created and then activated and then deactivated and then reactivated again the game objects always get reactivated in a static state. I've tried going through my code to find out where this problem might be coming from but I have no Idea. All the reactivated game objects have rigidbodys and the proper tags.
Ive tried going trough all the different classes which might be creating this problem but I haven't found anything out of the ordinary myself.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnPoint: MonoBehaviour
{
public Transform SpawnPoints;
public GameObject[] interact;
List<float> StarPositions = new List<float>();
int Interact;
int index = 1;
public int pooledAmount = 40;
List<GameObject> colouredBalls;
public static bool spawnAllowed;
public static int count = 0;
public void Start()
{
colouredBalls = new List<GameObject>();
for (int c = 0; c < pooledAmount; c++)
{
GameObject obj = (GameObject)Instantiate(interact[0]);
obj.SetActive(false);
colouredBalls.Add(obj);
}
if (ScoreScript.scoreValue < 5)
{
Vector2 pos = Camera.main.WorldToViewportPoint(transform.position);
for (int x = 1; x < 5; x++)
{
//Vector3 SpawnPos = spawnPoints[d].position;
int NrSpawnpoints = 4;
int NrSpaces = NrSpawnpoints + 1;
double Xlegnth = 1.0;
double spawnPosX = x * Xlegnth / NrSpaces;
pos.x = (float)spawnPosX;
pos.y = 1.3f;
Vector2 Posi = Camera.main.ViewportToWorldPoint(pos);
Instantiate(SpawnPoints, Posi, Quaternion.identity);
//Debug.Log(Posi);
}
}
spawnAllowed = true;
InvokeRepeating("SpawnAInteract", 0f, 1f);
}
void SpawnAInteract()
{
if (spawnAllowed)
{
int randomSpawnPoint;
Vector2 pos = Camera.main.WorldToViewportPoint(transform.position);
//Vector2 starpos = Camera.main.WorldToViewportPoint(transform.position);
if (index % 10 != 0)
{
for (int d = 1; d < 5; d++)
{
//Vector3 SpawnPos = spawnPoints[d].position;
int NrSpawnpoints = 4;
int NrSpaces = NrSpawnpoints + 1;
double Xlegnth = 1.0;
double spawnPosX = d * Xlegnth / NrSpaces;
pos.x = (float)spawnPosX;
pos.y = 1.3f;
Vector2 Posi = Camera.main.ViewportToWorldPoint(pos);
if (!colouredBalls[d].activeInHierarchy)
{
colouredBalls[d].transform.position = Posi;
colouredBalls[d].transform.rotation = transform.rotation;
colouredBalls[d].SetActive(true);
//Debug.Log("Nr active Balls:" + f + colouredBalls[f].activeInHierarchy);
Debug.Log("Nr active Balls:" + d + colouredBalls[d].activeInHierarchy);
count++;
break;
}
}
index++;
}
else
{
for (int d = 1; d < 5; d++)
{
int NrSpawnpoints = 4;
int NrSpaces = NrSpawnpoints + 1;
double Xlegnth = 1.0;
double spawnPosX = d * Xlegnth / NrSpaces;
pos.x = (float)spawnPosX;
pos.y = 1.3f;
Vector2 Posi = Camera.main.ViewportToWorldPoint(pos);
StarPositions.Add((float)spawnPosX);
//Debug.Log("Starpositions " + StarPositions.ToString());
//edit this
double StarPos = spawnPosX - Xlegnth / NrSpaces / 2;
//Change to a list
//Debug.Log("Star " + d);
StarPositions[d - 1] = (float)StarPos;
}
//edit this to make the star appear at the StarPosition directly to the left or to the right of the WhiteBall
Vector2 Start = new Vector2(0, 0);
Vector2 StartCon = Camera.main.ViewportToWorldPoint(Start);
float whiteBallX = GameObject.FindWithTag("White Ball").transform.position.x;
for (int d = 1; d < 5; d++)
{
if (whiteBallX >= StartCon.x && whiteBallX <= StarPositions[d - 1])
{
int[] potentialStarPositions = { d, d + 2 };
int positionIndex = Random.Range(0, 2);
int randomSpawnPoin = potentialStarPositions[positionIndex];
pos.x = StarPositions[randomSpawnPoin];
pos.y = 1.3f;
Vector2 StarPosi = Camera.main.ViewportToWorldPoint(pos);
Interact = 1;
Instantiate(interact[Interact], StarPosi, Quaternion.identity);
break;
}
}
index++;
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectDestroy: MonoBehaviour
{
public Transform CameraCollider;
int NonActive = 0;
void Start()
{
Vector3 ScreenSize = new Vector3(1.5f, 1.5f, 1.5f);
Vector3 ScreenSizeAdj = Camera.main.ViewportToWorldPoint(ScreenSize);
CameraCollider.localScale = ScreenSizeAdj;
Vector3 ScreenPos = new Vector3(0.5f, 0.5f, 0);
Vector3 ScreenPosAdj = Camera.main.ViewportToWorldPoint(ScreenPos);
Instantiate(CameraCollider, ScreenPosAdj, Quaternion.identity);
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.gameObject.CompareTag("ColouredBall Highress") || other.gameObject.CompareTag("Star"))
{
other.gameObject.SetActive(false);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InteractControl : MonoBehaviour
{
Rigidbody2D rb;
GameObject target;
float moveSpeed;
Vector3 directionToTarget;
Renderer m_Renderer;
void Start()
{
target = GameObject.Find("White Ball");
rb = GetComponent<Rigidbody2D>();
moveSpeed = 3f; //Movement speed of all the obstacles and powerups
MoveInteract(); //Method responsable for the movement of the obstacles and powerups, gets called at start
}
void MoveInteract() //Method responsable for the movement of the obstacles and stars
{
if (target != null)
{
if(ScoreScript.scoreValue > 5) //Determine when RedBall goes from going down in a straigh line to following white ball
{
directionToTarget = (target.transform.position - transform.position).normalized;
rb.velocity = new Vector2(directionToTarget.x * moveSpeed,
directionToTarget.y * moveSpeed);
}
else //Red Ball goes down in a straigh line
{
directionToTarget = new Vector3(0, -1, 0);
rb.velocity = new Vector2(0, directionToTarget.y * moveSpeed);
}
}
else
rb.velocity = Vector3.zero;
}
}
This is normal, when you deactivate an object the velocity resets. You must save their velocity before deactivating then set it again when reactivated.
I would look for other kind of optimization, this makes code more complex and probably there are better ways of optimizing it.
Edit: A quick solution would be to deactivate the sprite renderer, instead of the whole game object. This would optimize gpu load which I guess is the problem.

How can i check when the object MoveTowards has reached to the new position and then rotate it?

private void MoveToNewFormation()
{
squadMembers = GameObject.FindGameObjectsWithTag("Squad Member");
float step = speed * Time.deltaTime;
for (int i = 0; i < squadMembers.Length; i++)
{
squadMembers[i].transform.LookAt(newpos[i]);
squadMembers[i].transform.position = Vector3.MoveTowards(squadMembers[i].transform.position, newpos[i], step);
//squadMembers[i].transform.rotation = qua[i];
}
}
And calling it in the Update:
void Update()
{
if (Input.GetKeyDown(KeyCode.F))
{
ChangeFormation();
}
if (move == true)
MoveToNewFormation();
}
Once when one of the squadMembers reached to the newpos then i want to make
squadMembers[i].transform.rotation = qua[i];
qua is a List and i want to rotate the squad member once he reached the newpos.
Inside MoveToNewFormation i thought to add after the loop the line:
if (squadMembers[i].transform.position == newpos[i])
{
squadMembers[i].transform.rotation = qua[i];
}
But it's after the loop so 'i' not exist.
This is the complete script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SquadFormation : MonoBehaviour
{
enum Formation
{
Square, Circle, Triangle
}
public Transform squadMemeber;
public int columns = 4;
public int squareSpace = 10;
public int circleSpace = 40;
public int numberOfObjects = 20;
public float yOffset = 0;
public float speed = 3;
private Formation formation;
private GameObject[] squadMembers;
private List<Quaternion> qua = new List<Quaternion>();
private List<Vector3> newpos = new List<Vector3>();
private bool move = false;
// Use this for initialization
void Start()
{
formation = Formation.Square;
ChangeFormation();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.F))
{
ChangeFormation();
}
if (move == true)
MoveToNewFormation();
}
private void ChangeFormation()
{
switch (formation)
{
case Formation.Square:
FormationSquare();
break;
case Formation.Circle:
FormationCircle();
break;
}
}
private Vector3 FormationSquarePositionCalculation(int index) // call this func for all your objects
{
float posX = (index % columns) * squareSpace;
float posY = (index / columns) * squareSpace;
return new Vector3(posX, posY);
}
private void FormationSquare()
{
for (int i = 0; i < numberOfObjects; i++)
{
Transform go = Instantiate(squadMemeber);
Vector3 pos = FormationSquarePositionCalculation(i);
go.position = new Vector3(transform.position.x + pos.x, 0, transform.position.y + pos.y);
go.Rotate(new Vector3(0, -90, 0));
go.tag = "Squad Member";
}
formation = Formation.Circle;
}
private Vector3 FormationCirclePositionCalculation(Vector3 center, float radius, int index, float angleIncrement)
{
float ang = index * angleIncrement;
Vector3 pos;
pos.x = center.x + radius * Mathf.Sin(ang * Mathf.Deg2Rad);
pos.z = center.z + radius * Mathf.Cos(ang * Mathf.Deg2Rad);
pos.y = center.y;
return pos;
}
private void FormationCircle()
{
Vector3 center = transform.position;
float radius = (float)circleSpace / 2;
float angleIncrement = 360 / (float)numberOfObjects;
for (int i = 0; i < numberOfObjects; i++)
{
Vector3 pos = FormationCirclePositionCalculation(center, radius, i, angleIncrement);
var rot = Quaternion.LookRotation(center - pos);
pos.y = Terrain.activeTerrain.SampleHeight(pos);
pos.y = pos.y + yOffset;
newpos.Add(pos);
qua.Add(rot);
}
move = true;
formation = Formation.Square;
}
private void MoveToNewFormation()
{
squadMembers = GameObject.FindGameObjectsWithTag("Squad Member");
float step = speed * Time.deltaTime;
for (int i = 0; i < squadMembers.Length; i++)
{
squadMembers[i].transform.LookAt(newpos[i]);
squadMembers[i].transform.position = Vector3.MoveTowards(squadMembers[i].transform.position, newpos[i], step);
//squadMembers[i].transform.rotation = qua[i];
}
//if (squadMembers[i].transform.position == newpos[i])
}
}
You can use a threshold and check the distance using that threshold.
Define threshold like this at start of script.
public float threshold = 0.1f;
Then change the MoveToNewFormation() function like this:
private void MoveToNewFormation()
{
squadMembers = GameObject.FindGameObjectsWithTag("Squad Member");
float step = speed * Time.deltaTime;
for (int i = 0; i < squadMembers.Length; i++)
{
squadMembers[i].transform.LookAt(newpos[i]);
squadMembers[i].transform.position =
Vector3.MoveTowards(squadMembers[i].transform.position, newpos[i], step);
if(Vector3.Distance(squadMembers[i].transform.position,newpos[i])<threshold){
squadMembers[i].transform.rotation = qua[i];
}
}
//if (squadMembers[i].transform.position == newpos[i])
}

Return an ArrayList of GameObjects and grid issue

I was trying to generate a grid Unity3d and store all the tiles in an array. I want to use the created array also in others function.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class createGridClean : MonoBehaviour {
public GameObject tilePrefab = null;
public int numberOfTiles = 10;
public int tilesPerColumn = 4;
public float distanceBetweenTiles = 2.0f;
public Material newmat = null;
// Use this for initialization
void Start () {
CreateTiles ();
}
// Update is called once per frame
void Update () {
}
public ArrayList[] CreateTiles(){
GameObject[] allTiles = new GameObject[numberOfTiles*tilesPerColumn];
float xOffset = 0.0f;
float zOffset = 0.0f;
for (int createdTiles = 0; createdTiles <= numberOfTiles; createdTiles++) {
xOffset += distanceBetweenTiles;
if ( createdTiles % tilesPerColumn == 0){
zOffset += distanceBetweenTiles;
xOffset = 0.0f;
}
allTiles[createdTiles] = Instantiate (tilePrefab, new Vector3 (0f + xOffset, 0f, 0f + zOffset), Quaternion.identity) as GameObject;
}
return allTiles;
}
}
But here's the output:
Assets/my/Script/createGridClean.cs(34,17): error CS0029: Cannot implicitly convert type `UnityEngine.GameObject[]' to `System.Collections.ArrayList[]'
I have have even a problem with the grid, everytime an additional and unwanted extra cube were generated!
(here the original code that I've translated in C#)
function CreateTiles()
{
var xOffset: float = 0.0;
var zOffset: float = 0.0;
for(var tilesCreated: int = 0; tilesCreated < numberOfTiles; tilesCreated += 1)
{
xOffset += distanceBetweenTiles;
if(tilesCreated % tilesPerRow == 0)
{
zOffset += distanceBetweenTiles;
xOffset = 0;
}
Instantiate(tilePrefab, Vector3(transform.position.x + xOffset, transform.position.y, transform.position.z + zOffset), transform.rotation);
}
}
Any help will be fantastic!
Thanks,
Marco
Try changing
public ArrayList[] CreateTiles()
{
GameObject[] allTiles = new GameObject[numberOfTiles*tilesPerColumn];
...
return allTiles;
}
to:
public GameObject[] CreateTiles()
{
GameObject[] allTiles = new GameObject[numberOfTiles*tilesPerColumn];
...
return allTiles;
}
The error message you're getting: Cannot implicitly convert type X to Y refers to the fact that you're implicitly converting your GameObject[] to an ArrayList[]. You must either explicitly cast to an ArrayList[] (e.g. return (ArrayList[]) allTiles, although I'm not sure that's what you're after), or change your method to return a GameObject[].
Your question is a duplicate of all these other questions: https://stackoverflow.com/search?q=cannot+implicitly+convert

Categories

Resources