- Home /
The question is answered, right answer was accepted
Out of memory during play
Hi guys! I've been serching for answer but didn't find it. I'm making match3 game with tutorial, but i stuck after part where pieces in game should pop if they make a row. When i launch play, it's all okay but once i press mouse button on piece or trying to move it, it freeze, starting eating PC memmory untill it get to the limit and then it unfreeze and show an error:
OutOfMemoryException:Out of memory
System.Array.Resize[BGamePiece] (.BGamePiece[]& array, Int32 length, Int32 newSize) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System/Array.cs:1929)
System.Array.Resize[BGamePiece] (.BGamePiece[]& array, Int32 newSize) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System/Array.cs:1913)
System.Collections.Generic.List`1[BGamePiece].set_Capacity (Int32 value) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Collections.Generic/List.cs:622)
System.Collections.Generic.List`1[BGamePiece].GrowIfNeeded (Int32 newCount) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Collections.Generic/List.cs:100)
System.Collections.Generic.List`1[BGamePiece].Add (.BGamePiece item) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Collections.Generic/List.cs:91)
GridNet.GetMatch (.BGamePiece piece, Int32 newX, Int32 newY) (at Assets/Scripts/GridNet.cs:393)
GridNet.ClearAllValidMatches () (at Assets/Scripts/GridNet.cs:426)
GridNet+<Fill>c__Iterator2.MoveNext () (at Assets/Scripts/GridNet.cs:104)
It's pretty standart mechanics for match 3 game.I will show all parts of code that is shown in error, if will be needed something else please just ask me, im first time making question so i need practise :) Thanks!
Line 104
public IEnumerator Fill()
{
bool needsRefill = true;
while (needsRefill){
yield return new WaitForSeconds (fillTime);
while (FillStep ()) {
inverse = !inverse;
yield return new WaitForSeconds (fillTime);
}
needsRefill = ClearAllValidMatches ();
}
}
Line 393
if (verticalPieces.Count >= 3) {
for (int i = 0; i < verticalPieces.Count; i++) {
for (int dir = 0; dir <= 1; dir++) {
for (int x0ffset = 1; x0ffset < xDim; x0ffset++) {
int x;
if (dir == 0) { //left
x = newX - x0ffset;
} else { //right
x = newX + x0ffset;
}
if (x < 0 || x >= xDim) {
break;
}
if (pieces [x, verticalPieces[i].Y].IsColored () && pieces [x, verticalPieces[i].Y].ColorComponent.Color == color) {
verticalPieces.Add (pieces [x, verticalPieces [i].Y]);
} else {
break;
}
}
}
Line 426
public bool ClearAllValidMatches()
{
bool needsRefill = false;
for (int y = 0; y < yDim; y++) {
for (int x = 0; x < xDim; x++) {
if (pieces [x, y].IsClearable ()) {
List<BGamePiece> match = GetMatch (pieces [x, y], x, y);
if (match != null) {
for (int i = 0; i < match.Count; i++) {
if (ClearPiece (match [i].X, match [i].Y)) {
needsRefill = true;
}
}
}
}
}
}
return needsRefill;
}
Getmach
public List<BGamePiece> GetMatch(BGamePiece piece, int newX, int newY)
{
if (piece.IsColored ()) {
BColorPiece.Colortype color = piece.ColorComponent.Color;
List<BGamePiece> horizontalPieces = new List<BGamePiece> ();
List<BGamePiece> verticalPieces = new List<BGamePiece> ();
List<BGamePiece> matchingPieces = new List<BGamePiece> ();
//first check horizontal
horizontalPieces.Add (piece);
for (int dir = 0; dir <= 1; dir++) {
for (int x0ffset = 1; x0ffset < xDim; x0ffset++) {
int x;
if (dir == 0) {//left
x = newX - x0ffset;
} else {//right
x = newX + x0ffset;
}
if (x < 0 || x >= xDim) {
break;
}
if (pieces [x, newY].IsColored () && pieces [x, newY].ColorComponent.Color == color) {
horizontalPieces.Add (pieces [x, newY]);
} else {
break;
}
}
}
if (horizontalPieces.Count >= 3) {
for (int i = 0; i < horizontalPieces.Count; i++) {
matchingPieces.Add (horizontalPieces [i]);
}
}
//traverse vertically if we found a match (for L and T shape)
if (horizontalPieces.Count >= 3) {
for (int i = 0; i < horizontalPieces.Count; i++) {
for (int dir = 0; dir <= 1; dir++) {
for (int y0ffset = 1; y0ffset < yDim; y0ffset++) {
int y;
if (dir == 0) { //up
y = newY - y0ffset;
} else { //down
y = newY + y0ffset;
}
if (y < 0 || y >= yDim) {
break;
}
if (pieces [horizontalPieces [i].X, y].IsColored () && pieces [horizontalPieces [i].X, y].ColorComponent.Color == color) {
verticalPieces.Add (pieces [horizontalPieces [i].X, y]);
} else {
break;
}
}
}
if (verticalPieces.Count < 2) {
verticalPieces.Clear ();
} else {
for (int j = 0; j < verticalPieces.Count; j++) {
matchingPieces.Add (verticalPieces [j]);
}
break;
}
}
}
if (matchingPieces.Count >= 3) {
return matchingPieces;
}
//didn't find anything going horizontally first
//so now check vertically
horizontalPieces.Clear();
verticalPieces.Clear();
verticalPieces.Add (piece);
for (int dir = 0; dir <= 1; dir++) {
for (int y0ffset = 1; y0ffset < yDim; y0ffset++) {
int y;
if (dir == 0) {
y = newX - y0ffset;
} else {
y = newX + y0ffset;
}
if (y < 0 || y >= yDim) {
break;
}
if (pieces [newX, y].IsColored () && pieces [newX, y].ColorComponent.Color == color) {
verticalPieces.Add (pieces [newX, y]);
} else {
break;
}
}
}
if (verticalPieces.Count >= 3) {
for (int i = 0; i < verticalPieces.Count; i++) {
matchingPieces.Add (verticalPieces [i]);
}
}
// traverse horizontally if we found a match (for L and T shape)
if (verticalPieces.Count >= 3) {
for (int i = 0; i < verticalPieces.Count; i++) {
for (int dir = 0; dir <= 1; dir++) {
for (int x0ffset = 1; x0ffset < xDim; x0ffset++) {
int x;
if (dir == 0) { //left
x = newX - x0ffset;
} else { //right
x = newX + x0ffset;
}
if (x < 0 || x >= xDim) {
break;
}
if (pieces [x, verticalPieces[i].Y].IsColored () && pieces [x, verticalPieces[i].Y].ColorComponent.Color == color) {
verticalPieces.Add (pieces [x, verticalPieces [i].Y]);
} else {
break;
}
}
}
if (horizontalPieces.Count < 2) {
horizontalPieces.Clear ();
} else {
for (int j = 0; j < horizontalPieces.Count; j++) {
matchingPieces.Add (horizontalPieces [j]);
}
break;
}
}
}
if (matchingPieces.Count >= 3) {
return matchingPieces;
}
}
return null;
}
ClearPiece
public bool ClearPiece(int x, int y)
{
if (pieces [x, y].IsClearable() && !pieces [x, y].ClearableComponent.IsBeingCleared) {
pieces [x, y].ClearableComponent.Clear ();
SpawnNewPiece (x, y, PieceType.EMPTY);
//Clear0bstacles (x, y);
return true;
}
return false;
}
FillStep
public bool FillStep()
{
bool movedPiece = false;
for (int y = yDim - 2; y >= 0; y--) {
for (int loopX = 0; loopX < xDim; loopX++) {
int x = loopX;
if(inverse)
{
x = xDim - 1 - loopX;
}
BGamePiece piece = pieces [x, y];
if (piece.isMoveable ()) {
BGamePiece pieceBelow = pieces [x, y + 1];
if (pieceBelow.Type == PieceType.EMPTY) {
Destroy (pieceBelow.gameObject);
piece.MoveableComponent.Move (x, y + 1, fillTime);
pieces [x, y + 1] = piece;
SpawnNewPiece (x, y, PieceType.EMPTY);
movedPiece = true;
} else {
for (int diag = -1; diag <= 1; diag++) {
if (diag != 0) {
int diagX = x + diag;
if (inverse) {
diagX = x - diag;
}
if (diagX >= 0 && diagX < xDim) {
BGamePiece diagonalPiece = pieces [diagX, y + 1];
if (diagonalPiece.Type == PieceType.EMPTY) {
bool hasPieceAbove = true;
for (int aboveY = y; aboveY >= 0; aboveY--) {
BGamePiece pieceAbove = pieces [diagX, aboveY];
if (pieceAbove.isMoveable ()) {
break;
} else if (!pieceAbove.isMoveable () && pieceAbove.Type != PieceType.EMPTY) {
hasPieceAbove = false;
break;
}
}
if (!hasPieceAbove) {
Destroy (diagonalPiece.gameObject);
piece.MoveableComponent.Move (diagX, y + 1, fillTime);
pieces [diagX, y + 1] = piece;
SpawnNewPiece (x, y, PieceType.EMPTY);
movedPiece = true;
break;
}
}
}
}
}
}
}
}
}
for (int x = 0; x < xDim; x++) {
BGamePiece pieceBelow = pieces [x, 0];
if (pieceBelow.Type == PieceType.EMPTY) {
Destroy (pieceBelow.gameObject);
GameObject newPiece = (GameObject)Instantiate (piecePrefabDict [PieceType.NORMAL], GetWorldPosition (x, -1), Quaternion.identity);
newPiece.transform.parent = transform;
pieces [x, 0] = newPiece.GetComponent<BGamePiece> ();
pieces [x, 0].Init (x, -1, this, PieceType.NORMAL);
pieces [x, 0].MoveableComponent.Move (x, 0,fillTime);
pieces [x, 0].ColorComponent.SetColor ((BColorPiece.Colortype)Random.Range (0, pieces [x, 0].ColorComponent.NumColors));
movedPiece = true;
}
}
return movedPiece;
}
You have some sort of loop going on that isn't ending when you expect.
How are you starting the Fill
coroutine?
We need to see the entire Get$$anonymous$$atch
and ClearPiece
and FillStep
methods. Are any of those calling ClearAllValid$$anonymous$$atches
? Is FillStep
ever returning false? If not then you have an infinite loop there.
What is the value of fillTime
?
I added Get$$anonymous$$atch, ClearPiece and FillStep. FillTime is 0.1 sec
Just checked and didn't find any line of code that making FillStep false
this is how Fill starts
public void SwapPieces(BGamePiece piece1, BGamePiece piece2)
{
if (piece1.is$$anonymous$$oveable () && piece2.is$$anonymous$$oveable ()) {
pieces [piece1.X, piece1.Y] = piece2;
pieces [piece2.X, piece2.Y] = piece1;
if (Get$$anonymous$$atch (piece1, piece2.X, piece2.Y) != null || Get$$anonymous$$atch (piece2, piece1.X, piece1.Y) != null) {
int piece1X = piece1.X;
int piece1Y = piece1.Y;
piece1.$$anonymous$$oveableComponent.$$anonymous$$ove (piece2.X, piece2.Y, fillTime);
piece2.$$anonymous$$oveableComponent.$$anonymous$$ove (piece1X, piece1Y, fillTime);
ClearAllValid$$anonymous$$atches ();
StartCoroutine (Fill ());
} else {
pieces [piece1.X, piece1.Y] = piece1;
pieces [piece2.X, piece2.Y] = piece1;
}
}
}
System.Collections.Generic.List`1[BGamePiece].Add (.BGamePiece item) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Collections.Generic/List.cs:91) GridNet.Get$$anonymous$$atch (.BGamePiece piece, Int32 newX, Int32 newY) (at Assets/Scripts/GridNet.cs:393) GridNet.ClearAllValid$$anonymous$$atches () (at Assets/Scripts/GridNet.cs:426)
This part of the log is showing that ClearAllValid$$anonymous$$atches calls Get$$anonymous$$atch, which calls List.Add, which is causing the out of memory error. This indicates that one of those methods is being called over and over in some sort of loop. So either something is calling ClearAllValid$$anonymous$$atches over and over, or something inside of that is calling Get$$anonymous$$atch over and over.
You have a lot of loops within loops and such and it's possible one of those is causing problems. It's also possible that something is calling SwapPieces over and over which is starting your Coroutine multiple times which is doing a lot of list adding.
Are you calling SwapPieces from Update or something?
These sorts of things can be difficult to debug. One technique is to add Debug.Log calls so you can see the program flow (although that can be problematic if you're dealing with a loop). Another technique is to start removing pieces from the inside out until the problem stops happening.
okay dude, thanks, i got an idea now, i'll try to fix it and let you know.
// traverse horizontally if we found a match (for L and T shape)
if (verticalPieces.Count >= 3) {
for (int i = 0; i < verticalPieces.Count; i++) {
for (int dir = 0; dir <= 1; dir++) {
for (int x0ffset = 1; x0ffset < xDim; x0ffset++) {
int x;
if (dir == 0) { //left
x = newX - x0ffset;
} else { //right
x = newX + x0ffset;
}
if (x < 0 || x >= xDim) {
break;
}
/*if (pieces [x, verticalPieces[i].Y].IsColored () && pieces [x, verticalPieces[i].Y].ColorComponent.Color == color) {
verticalPieces.Add (pieces [x, verticalPieces [i].Y]);
Debug.Log ("This line is causing $$anonymous$$emmory error");
} else {
break;
}*/
}
}
if (horizontalPieces.Count < 2) {
horizontalPieces.Clear ();
} else {
for (int j = 0; j < horizontalPieces.Count; j++) {
matchingPieces.Add (horizontalPieces [j]);
Debug.Log ("Added Horizontally L,T");
}
break;
}
}
}
if (matchingPieces.Count >= 3) {
return matchingPieces;
}
}
return null;
}
this part of code been causing freeze and memory overload (I think so) i commented this part of code and it stops freezing now, but still it acts strange and i can't find out why it been causing memmory error. Looks like FillStep looping infinetly but works good and most vicious part it getmatch and maybe something wrong in SwapPieces, i keep working on debugging it.
Thanks for answers dude, you helped us to find an error. We found few mistakes in code, so that was totally our mistake, but still you helped to find it :)
Follow this Question
Related Questions
Is there a better way to tell when enemies are dead? 2 Answers
Multiple Cars not working 1 Answer
Unity|C#| Card Game: How to draw a card for each 0.5 secs? 2 Answers
Distribute terrain in zones 3 Answers