assigning a property from an object in a list to a variable

Started by
71 comments, last by ethancodes 5 years, 11 months ago

I fixed it! It was just a stupid mistake. I had + and - 11 and not 1 when I was trying to check the bricks to the left and the right. it works perfectly now. Thanks so much Scouting Ninja for all of your help!

Advertisement

So this grid works great so far, but I'm trying to figure out the best way to get the most use out of it. For instance, I am making a brick that explodes, destroying all adjacent bricks (top, bottom, left, right, and diagonal bricks as well). I need to know if I can use the grid system for this, and if so, how exactly would I implement that? The class for the Exploding Brick is attached to the individual brick, if that matters. 

 

For further reference, here is the method that currently checks the top, below, left, and right bricks of a particular selection. How to enhance this to check the diagonal bricks as well, but only do this when the method is invoked by the ExplosiveBricks class, I have no idea.


void CheckBorders (GridSquare currentPosition)
		{
			gridOptions.Clear (); //empty gridOptions list

			if (currentPosition.GridPosition.x != 0) { //check to make sure we are not on column 1, if not, check 1 column to the left. If available, set to gridOptions list
				tempPosition = gridPositions[(int)currentPosition.GridPosition.x - 1, (int)currentPosition.GridPosition.y];

				if (tempPosition.IsVisible == true) {
					gridOptions.Add (tempPosition);
				}
			}

			if (currentPosition.GridPosition.x != 19) { //check to make sure we are not on column 19, if not, check 1 column to the right. If available, set to gridOptions list
				tempPosition = gridPositions[(int)currentPosition.GridPosition.x + 1, (int)currentPosition.GridPosition.y];

				if (tempPosition.IsVisible == true) {
					gridOptions.Add (tempPosition);
				}
			}

			if (currentPosition.GridPosition.y != 16) { //check to make sure we are not on row 18, if not, check 1 row under. If available, set to gridOptions list
				tempPosition = gridPositions[(int)currentPosition.GridPosition.x, (int)currentPosition.GridPosition.y - 1];

				if (tempPosition.IsVisible == true) {
					gridOptions.Add (tempPosition);
				}
			}

			if (currentPosition.GridPosition.y != 22) { //check to make sure we are not on row 30, if not, check 1 row up. If available, set to gridOptions list
				tempPosition = gridPositions[(int)currentPosition.GridPosition.x, (int)currentPosition.GridPosition.y + 1];

				if (tempPosition.IsVisible == true) {
					gridOptions.Add (tempPosition);
				}
			}
		}

 

13 minutes ago, ethancodes said:

I need to know if I can use the grid system for this, and if so, how exactly would I implement that?

With 2D arrays you just check the index to do this type of thing.

2DArrayBomb.jpg.a2d9adb5fd98100e50835f6d8d107342.jpg

With a single array this is more difficult because you would need to run checks for all indexes after the exploding. The best would be to draw an example and from that calculate what the formula will be:

1DArrayBomb.jpg.1db991ecdf549f7b1c08e59a3e1db1c1.jpg

You will need to check how far in the X row the block is then check that the explosion only explodes blocks in the same row.

But how do I call the methods from the ExplosiveBrick class? Do I just make another instance of the BoardManager in that class? Like this:


public BoardManager boardScript;

boardScript = GetComponent<BoardManager>();

Or is there a different way to do this? I feel like this is not the right thing to do because there should only be one instance of the BoardManager right? Unless this is just a reference to the one instance? 

22 hours ago, ethancodes said:

But how do I call the methods from the ExplosiveBrick class? Do I just make another instance of the BoardManager in that class?

Unity makes a instance as the component when a script is attached to an object.

This is how class methods is called normally in c# :

Spoiler

To call something from a class



public class MyClass{
  public int Health = 100;
  
  public SubtractHealth(int InAmount)
  {
    Health -= InAmount;
  }
}

//To use it we do this:
MyClass Player1 = new MyClass();

Player1.SubtractHealth(10); //This reduces Player1 health by 10


 

In Unity we can use a Unity GameObject to find the script attached like this:


//Special thing about the Unity script is that it is a inheritance
//of the Unity MonoBehaviour

public class MyClass : MonoBehaviour{
  public int Health = 100;
  
  public SubtractHealth(int InAmount)//Must be public
  {
    Health -= InAmount;
  }
}

//To use this from a other script we do this:
public class MySecondClass : MonoBehaviour{
  //To call a script from a object you need a way to
  //find the object.
  GameObject TargetObject;
  
  void Start(){
    //Unity script components have the same name as 
    //the file name and class name; "MyClass" here
    TargetObject.GetComponent<MyClass>().SubtractHealth(10);
  }
}

What "GetComponent<Name>()" does is check if that class is attached to a Unity object. "Components" are just class instances inside a array inside of the object class.

So, I don't think I'm utilizing the grid correctly. I don't believe I'm moving them through the grid when I move the bricks. I think I spawn the bricks and then move them through the game space, but don't actually move their positions in the grid, so I either need to fix how I move the bricks, or change how I detect adjacent bricks. I think it would be smart to utilize the grid correctly, though I'm unsure of how to do that. This is how I'm moving the bricks currently:

 


private float delay = 1.5f;                //Delay till bricks move down 1 row.
private float timer = 0;				  // update ever frame and compare to delay. 


// Update is called once per frame
	void Update ()
	{
		timer += Time.deltaTime;
		//timer determines when the brick will move
		if (timer >= delay) 
		{
			transform.Translate(0.0f, -1.0f,0.0f);
			timer = 0;
		}
	}

 

23 minutes ago, ethancodes said:

I think I spawn the bricks and then move them through the game space, but don't actually move their positions in the grid

This is fine, the only thing the grid needs is to tell you the relative positions of and object.

For example if you want to find the object to the right you check index+1; instead of looking for it's world position. That way objects can quickly find a other object relative to it's own position.

1DArrayBomb.jpg.1db991ecdf549f7b1c08e59a3e1db1c1.jpg

As shown in this image the only thing that matters is that there must be some way of finding the objects relative to each other. If we looked for an object above 6 we know it is object 1.

RandomList.jpg.04190eca5ddf0903c2fda332e3112a1d.jpg

If the list was random like this, where the object above 6 could be any number we would need to check each item in the list to find the one above 6. This makes it much slower than the collision system already in use by Unity.

We could then save a lot of time by using the position of 6 and ray casting above it, to see what object is in that space; instead of checking each item in a list.

 

Collision systems in the engine is a list of objects, it's optimized to be fast as possible so it can produce good results. Using the collision system to find a object is faster than checking each objects position. To understand why read about Octrees.

The whole point of a grid system is to make a even faster collision system. The goal is to keep objects relative or to move them in the grid system. If you don't then your grid system is slower than the collision system that Unity has.

 

Oh my gosh of course! I can't believe I didn't realize that! Thanks! You are a real life saver. lol.

 

So this is what I have now:


public GameObject boardManager;
	GridSquare currentPosition;


	public override void DestroyBrick ()
	{
		if (timesHit >= maxHits) {
			breakableCount--;
			boardManager.GetComponent<BoardManager>().CheckBorders(currentPosition);
			boardManager.GetComponent<BoardManager>().CheckDiagonals(currentPosition);
			levelManager.BrickDestroyed ();
			PuffSmoke ();
			Destroy (gameObject);
		} else {
			LoadSprites ();
		}
	}

But I'm not sure how to set currentPosition? How do I let CheckBorders and CheckDiagonals know which member of the array we are at?

1 hour ago, ethancodes said:

But I'm not sure how to set currentPosition?

That is the array index. It means the code has to be run from the array holder's perspective; it's why in my example I made a public function to call it.

Make some kind of public function that returns the object at the index input.

46 minutes ago, ethancodes said:

How do I let CheckBorders and CheckDiagonals know which member of the array we are at?

That was what the two images shows. In a 1D array you need a formula derived from the X and Y size to check that the next object is in fact next to the object, instead of bellow it.

So if we want the number above it is Index-X and bellow is Index+X. Right is Index+1 and Left is Index-1.

xx1DArrayBomb.jpg.1db991ecdf549f7b1c08e59a3e1db1c1.jpg,Mic.8YvpoulSmV.webp.pagespeed.ic.GPjs_GyDGP.webp

In a 2D array we know that the same index numbers are above and bellow while larger and smaller numbers is right and left.

x2DArrayBomb.jpg.a2d9adb5fd98100e50835f6d8d107342.jpg.pagespeed.ic.KS2gedU1_0.webp

 

Honestly I think you should abandon this whole list system and just use the Unity collision system, it works more like what you are trying to do now. You could just ray trace and see where blocks are based on their engine position, instead of index position.

World position is much more comprehensible.

Eff my life. lol. I'll look into it. Thanks man.

This topic is closed to new replies.

Advertisement