Having a slight c# problem here.
I'm currently coding a small platformer-game with Unity and I had some raycasts which checked collisions and such.
Now, I started to clean the code a bit, by storing the results of those raycasts into an integer array, but I'm getting a IndexOutOfRangeException.
I've tried to read through my code many times but can't seem to find what is causing the problem. If someone can help me out, I would be really glad.
Here's my code:
using UnityEngine;
using System.Collections;
public class PlayerRayCaster : MonoBehaviour {
public float playerHeight = 1;
public enum FeetState {Air, Ground};
public FeetState playerFeetState = FeetState.Air;
public int feetHitRays;
public int behindHitRay;
//Arrays of rays. value of 1 means that ray hits a target, 0 means that it does not hit.
public int[] sideRays; // [0-3] = Left side. [4-8] = Right side.
public int[] depthRays; // [0] = Away from camera. [1] = Towards camera.
public int[] feetRays;
public int counter;
void Start(){
sideRays = new int[8];
depthRays = new int[2];
feetRays = new int[3];
}
// Update is called once per frame
void Update () {
FeetRays();
SideRays();
BehindRay();
}
//Rays, which check if the character is bumping into an object, left or right.
void SideRays(){
float rayLength = 0.4f;
counter = 0;
//Left side rays.
for(int rayHeight = 0 ; rayHeight>=-4 ; rayHeight-=1 , counter++){
Debug.Log(sideRays[counter]);
if(Physics.Raycast(transform.position-new Vector3(0,rayHeight/2,0), new Vector3(-1,0,0),rayLength)){
sideRays[counter] = 1;
Debug.DrawRay(transform.position-new Vector3(0,rayHeight/2,0), new Vector3(-rayLength,0,0), Color.green);
}
else{
sideRays[counter] = 0;
Debug.DrawRay(transform.position-new Vector3(0,rayHeight/2,0), new Vector3(-rayLength,0,0), Color.yellow);
}
}
//Right side rays.
for(int rayHeight = 0;rayHeight>=-4;rayHeight-=1,counter++){
if(Physics.Raycast(transform.position-new Vector3(0,rayHeight/2,0), new Vector3(1,0,0),rayLength)){
sideRays[counter] = 1;
Debug.DrawRay(transform.position-new Vector3(0,rayHeight/2,0), new Vector3(rayLength,0,0), Color.green);
}
else{
sideRays[counter] = 0;
Debug.DrawRay(transform.position-new Vector3(0,rayHeight/2,0), new Vector3(rayLength,0,0), Color.yellow);
}
}
}
//Three rays, which check if the characters feet are on the ground or not.
void FeetRays(){
feetHitRays = 0;
float rayLength = 0.2f;
//Shoots three rays down from player.
for(float i=-0.7f;i<=0.7f;i+=0.7f){
if(Physics.Raycast(transform.position-new Vector3(i/2,0,0), new Vector3(0,-1,0),rayLength)){
feetHitRays++;
Debug.DrawRay(transform.position-new Vector3(i/2,0,0), new Vector3(0,-rayLength,0), Color.green);
}
else{
Debug.DrawRay(transform.position-new Vector3(i/2,0,0), new Vector3(0,-rayLength,0), Color.red);
}
}
//Sets the feet state.
if(feetHitRays==0)
{
playerFeetState = PlayerRayCaster.FeetState.Air;
}
else{
playerFeetState = PlayerRayCaster.FeetState.Ground;
}
}
//Shoots a raycast in z-direction from the character, to check for door access.
void BehindRay(){
behindHitRay = 0;
float rayLength = 2;
if(Physics.Raycast(transform.position, new Vector3(0,0,1), rayLength)){ //Away from camera
behindHitRay = 1;
Debug.DrawRay(transform.position, new Vector3(0,0,rayLength), Color.green);
}
if(Physics.Raycast(transform.position, new Vector3(0,0,-1), rayLength)){ // Towards camera.
behindHitRay = -1;
Debug.DrawRay(transform.position, new Vector3(0,0,-rayLength), Color.green);
}
}
}
This is the line that gives me the exception:
sideRays[counter] = 1;
Thanks in advance.
I believe this is the problem:
for(int rayHeight = 0 ; rayHeight>=-4 ; rayHeight-=1 , counter++)
You're basically doing that twice, and that means 10 iterations, whereas your array is initialized like this:
sideRays = new int[8];
You may well want:
// Note the > instead of >=
for (int rayHeight = 0; rayHeight > -4; rayHeight--, counter++)
(As an aside, I'd very strongly recommend that you don't use public fields, but that's a different matter.)
You declare sideRays with a size of 8, but it looks from a quick glance at your loops that counter can get as high as 10.
Check your bounds on for(int rayHeight = 0;rayHeight>=-4;rayHeight-=1,counter++){ You'll end up accessing the array 5 times for each loop and you've defined your array to have 8 items. Accessing 9 and 10 will throw an exception.
Related
I've created a procedural mesh script while watching one of Freya Holmér's improvised live course vods, and re purposed the code to create a procedural tube mesh with subdivision and plenty of other niche features.
But, after looking over the code and the lesson, I still cannot for the life of me figure out why sometimes I will get an:
argument out of range exception
...and sometimes I won't depending on the level of subdivision; also, entire faces wont be generated by the script.
TL;DR Problems list:
Argument out of range exception (Depending on level of subdivision).
Entire sides/faces of the tube mesh will not be generated, even when no errors are provided.
These problems are stemming from line 154 in the UpdateTris() method.
Code
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
using OpenNexus.ExtraGizmos;
#endif
using OpenNexus.BaseMath;
using OpenNexus.MeshFormat;
namespace OpenNexus.Procedurals
{
[RequireComponent(typeof(MeshFilter))]
public class TubeMesh : MonoBehaviour
{
private MeshFilter filter;
private Mesh mesh;
public List<Vector3> Points = new List<Vector3>()
{
new Vector3(0, 0, 0),
new Vector3(0, 1, 1),
new Vector3(0, 0, 2)
};
[Header("Bezier Data")]
public Precision BezierPrecision = Precision.Fast;
[Header("Tube Data")]
[Range(0.01f, 1f)]public float Radius = 0.01f;
[Range(3, 32)] public int Segments = 8;
[Range(3, 6)] public int Subdivisions = 3;
[Header("Mesh Data")]
public ProceduralMesh2D BaseProceduralMesh = new ProceduralMesh2D();
public List<Vector3> Vertices;
public List<int> Tris;
private void OnEnable()
{
if (!GetComponent<MeshRenderer>()) // Check for and add missing mesh renderer.
gameObject.AddComponent<MeshRenderer>();
if (filter == null) // Check for and assign mesh filter variable.
filter = GetComponent<MeshFilter>();
if (mesh == null) // Check for and instantiate a new mesh object.
mesh = new Mesh();
mesh.name = "TubeMesh"; // Set name to mesh object.
filter.sharedMesh = mesh; // Set MeshFilter's shared mesh variable to new mesh object.
}
private void Update()
{
/*
Data reset
------------------------------
*/
// Reset base mesh data.
BaseProceduralMesh.Vertices = new List<Vertex>();
BaseProceduralMesh.LineIndex = new List<int>();
// Reset mesh data.
Vertices = new List<Vector3>();
Tris = new List<int>();
/*
Data update
------------------------------
*/
// Update base mesh.
UpdateBaseMesh();
// Update mesh data.
UpdateVertices();
UpdateTris();
}
private void LateUpdate() => UpdateMesh();
private BezierPoint GetBezierPoint(int index)
{
float _t = index / (Segments - 1f);
BezierPoint _bp = BezierMath.QuadraticBezier(Points, BezierPrecision, _t);
return _bp;
}
private void UpdateBaseMesh()
{
// Generate base vertices.
for (int i = 0; i < Subdivisions; i++)
{
float _point = i / (float)Subdivisions;
float _radius = _point * Floats.TAU;
Vertex _vertex = new Vertex(VectorThrees.UnitVectorByAngle(_radius) * Radius);
BaseProceduralMesh.Vertices.Add(_vertex);
}
// Generate base LineIndexes.
for (int i = 0; i < BaseProceduralMesh.VertexCount; i++)
{
BaseProceduralMesh.LineIndex.Add(i);
}
BaseProceduralMesh.LineIndex.Add(0);
}
private void UpdateVertices()
{
for (int i = 0; i < Segments; i++)
{
BezierPoint _point = GetBezierPoint(i);
for (int j = 0; j < BaseProceduralMesh.VertexCount; j++)
{
Vertices.Add(_point.LocalToWorldPosition(BaseProceduralMesh.Vertices[j].Point));
}
}
}
private void UpdateTris()
{
for (int s = 0; s < Segments - 1; s++)
{
int _root = s * BaseProceduralMesh.VertexCount;
int _rootNext = (s + 1) * BaseProceduralMesh.VertexCount;
for (int i = 0; i < BaseProceduralMesh.EdgeCount; i+=2)
{
int _lineA = BaseProceduralMesh.LineIndex[i];
int _lineB = BaseProceduralMesh.LineIndex[i + 1];
int _currentA = _root + _lineA;
int _currentB = _root + _lineB;
int _nextA = _rootNext + _lineA;
int _nextB = _rootNext + _lineB;
Tris.Add(_currentA);
Tris.Add(_nextA);
Tris.Add(_nextB);
Tris.Add(_currentA);
Tris.Add(_nextB);
Tris.Add(_currentB);
}
}
}
private void UpdateMesh()
{
mesh.Clear();
mesh.SetVertices(Vertices);
mesh.SetTriangles(Tris, 0);
mesh.RecalculateNormals();
}
#if UNITY_EDITOR
private void OnDrawGizmos()
{
// Draw psudo mesh with gizmos.
/*
Draw segment/edge loops
-------------------------------------
*/
for (int i = 0; i < Segments; i++) // Debug each segment, and what their 2D mesh segment should look like.
{
BezierPoint _point = GetBezierPoint(i);
WireGizmos.DrawWireCircle(_point.Position, _point.Rotation, Radius, Subdivisions);
}
Gizmos.color = Color.red;
for (int i = 0; i < Vertices.Count; i++) // Debug each vertex.
{
Gizmos.DrawSphere(Vertices[i], 0.01f);
Handles.Label(Vertices[i], "\n\nVertex: " + i + "\n\nVertex position:\n" + Vertices[i].ToString());
}
for (int i = 0; i < Tris.Count; i++)
{
Gizmos.DrawLine(Vertices[Tris[i]], Vertices[Tris[(i + 1) % Tris.Count]]);
}
}
#endif
}
}
I've already looked over my code compared to the code in the video, it's fundamentally the same, with the main differences being, how I'm creating the 2D mesh format for the script to work with, and the structure of the code.
After looking back at what they had done compared to mine, I just don't see how I'm running into this issue.
Things I've tried
Change the loop iteration i+=2 -to- i++ (This spits out the exception, but generates the first section of the tube before getting stuck between the second vertex in the next segment, and vert 0).
Every suggestion I try from this question, I will update the "Things I've tried..." list.
Please let me know if I need to clarify anything in this post, and if you wish to see the other classes/structs referenced in this script.
After a day of resting, and the a couple of hours of testing different values and questioning the code. I've found the problem.
The real issue
The nested for loop in the UpdateTris() method was going up by twos assuming I was making a hard edge mesh with pared vertices. This caused the loop to skip over an entire face of the mesh, and causing the
ArgumentOutOfRangeException
...when the Subdivision value was an even number.
My solution
I had to bring it back to the default single iteration (since I was trying to make a smooth lighting mesh), the second issue with the for loop was the iteration limit BaseProceduralMesh.LineCount needing to be subtracted by one since that was causing another
ArgumentOutOfRangeException
I'm working on a unity project involving deformable terrain based on marching-cubes. It works by generating a map of density over the 3-dimensional coordinates of a terrain chunk and using that data to create a mesh representing the surface of the terrain. It has been working, however the process is very slow. I'm attempting to introduce multithreading to improve performance, but I've run into a problem that's left me scratching my head.
When I run CreateMeshData() and try to pass my density map terrainMap into the MarchCubeJob struct, it recognizes it as a reference type, not a value type. I've seemed to whittle down the errors to this one, but I've tried to introduce the data in every way I know how and I'm stumped. I thought passing a reference like this was supposed to create a copy of the data disconnected from the reference, but my understanding must be flawed. My goal is to pass each marchingcube cube into a job and have them run concurrently.
I'm brand new to multithreading, so I've probably made some newbie mistakes here and I'd appreciate if someone would help me out with a second look. Cheers!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Jobs;
using Unity.Collections;
using Unity.Burst;
public class Chunk
{
List<Vector3> vertices = new List<Vector3>();
List<int> triangles = new List<int>();
public GameObject chunkObject;
MeshFilter meshFilter;
MeshCollider meshCollider;
MeshRenderer meshRenderer;
Vector3Int chunkPosition;
public float[,,] terrainMap;
// Job system
NativeList<Vector3> marchVerts;
NativeList<Vector3> marchTris;
MarchCubeJob instanceMarchCube;
JobHandle instanceJobHandle;
int width { get { return Terrain_Data.chunkWidth;}}
int height { get { return Terrain_Data.chunkHeight;}}
static float terrainSurface { get { return Terrain_Data.terrainSurface;}}
public Chunk (Vector3Int _position){ // Constructor
chunkObject = new GameObject();
chunkObject.name = string.Format("Chunk x{0}, y{1}, z{2}", _position.x, _position.y, _position.z);
chunkPosition = _position;
chunkObject.transform.position = chunkPosition;
meshRenderer = chunkObject.AddComponent<MeshRenderer>();
meshFilter = chunkObject.AddComponent<MeshFilter>();
meshCollider = chunkObject.AddComponent<MeshCollider>();
chunkObject.transform.tag = "Terrain";
terrainMap = new float[width + 1, height + 1, width + 1]; // Weight of each point
meshRenderer.material = Resources.Load<Material>("Materials/Terrain");
// Generate chunk
PopulateTerrainMap();
CreateMeshData();
}
void PopulateTerrainMap(){
...
}
void CreateMeshData(){
ClearMeshData();
vertices = new List<Vector3>();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
for (int z = 0; z < width; z++) {
Debug.Log(x + ", " + y + ", " + z + ", begin");
Vector3Int position = new Vector3Int(x, y, z);
// Set up memory pointers
NativeList<Vector3> marchVerts = new NativeList<Vector3>(Allocator.TempJob);
NativeList<int> marchTris = new NativeList<int>(Allocator.TempJob);
NativeList<float> mapSample = new NativeList<float>(Allocator.TempJob);
// Split marchcube into jobs by cube
instanceMarchCube = new MarchCubeJob(){
position = position,
marchVerts = marchVerts,
marchTris = marchTris,
mapSample = terrainMap
};
// Run job for each cube in a chunk
instanceJobHandle = instanceMarchCube.Schedule();
instanceJobHandle.Complete();
// Copy data from job to mesh data
//instanceMarchCube.marchVerts.CopyTo(vertices);
vertices.AddRange(marchVerts);
triangles.AddRange(marchTris);
// Dispose of memory pointers
marchVerts.Dispose();
marchTris.Dispose();
mapSample.Dispose();
Debug.Log(x + ", " + y + ", " + z + ", end");
}
}
}
BuildMesh();
}
public void PlaceTerrain (Vector3 pos, int radius, float speed){
...
CreateMeshData();
}
public void RemoveTerrain (Vector3 pos, int radius, float speed){
...
CreateMeshData();
}
void ClearMeshData(){
vertices.Clear();
triangles.Clear();
}
void BuildMesh(){
Mesh mesh = new Mesh();
mesh.vertices = vertices.ToArray();
mesh.triangles = triangles.ToArray();
mesh.RecalculateNormals();
meshFilter.mesh = mesh;
meshCollider.sharedMesh = mesh;
}
private void OnDestroy(){
marchVerts.Dispose();
marchTris.Dispose();
}
}
// Build a cube as a job
[BurstCompile]
public struct MarchCubeJob: IJob{
static float terrainSurface { get { return Terrain_Data.terrainSurface;}}
public Vector3Int position;
public NativeList<Vector3> marchVerts;
public NativeList<int> marchTris;
public float[,,] mapSample;
public void Execute(){
//Sample terrain values at each corner of cube
float[] cube = new float[8];
for (int i = 0; i < 8; i++){
cube[i] = SampleTerrain(position + Terrain_Data.CornerTable[i]);
}
int configIndex = GetCubeConfiguration(cube);
// If done (-1 means there are no more vertices)
if (configIndex == 0 || configIndex == 255){
return;
}
int edgeIndex = 0;
for (int i = 0; i < 5; i++){ // Triangles
for (int p = 0; p < 3; p++){ // Tri Vertices
int indice = Terrain_Data.TriangleTable[configIndex, edgeIndex];
if (indice == -1){
return;
}
// Get 2 points of edge
Vector3 vert1 = position + Terrain_Data.CornerTable[Terrain_Data.EdgeIndexes[indice, 0]];
Vector3 vert2 = position + Terrain_Data.CornerTable[Terrain_Data.EdgeIndexes[indice, 1]];
Vector3 vertPosition;
// Smooth terrain
// Sample terrain values at either end of current edge
float vert1Sample = cube[Terrain_Data.EdgeIndexes[indice, 0]];
float vert2Sample = cube[Terrain_Data.EdgeIndexes[indice, 1]];
// Calculate difference between terrain values
float difference = vert2Sample - vert1Sample;
if (difference == 0){
difference = terrainSurface;
}
else{
difference = (terrainSurface - vert1Sample) / difference;
}
vertPosition = vert1 + ((vert2 - vert1) * difference);
marchVerts.Add(vertPosition);
marchTris.Add(marchVerts.Length - 1);
edgeIndex++;
}
}
}
static int GetCubeConfiguration(float[] cube){
int configurationIndex = 0;
for (int i = 0; i < 8; i++){
if (cube[i] > terrainSurface){
configurationIndex |= 1 << i;
}
}
return configurationIndex;
}
public float SampleTerrain(Vector3Int point){
return mapSample[point.x, point.y, point.z];
}
}
If the grid is 10x10 or 23x7 it's working fine but when the grid have 1.5 spaces between the cubes the directions sometimes are wrong.
This is the grid script:
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 GameObject[] allBlocks;
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();
allBlocks = GameObject.FindGameObjectsWithTag("Blocks");
var findpath = GetComponent<PathFinder>();
findpath.FindPath();
}
public void AutoGenerateGrid()
{
allBlocks = GameObject.FindGameObjectsWithTag("Blocks");
for (int i = 0; i < allBlocks.Length; i++)
{
DestroyImmediate(allBlocks[i]);
}
var end = GameObject.FindGameObjectWithTag("End");
DestroyImmediate(end);
GenerateGrid();
allBlocks = GameObject.FindGameObjectsWithTag("Blocks");
var findpath = GetComponent<PathFinder>();
findpath.FindPath();
}
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.name = "Block";
block.transform.tag = "Blocks";
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
{
block.transform.parent = wallsParents[0].transform;
block.transform.name = "TopWall";
block.transform.tag = "Blocks";
}
else if (z == 0)//LEFT
{
block.transform.parent = wallsParents[1].transform;
block.transform.name = "LeftWall";
block.transform.tag = "Blocks";
}
else if (z == gridHeight - 1)//RIGHT
{
block.transform.parent = wallsParents[2].transform;
block.transform.name = "RightWall";
block.transform.tag = "Blocks";
}
else if (x == gridWidth - 1)//BOTTOM
{
block.transform.parent = wallsParents[3].transform;
block.transform.name = "BottomWall";
block.transform.tag = "Blocks";
}
}
}
}
}
On this line i'm adding the spaces between the cubes:
block.transform.localPosition = new Vector3(x * 1.5f, 0, z * 1.5f);
Then in another script i'm trying to find what directions next are possible to move to.
private void Directions()
{
GridGenerator gridgenerator = GetComponent<GridGenerator>();
Vector3 playerPosition;
playerPosition = player.localPosition;
if (playerPosition.x > 0)
{
// can go left
possibleDirections[0] = "Can go left";
}
else
{
possibleDirections[0] = "Can't go left";
}
if (playerPosition.x + 1 < gridgenerator.gridWidth * 1.5f)
{
// can go right
possibleDirections[1] = "Can go right";
}
else
{
possibleDirections[1] = "Can't go right";
}
if (playerPosition.z > 0)
{
// can go backward
possibleDirections[2] = "Can go backward";
}
else
{
possibleDirections[2] = "Can't go backward";
}
if (playerPosition.z + 1 < gridgenerator.gridHeight * 1.5f)
{
// can go backward
possibleDirections[3] = "Can go forward";
}
else
{
possibleDirections[3] = "Can't go forward";
}
}
possibleDirections is array string type
When the grid size is 10x10 without spaces between cubes this two lines:
if (playerPosition.x + 1 < gridgenerator.gridWidth * 1.5f)
if (playerPosition.z + 1 < gridgenerator.gridHeight * 1.5f)
Was:
if (playerPosition.x + 1 < gridgenerator.gridWidth)
if (playerPosition.z + 1 < gridgenerator.gridHeight)
But when i added the spaces between the cubes i tried to add to the gridgenerator.gridWidth and gridgenerator.gridHeight the * 1.5
But it didn't work so i tried also:
if (playerPosition.x + 1 < gridgenerator.gridWidth * (1 + 1.5))
if (playerPosition.z + 1 < gridgenerator.gridHeight * (1 + 1.5))
1 is the cube width and 1.5 is the space. But this is not working good either.
In the screenshot the player is in the top left corner facing up(forward)
He can't move forward but in the inspector it says "Can go forward" And should be "Can't go forward"
It only happens when there are spaces between the cubes.
This line is wrong:
if (playerPosition.x + 1 < gridgenerator.gridWidth * 1.5f)
Your gridWidth variable stores the number of cubes, not their collective spacing. You have 10 cubes representing move spaces, determining the out-of-bounds this value should remain constant (it's still only 10 cubes, even if they're spaced with a half-block worth of space between them).
You need to convert from the player's scene location (transform.position.x) to a board space location (likely dividing by the same multiplier used to space the cubes out).
Alternatively, the "this makes my soul cry" solution of doing this:
if (playerPosition.x + 1.5f < gridgenerator.gridWidth * 1.5f)
Because the next cube is 1.5 scene units away, not 1. And this makes my soul cry because it makes your code full of hard-coded 1.5f multipliers and offsets rather than keeping such things to a single, fixed, constant value stored Elsewhere and used sparingly.
Related:
possibleDirections[0] = "Can go left";
Why are you using stringly typed things? There are values called booleans for a reason...
Below is a few simple lines of code that is part of uni tech demo. In an attempt to create a 3D grid of vectors within a given area.
My solution thus far is to create a 2D grid at the starting X and Y points and then repeat this process along the Z.
As a temporary visualization I then instantiate Sphere prefabs.
The purpose of which is to use this grid of vectors as a model for a depth first search path algorithm which I will use to input vectors for a procedurally generated track(currently control points are set manually via editor methods)
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class GridLayout : MonoBehaviour {
public int GridWidth;
public int GridLength;
public int GridHeight;
public int resolution;
private int ResW;
private int ResL;
private int ResH;
private List<Vector3> GridPoints = new List<Vector3>();
private bool GridCompleted = false;
private GameObject tempObject;
// Use this for initialization
void Start () {
//Area box Start square
GridPoints.Add(new Vector3(0,0,0));
GridPoints.Add(new Vector3(0,GridHeight,0));
GridPoints.Add(new Vector3(GridWidth,0,0));
GridPoints.Add(new Vector3(GridWidth,GridHeight,0));
ResW = GridWidth/resolution;
ResH = GridHeight/resolution;
ResL = GridLength/resolution;
}
// Update is called once per frame
void Update () {
if (GridCompleted == false)
CreateGrid();
else
{
for(int i = 0; i <= GridPoints.Count; i++)
{
tempObject = GameObject.CreatePrimitive(PrimitiveType.Sphere);
tempObject.transform.position = GridPoints[i];
}
}
} //Area Box End square
// GridPoints.Add(new Vector3(0,0,GridLength));
// GridPoints.Add(new Vector3(0,GridHeight,GridLength));
// GridPoints.Add(new Vector3(GridWidth,0,GridLength));
// GridPoints.Add(new Vector3(GridWidth,GridHeight,GridLength));
void CreateGrid()
{
if(ResW != GridWidth | ResL != GridLength | ResH != GridHeight)
{
for(int l = 1;ResL <= GridLength; l++)
{
GridPoints.Add (new Vector3(0,0,ResL));
ResL = (GridLength/(resolution))*l;
for(int w = 1;ResW <= GridWidth; w++)
{
GridPoints.Add (new Vector3(ResW,0,0));
ResW = (GridWidth/(resolution))*w;
for(int h = 1;ResW <= GridHeight; h++)
{
GridPoints.Add (new Vector3(0,ResH,0));
ResH = (GridHeight/(resolution))*h;
}
}
}
}
else
{
GridCompleted = true;
}
}
}
Unfortunately this triple for loop leads to a memory exception - this is a high end PC however I will be forced to run my project on a laptop with 4GB ram.
With that in mind : is there a more memory efficient way of creating a vector3 grid.
Thanks in advance.
Typing failure in line
for(int h = 1;ResW <= GridHeight; h++)
Is causing your memory problems. The most inner loop runs infinitely, it should be ResH. Therefore I suggest to check the for-variable inside the for-statement and not something else:
for(int h = 1; h < wharever; h++)
secondly: bad code formatting and indentation.
Finally, so far, a list<object> is a 1D structure. A 3rd structure would be a list<list<list<object>>> or a array object [][][]:
Vector3 [][][] vector3grid;
vector3grid = new vector3[lenX][][];
for (int x=0; x<lenX; x++)
{
vector3grid[x] = new vector3 [lenY][];
for (int y=0; y<lenY; y++)
{
vector3grid[x][y] = new vector3 [lenZ];
// init if needed:
for(int z=0; ...
vector3grid[x][y][z] = ...
}
}
Edit:
I just noticed that my answer is not 100% correct. The sample above is 1 of 2 (or more) ways to create a 3D array. The easier one of them is following:
In C++/cli:
Array<vector3, 3>^ vector3grid = gcnew array<vector3, 3>(lenX, lenY, lenZ);
For c# and VB.net I need to look up the Syntax first.
This is a REAL 3D array now. ;-)
Edit 2:
3D in c#:
Vector3 [,,] vector3grid = New vector3[lenX,lenY,lenZ];
i'm making my first game on XNA for my class. I'm trying to make the monsters move left and right automatically. I have total 4 monsters for now. I'm trying to get them move left then right within the screen.
//Monster movements
for (int i = 0; i < numOfMonster; i++)
{
if (destinationMonster[i].X >= screenWidth - 60)
{
while(destinationMonster[i].X != -10)
moveLeft = true;
}
else
{
moveRight = true;
}
if (moveLeft)
{
int temp = destinationMonster[i].X;
temp = destinationMonster[i].X - monsterSpeed;
//This prevents the object passing the screen boundary
if (!(temp < -10))
{
destinationMonster[i].X = temp;
}
moveLeft = false;
}
if (moveRight)
{
int temp = destinationMonster[i].X;
temp = destinationMonster[i].X + monsterSpeed;
//This prevents the object passing the screen boundary
if (!(temp > screenWidth - 50))
{
destinationMonster[i].X = temp;
}
moveRight = false;
}
}
Your first problem is your while statement, once you enter it you are not going to exit because you are not changing your X value. If it were me I would have a bool array variable corresponding to each of your monsters. I would also change your conditional to trigger the change of the boolean value once the monster has reached the extents at either end. Something like this.
if (destinationMonster[i].X >= screenWidth - 60)
{
moveRight[i] = false ;
}
else if (destinationMonster[i].X <= -10)
{
moveRight[i] = true ;
}