Unity Destroy() doesn't delete script - unity3d

Noob mistake I was only referencing the parents brain from the child's instead of copying it directly. It's a neural network that can grow in size (or shrink) through genetics. I was going to post it but it doesn't fit on this without me having to type a larger ratio of words to code oh look it works now
public class Animal1 : MonoBehaviour
{
public class Neuron1
{
public int[] children;
public float[] weights;
public float bias;
public float value;
public Neuron1()
{
children = new int[10];
for (int i = 0; i < 10; i++)
{
children[i] = -1;
}
weights = new float[10];
for (int i = 0; i < 10; i++)
{
weights[i] = 1;
}
bias = 0;
value = 0;
}
}
float sightRange = 2;
Vector2 left = new Vector2(-.4f,.6f);
Vector2 right = new Vector2(.4f, .6f);
RaycastHit2D hitLeft;
RaycastHit2D hitForward;
RaycastHit2D hitRight;
public LayerMask animalLayerMask;
[System.NonSerialized]
public int food = 0;
int foodCounter = 0;
int foodForReproduction = 3;
float noFoodCounter = 0;
int lifeWithoutFood = 20;
int maxBrainSize = 100;
[System.NonSerialized]
public Neuron1[] brain1 = new Neuron1[100]; //first three and last three are inputs and outputs and are never mutated
int childrenMaxAmount = 5;
float biasInitRange = 2;
float weightInitRange = 2;
int outputSize = 2;
int inputSize = 3;
GameObject manager;
[System.NonSerialized]
public bool firstGen = false;
[System.NonSerialized]
public GameObject parent1;
[System.NonSerialized]
public bool directCopy = false;
float maxTravelRange = 5;
Color color;
float colorMutationRate = .1f;
public GameObject animal1Prefab1;
bool debugBool = false;
void Start()
{
manager = GameObject.Find("Manager Object");
if (firstGen == true)
{
InitializeBrain(3, 2, 20);
firstGen = false;
transform.GetComponent<SpriteRenderer>().color = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f), 1);
}
else
{
if (parent1.GetComponent<Animal1>().brain1[0].bias == 1234)
{
Debug.Log("parent passing brain after deletion");
}
Mutate(parent1, 5, 1f, .5f);
transform.GetComponent<SpriteRenderer>().color = color;
}
}
void Update()
{
if (brain1[0].bias == 1234)
{
GetComponent<SpriteRenderer>().color = Color.black;
}
//teleportation
if (transform.position.x > maxTravelRange)
{
Vector2 newPosition = new Vector2(-maxTravelRange, transform.position.y);
transform.position = newPosition;
}
if (transform.position.x < -maxTravelRange)
{
Vector2 newPosition = new Vector2(maxTravelRange, transform.position.y);
transform.position = newPosition;
}
if (transform.position.y > maxTravelRange)
{
Vector2 newPosition = new Vector2(transform.position.x, -maxTravelRange);
transform.position = newPosition;
}
if (transform.position.y < -maxTravelRange)
{
Vector2 newPosition = new Vector2(transform.position.x, maxTravelRange);
transform.position = newPosition;
}
//input
hitLeft = Physics2D.Raycast(transform.position, transform.TransformDirection(left), sightRange, ~animalLayerMask); //left
hitForward = Physics2D.Raycast(transform.position, transform.TransformDirection(Vector2.up), sightRange, ~animalLayerMask); //forward
hitRight = Physics2D.Raycast(transform.position, transform.TransformDirection(right), sightRange, ~animalLayerMask); //right
if (hitLeft)
{
brain1[0].value = 1;
}
if (hitForward)
{
brain1[1].value = 1;
}
if (hitRight)
{
brain1[2].value = 1;
}
//output
Think();
// one output for speed, another for turning
int rotDir = 1;
if (brain1[maxBrainSize - 1].value < 0)
{
rotDir = -1;
}
Vector3 eulerRotation = new Vector3(0, 0, (45 * rotDir + (transform.rotation.eulerAngles.z % 360)) % 360);
transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.Euler(eulerRotation), Mathf.Abs(brain1[maxBrainSize - 1].value) * 25 * Time.deltaTime);
if (brain1[maxBrainSize - 2].value > 0) // so they can't go backwards
{
transform.Translate(Vector2.up * (brain1[maxBrainSize - 2].value * .1f) * Time.deltaTime);
}
//reset outputs
brain1[maxBrainSize - 2].value = 0;
brain1[maxBrainSize - 1].value = 0;
// reset inputs
brain1[0].value = 0;
brain1[1].value = 0;
brain1[2].value = 0;
noFoodCounter += Time.deltaTime;
if (food > 0)
{
foodCounter++;
food = 0;
noFoodCounter = 0;
}
if (foodCounter > foodForReproduction)
{
foodCounter = 0;
Reproduce();
}
if (noFoodCounter > lifeWithoutFood/2)
{
foodCounter = 0;
}
if (noFoodCounter > lifeWithoutFood)
{
Destroy(gameObject);
}
}
void InitializeBrain(int inputs, int outputs, int sizeExcludingInputsAndOutputs)
{
for (int i = 0; i < sizeExcludingInputsAndOutputs + inputs; i++)
{
brain1[i] = new Neuron1();
}
for (int i = maxBrainSize - outputs; i < maxBrainSize; i++) // outputs
{
brain1[i] = new Neuron1();
}
// all neurons in between the inputs and outputs
for (int i = inputs; i < sizeExcludingInputsAndOutputs + inputs; i++)
{
brain1[i].bias = Random.Range(-biasInitRange, biasInitRange);
for (short j = 0; j < childrenMaxAmount -1; j++) // -1 so there is always at least one free space for a child
{
int rnd1 = Random.Range(inputs, sizeExcludingInputsAndOutputs + inputs);
bool alreadyContains = true;
int errorCounter = 0;
while (alreadyContains) // making sure none are children of themselves, and that it doesn't already have this child
{
alreadyContains = false;
for (short h = 0; h < childrenMaxAmount; h++)
{
if (brain1[i].children[h] == rnd1) // if it already has this child
{
alreadyContains = true;
rnd1 = Random.Range(inputs, sizeExcludingInputsAndOutputs + inputs);
while (rnd1 == i) // and its not itself
{
rnd1 = Random.Range(inputs, sizeExcludingInputsAndOutputs + inputs);
}
break;
}
}
errorCounter++;
if (errorCounter > 100) // so we don't get stuck in small network sizes
{
goto outside2;
}
}
brain1[i].children[j] = rnd1;
brain1[i].weights[j] = Random.Range(-weightInitRange, weightInitRange);
if (Random.Range(1, 10) > 8)
{
break; // so not every neuron has the same amount of children
}
}
outside2:
{
}
}
// assign children of inputs
for (int i = 0; i < inputs; i++)
{
for (int j = 0; j < childrenMaxAmount; j++) // assigning all max children (sometimes) to inputs, their amounts of children will never change
{
int rnd1 = Random.Range(inputs, sizeExcludingInputsAndOutputs + inputs);
bool alreadyContains = true;
int errorCounter = 0;
while (alreadyContains)
{
alreadyContains = false;
for (short h = 0; h < childrenMaxAmount; h++)
{
if (brain1[i].children[h] == rnd1)
{
alreadyContains = true;
rnd1 = Random.Range(inputs, sizeExcludingInputsAndOutputs + inputs);
}
}
errorCounter++;
if (errorCounter > 1000) // so we don't get stuck in small network sizes
{
goto outside1;
}
}
brain1[i].children[j] = rnd1;
//brain1[i].weights[j] = 100; // input weight
}
outside1:
{
}
}
RemoveDeadNeurons();
// assign parents of outputs
int brainEnd = maxBrainSize - outputs;
for (int i = brainEnd; i < maxBrainSize; i++)
{
for (short j = 0; j < childrenMaxAmount; j++) // same amount of parents as inputs have children
{
int rnd1 = Random.Range(inputs, brainEnd);
while (brain1[rnd1] == null)
{
rnd1 = Random.Range(inputs, brainEnd);
}
bool alreadyContains = true;
int errorCounter = 0;
while (alreadyContains) //making sure we dont already have this parent
{
alreadyContains = false;
for (short h = 0; h < childrenMaxAmount; h++)
{
if (brain1[rnd1].children[h] == i)
{
alreadyContains = true;
rnd1 = Random.Range(inputs, brainEnd);
while (brain1[rnd1] == null)
{
rnd1 = Random.Range(inputs, brainEnd);
}
}
}
errorCounter++;
if (errorCounter > 1000) // so we don't get stuck
{
goto outside3;
}
}
for (int h = 0; h < childrenMaxAmount; h++) //adding to next available child space of the parent
{
if (brain1[rnd1].children[h] == -1)
{
brain1[rnd1].children[h] = i;
brain1[rnd1].weights[h] = Random.Range(-weightInitRange, weightInitRange);
break;
}
}
}
outside3:
{
}
}
}
void Think()
{
int[] activatedChildrenIndexes = new int[500];
int[] workingArray = new int[500];
int workingArrayCounter = 0;
short layerCounter = 0;
for (int i = 0; i < 500; i++)
{
activatedChildrenIndexes[i] = -1;
}
//initializing inputs as first activated children layer to be calculated
activatedChildrenIndexes[0] = 0;
activatedChildrenIndexes[1] = 1;
activatedChildrenIndexes[2] = 2;
int thoughtDepth = 6; //keep this as low as possible, will change to make it a percent of the amount of neurons that already exist
for (int x = 0; x < thoughtDepth; x++)
{
for (int i = 0; i < 500; i++) // cycle through activated children and add their activated children to a list
{
int currentNodeIndex = activatedChildrenIndexes[i];
if (currentNodeIndex == -1)
{
layerCounter++;
break;
}
//activation function
if (brain1[currentNodeIndex].value <= 0)
{
brain1[currentNodeIndex].value = 0;
}
else
{
brain1[currentNodeIndex].value = 1;
}
for (int j = 0; j < childrenMaxAmount; j++)
{
if (brain1[currentNodeIndex].children[j] == -1)
{
break;
}
brain1[brain1[currentNodeIndex].children[j]].value
+= (brain1[currentNodeIndex].value * brain1[currentNodeIndex].weights[j]) + brain1[currentNodeIndex].bias;
bool activatedChildIsInNextLayer = false;
for (int h = 0; h < 500; h++)
{
if (brain1[currentNodeIndex].children[j] == activatedChildrenIndexes[h])
{
activatedChildIsInNextLayer = true;
}
}
if (brain1[brain1[currentNodeIndex].children[j]].value > 0
|| layerCounter == 0
|| brain1[currentNodeIndex].children[j] > maxBrainSize - outputSize)
{
if (!activatedChildIsInNextLayer)
{
workingArray[workingArrayCounter] = brain1[currentNodeIndex].children[j];
if (workingArrayCounter < 499)//to prevent out of bounds indexing
{
workingArrayCounter++;
}
}
}
if (brain1[brain1[currentNodeIndex].children[j]].value < 0 && brain1[currentNodeIndex].children[j] < maxBrainSize - outputSize)
{
brain1[brain1[currentNodeIndex].children[j]].value = 0; //resetting negative nodes that didn't get added to next layer
}
}
brain1[currentNodeIndex].value = 0; // resetting value after passing to children
}
for (int i = workingArrayCounter; i < 500; i++)
{
workingArray[i] = -1;
}
workingArrayCounter = 0;
for (int i = 0; i < 500; i++)
{
activatedChildrenIndexes[i] = workingArray[i];
}
}
}
void Mutate(GameObject parent, float mutationRate, float weightsMutate, float biasMutate)
{
color = parent.GetComponent<SpriteRenderer>().color;
for (int i = 0; i < maxBrainSize; i++) // initialized to its parent's brain
{
if (parent.GetComponent<Animal1>().brain1[i] != null)
{
brain1[i] = new Neuron1();
brain1[i].bias = parent.GetComponent<Animal1>().brain1[i].bias;
for (int j = 0; j < childrenMaxAmount; j++)
{
brain1[i].children[j] = parent.GetComponent<Animal1>().brain1[i].children[j];
brain1[i].weights[j] = parent.GetComponent<Animal1>().brain1[i].weights[j];
}
}
}
for (int i = inputSize; i < maxBrainSize - outputSize; i++)
{
if (brain1[i] != null)
{
if (Random.Range(0, 100) < mutationRate) // it will be mutated
{
switch (Random.Range(1, 5))
{
case 1: //change one of its weights
int weightCounter = 0;
for (int k = 0; k < childrenMaxAmount; k++) // counting its weights
{
if (brain1[i].children[k] != -1)
{
weightCounter++;
}
else
{
break;
}
}
brain1[i].weights[Random.Range(0, weightCounter)] += Random.Range(-weightsMutate, weightsMutate);
color.r += Random.Range(-colorMutationRate, colorMutationRate);
color.g += Random.Range(-colorMutationRate, colorMutationRate);
color.b += Random.Range(-colorMutationRate, colorMutationRate);
break;
case 2: //change its bias
brain1[i].bias += Random.Range(-biasMutate, biasMutate);
color.r += Random.Range(-colorMutationRate, colorMutationRate);
color.g += Random.Range(-colorMutationRate, colorMutationRate);
color.b += Random.Range(-colorMutationRate, colorMutationRate);
break;
case 3: //break a connection/ remove neuron
int childrenCounter = 0;
for (int k = 0; k < childrenMaxAmount; k++) // counting its children
{
if (brain1[i].children[k] != -1)
{
childrenCounter++;
}
else
{
break;
}
}
int rndChild = Random.Range(0, childrenCounter);
for (int s = rndChild; s < childrenMaxAmount - 1; s++) // shift children list down starting from rndChild and to the second to last element
{
brain1[i].children[s] = brain1[i].children[s + 1];
brain1[i].weights[s] = brain1[i].weights[s + 1];
}
brain1[i].children[childrenMaxAmount - 1] = -1; // removing the last child after shifting the list down one
brain1[i].weights[childrenMaxAmount - 1] = 0;
RemoveDeadNeurons();
color.r += Random.Range(-colorMutationRate, colorMutationRate);
color.g += Random.Range(-colorMutationRate, colorMutationRate);
color.b += Random.Range(-colorMutationRate, colorMutationRate);
break;
case 4: //add a new child if possible
int childrenCounter2 = 0;
for (int k = 0; k < childrenMaxAmount; k++) // counting its children
{
if (brain1[i].children[k] != -1)
{
childrenCounter2++;
}
else
{
break;
}
}
if (childrenCounter2 < childrenMaxAmount) // if we have room for another child
{
int newChild = Random.Range(inputSize, maxBrainSize);
while (brain1[newChild] == null)
{
newChild = Random.Range(inputSize, maxBrainSize);
}
brain1[i].children[childrenCounter2] = newChild;
brain1[i].weights[childrenCounter2] = Random.Range(-weightInitRange, weightInitRange);
color.r += Random.Range(-colorMutationRate, colorMutationRate);
color.g += Random.Range(-colorMutationRate, colorMutationRate);
color.b += Random.Range(-colorMutationRate, colorMutationRate);
}
break;
}
}
}
}
if (Random.Range(0, 100) < 10) // create a new neuron if space is available for one
{
for (int i = inputSize; i < maxBrainSize - outputSize; i++)
{
if (brain1[i] == null) // the first available neuron
{
brain1[i] = new Neuron1();
int rndParent = Random.Range(0, maxBrainSize - outputSize);
int childrenCounter3 = 0;
if (brain1[rndParent] != null)
{
for (int k = 0; k < childrenMaxAmount; k++) // counting its children
{
if (brain1[rndParent].children[k] != -1)
{
childrenCounter3++;
}
else
{
break;
}
}
}
while (brain1[rndParent] == null || childrenCounter3 == childrenMaxAmount) // making sure it is both an existing neuron and that it has room for another child
{
childrenCounter3 = 0;
rndParent = Random.Range(0, maxBrainSize - outputSize);
if (brain1[rndParent] != null)
{
for (int k = 0; k < childrenMaxAmount; k++) // counting its children
{
if (brain1[rndParent].children[k] != -1)
{
childrenCounter3++;
}
else
{
break;
}
}
}
}
brain1[rndParent].children[childrenCounter3] = i; //giving the neuron a parent
brain1[rndParent].weights[childrenCounter3] = Random.Range(-weightInitRange, weightInitRange);
int rndChild = Random.Range(inputSize, maxBrainSize);
while(brain1[rndChild] == null)
{
rndChild = Random.Range(inputSize, maxBrainSize);
}
brain1[i].children[0] = rndChild; // giving the new neuron a child, a weight, and its bias
brain1[i].weights[0] = Random.Range(-weightInitRange, weightInitRange);
brain1[i].bias = Random.Range(-biasInitRange, biasInitRange);
color.r += Random.Range(-colorMutationRate, colorMutationRate);
color.g += Random.Range(-colorMutationRate, colorMutationRate);
color.b += Random.Range(-colorMutationRate, colorMutationRate);
break;
}
}
}
}
void RemoveDeadNeurons()
{
bool allGood = false;
while (!allGood)
{
for (int i = inputSize; i < maxBrainSize - outputSize; i++) // for every hidden layer neuron
{
if (brain1[i] != null) // if it's a neuron
{
if (brain1[i].children[0] == -1) // if it has no children
{
brain1[i] = null; // deleting neuron
for (int h = 0; h < maxBrainSize - outputSize; h++) //remove from other neurons children list, including from the input layer
{
if (brain1[h] != null)
{
for (int g = 0; g < childrenMaxAmount; g++)
{
if (brain1[h].children[g] == i) // if brain[h] has the removed neuron as a child
{
for (int s = g; s < childrenMaxAmount - 1; s++) // shift children list down
{
brain1[h].children[s] = brain1[h].children[s + 1];
brain1[h].weights[s] = brain1[h].weights[s + 1];
}
brain1[h].children[childrenMaxAmount - 1] = -1; // removing the last child in the list after shifting it down one
brain1[h].weights[childrenMaxAmount - 1] = 0;
}
}
}
}
goto outsideRDNLoop; // break out of for loop and recheck the brain
}
bool parentless = true;
for (int h = 0; h < maxBrainSize - outputSize; h++) // check if it is parentless
{
if (brain1[h] != null)
{
for (int g = 0; g < childrenMaxAmount; g++)
{
if (brain1[h].children[g] == i) // if it is a child of brain[h]
{
parentless = false;
}
}
}
}
if (parentless)
{
brain1[i] = null; //deleting neuron
goto outsideRDNLoop;
}
}
if (i == (maxBrainSize - outputSize) - 1) // if we reached the end of the for loop and this line, we know the brain was allGood
{
allGood = true;
}
}
outsideRDNLoop:
{
}
}
}
void Reproduce()
{
GameObject offspring = Instantiate(animal1Prefab1, new Vector2(transform.position.x + 1, transform.position.y + 1), Quaternion.identity);
offspring.GetComponent<Animal1>().parent1 = gameObject;
offspring.name = "animal1";
}
void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
Gizmos.DrawRay(transform.position, transform.TransformDirection(left) * sightRange);
Gizmos.DrawRay(transform.position, transform.TransformDirection(Vector2.up) * sightRange);
Gizmos.DrawRay(transform.position, transform.TransformDirection(right) * sightRange);
}
}

I've not run your code, just looked at it, but this looks suspicious if you are having problems with the contents of brain1 being overwritten elsewhere:
void Mutate(GameObject parent, float mutationRate, float weightsMutate, float biasMutate)
{
color = parent.GetComponent<SpriteRenderer>().color;
// This line here is suspicious:
brain1 = parent.GetComponent<Animal1>().brain1; // initialized to its parent's brain
What you are doing here is replacing the reference to the child's brain with the parent's - so if you are starting with just one parent initially, every single entity will be sharing the same brain.
I think perhaps you meant to deep copy the contents from parent's brain into the child's brain? What your assignment here is doing is just taking the reference to the parent's brain and using it as the child brain as well.
Example Deep copy:
Updated Neuron1 class:
public class Neuron1
{
public int[] children;
public float[] weights;
public float bias;
public float value;
public Neuron1()
{
children = new int[10];
for (int i = 0; i < 10; i++)
{
children[i] = -1; // to stop looping when reaching -1
}
weights = new float[10];
for (int i = 0; i < 10; i++)
{
weights[i] = 1;
}
bias = 0;
value = 0;
}
// Added clone function:
public Neuron1 Clone()
{
Neuron1 clone = new Neuron1();
for (int i = 0; i < clone.children.Length; i++)
{
clone.children[i] = this.children[i];
}
for (int i = 0; i < clone.weights.Length; i++)
{
clone.weights[i] = this.weights[i];
}
clone.bias = this.bias;
clone.value = this.value;
return clone;
}
}
Updated start of Mutate function.
void Mutate(GameObject parent, float mutationRate, float weightsMutate, float biasMutate)
{
color = parent.GetComponent<SpriteRenderer>().color;
Neuron1[] parentBrain = parent.GetComponent<Animal1>().brain1; // initialized to its parent's brain
for (int i = 0; i < brain1.Length; ++i)
{
brain1[i] = parentBrain[i].Clone();
}

Well, I have a demo scene here. In it I created an empty game object. It has a script attached to it (CSharp.cs), like this:
In my Update method I wrote
And as soon as I start the game, the game object including the script is deleted.
But if I replace transform.gameObject wit just this then only the script disappears and the game object remains.

DestoryImmediate() is not recommended to be used, instead use Destory()
Destroy() will set the object to null at the end of the frame and whereas DestroyImmediate() function immediately set object reference to null.
DestoryImmediate can also delete prefabs/scenes/art in your project outside of playmode which is another reason you should not use it.

Related

2D procedural dungeon generation game

I am currently messing around with a procedural 2D game in unity. Below are the scripts i am using to generate the dungeon and wanted to know if there was anyway of specifying a standard starting room. I have prefab room built but would like to have a single prefab room players always start in.
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public class DungeonGeneration : MonoBehaviour {
[SerializeField]
private int numberOfRooms;
[SerializeField]
private int numberOfObstacles;
[SerializeField]
private Vector2Int[] possibleObstacleSizes;
[SerializeField]
private int numberOfEnemies;
[SerializeField]
private GameObject[] possibleEnemies;
[SerializeField]
private GameObject goalPrefab;
[SerializeField]
private TileBase obstacleTile;
private Room[,] rooms;
private Room currentRoom;
private static DungeonGeneration instance = null;
void Awake () {
if (instance == null) {
DontDestroyOnLoad (this.gameObject);
instance = this;
this.currentRoom = GenerateDungeon ();
} else {
string roomPrefabName = instance.currentRoom.PrefabName ();
GameObject roomObject = (GameObject) Instantiate (Resources.Load (roomPrefabName));
Tilemap tilemap = roomObject.GetComponentInChildren<Tilemap> ();
instance.currentRoom.AddPopulationToTilemap (tilemap, instance.obstacleTile);
Destroy (this.gameObject);
}
}
void Start () {
string roomPrefabName = this.currentRoom.PrefabName ();
GameObject roomObject = (GameObject) Instantiate (Resources.Load (roomPrefabName));
Tilemap tilemap = roomObject.GetComponentInChildren<Tilemap> ();
this.currentRoom.AddPopulationToTilemap (tilemap, this.obstacleTile);
}
private Room GenerateDungeon() {
int gridSize = 3 * numberOfRooms;
rooms = new Room[gridSize, gridSize];
Vector2Int initialRoomCoordinate = new Vector2Int ((gridSize / 2) - 1, (gridSize / 2) - 1);
Queue<Room> roomsToCreate = new Queue<Room> ();
roomsToCreate.Enqueue (new Room(initialRoomCoordinate.x, initialRoomCoordinate.y));
List<Room> createdRooms = new List<Room> ();
while (roomsToCreate.Count > 0 && createdRooms.Count < numberOfRooms) {
Room currentRoom = roomsToCreate.Dequeue ();
this.rooms [currentRoom.roomCoordinate.x, currentRoom.roomCoordinate.y] = currentRoom;
createdRooms.Add (currentRoom);
AddNeighbors (currentRoom, roomsToCreate);
}
int maximumDistanceToInitialRoom = 0;
Room finalRoom = null;
foreach (Room room in createdRooms) {
List<Vector2Int> neighborCoordinates = room.NeighborCoordinates ();
foreach (Vector2Int coordinate in neighborCoordinates) {
Room neighbor = this.rooms [coordinate.x, coordinate.y];
if (neighbor != null) {
room.Connect (neighbor);
}
}
room.PopulateObstacles (this.numberOfObstacles, this.possibleObstacleSizes);
room.PopulatePrefabs (this.numberOfEnemies, this.possibleEnemies);
int distanceToInitialRoom = Mathf.Abs (room.roomCoordinate.x - initialRoomCoordinate.x) + Mathf.Abs(room.roomCoordinate.y - initialRoomCoordinate.y);
if (distanceToInitialRoom > maximumDistanceToInitialRoom) {
maximumDistanceToInitialRoom = distanceToInitialRoom;
finalRoom = room;
}
}
GameObject[] goalPrefabs = { this.goalPrefab };
finalRoom.PopulatePrefabs(1, goalPrefabs);
return this.rooms [initialRoomCoordinate.x, initialRoomCoordinate.y];
}
private void AddNeighbors(Room currentRoom, Queue<Room> roomsToCreate) {
List<Vector2Int> neighborCoordinates = currentRoom.NeighborCoordinates ();
List<Vector2Int> availableNeighbors = new List<Vector2Int> ();
foreach (Vector2Int coordinate in neighborCoordinates) {
if (this.rooms[coordinate.x, coordinate.y] == null) {
availableNeighbors.Add (coordinate);
}
}
int numberOfNeighbors = (int)Random.Range (1, availableNeighbors.Count);
for (int neighborIndex = 0; neighborIndex < numberOfNeighbors; neighborIndex++) {
float randomNumber = Random.value;
float roomFrac = 1f / (float)availableNeighbors.Count;
Vector2Int chosenNeighbor = new Vector2Int(0, 0);
foreach (Vector2Int coordinate in availableNeighbors) {
if (randomNumber < roomFrac) {
chosenNeighbor = coordinate;
break;
} else {
roomFrac += 1f / (float)availableNeighbors.Count;
}
}
roomsToCreate.Enqueue (new Room(chosenNeighbor));
availableNeighbors.Remove (chosenNeighbor);
}
}
private void PrintGrid() {
for (int rowIndex = 0; rowIndex < this.rooms.GetLength (1); rowIndex++) {
string row = "";
for (int columnIndex = 0; columnIndex < this.rooms.GetLength (0); columnIndex++) {
if (this.rooms [columnIndex, rowIndex] == null) {
row += "X";
} else {
row += "R";
}
}
Debug.Log (row);
}
}
public void MoveToRoom(Room room) {
this.currentRoom = room;
}
public Room CurrentRoom() {
return this.currentRoom;
}
public void ResetDungeon() {
this.currentRoom = GenerateDungeon ();
}
}
and
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public class Room
{
public Vector2Int roomCoordinate;
public Dictionary<string, Room> neighbors;
private string[,] population;
private Dictionary<string, GameObject> name2Prefab;
public Room (int xCoordinate, int yCoordinate)
{
this.roomCoordinate = new Vector2Int (xCoordinate, yCoordinate);
this.neighbors = new Dictionary<string, Room> ();
this.population = new string[18, 10];
for (int xIndex = 0; xIndex < 18; xIndex += 1) {
for (int yIndex = 0; yIndex < 10; yIndex += 1) {
this.population [xIndex, yIndex] = "";
}
}
this.population [8, 5] = "Player";
this.name2Prefab = new Dictionary<string, GameObject> ();
}
public Room (Vector2Int roomCoordinate)
{
this.roomCoordinate = roomCoordinate;
this.neighbors = new Dictionary<string, Room> ();
this.population = new string[18, 10];
for (int xIndex = 0; xIndex < 18; xIndex += 1) {
for (int yIndex = 0; yIndex < 10; yIndex += 1) {
this.population [xIndex, yIndex] = "";
}
}
this.population [8, 5] = "Player";
this.name2Prefab = new Dictionary<string, GameObject> ();
}
public List<Vector2Int> NeighborCoordinates () {
List<Vector2Int> neighborCoordinates = new List<Vector2Int> ();
neighborCoordinates.Add (new Vector2Int(this.roomCoordinate.x, this.roomCoordinate.y - 1));
neighborCoordinates.Add (new Vector2Int(this.roomCoordinate.x + 1, this.roomCoordinate.y));
neighborCoordinates.Add (new Vector2Int(this.roomCoordinate.x, this.roomCoordinate.y + 1));
neighborCoordinates.Add (new Vector2Int(this.roomCoordinate.x - 1, this.roomCoordinate.y));
return neighborCoordinates;
}
public void Connect (Room neighbor) {
string direction = "";
if (neighbor.roomCoordinate.y < this.roomCoordinate.y) {
direction = "N";
}
if (neighbor.roomCoordinate.x > this.roomCoordinate.x) {
direction = "E";
}
if (neighbor.roomCoordinate.y > this.roomCoordinate.y) {
direction = "S";
}
if (neighbor.roomCoordinate.x < this.roomCoordinate.x) {
direction = "W";
}
this.neighbors.Add (direction, neighbor);
}
public string PrefabName () {
string name = "Room_";
foreach (KeyValuePair<string, Room> neighborPair in neighbors) {
name += neighborPair.Key;
}
return name;
}
public Room Neighbor (string direction) {
return this.neighbors [direction];
}
public void PopulateObstacles (int numberOfObstacles, Vector2Int[] possibleSizes) {
for (int obstacleIndex = 0; obstacleIndex < numberOfObstacles; obstacleIndex += 1) {
int sizeIndex = Random.Range (0, possibleSizes.Length);
Vector2Int regionSize = possibleSizes [sizeIndex];
List<Vector2Int> region = FindFreeRegion (regionSize);
foreach (Vector2Int coordinate in region) {
this.population [coordinate.x, coordinate.y] = "Obstacle";
}
}
}
public void PopulatePrefabs (int numberOfPrefabs, GameObject[] possiblePrefabs) {
for (int prefabIndex = 0; prefabIndex < numberOfPrefabs; prefabIndex += 1) {
int choiceIndex = Random.Range (0, possiblePrefabs.Length);
GameObject prefab = possiblePrefabs [choiceIndex];
List<Vector2Int> region = FindFreeRegion (new Vector2Int(1, 1));
this.population [region[0].x, region[0].y] = prefab.name;
this.name2Prefab [prefab.name] = prefab;
}
}
private List<Vector2Int> FindFreeRegion (Vector2Int sizeInTiles) {
List<Vector2Int> region = new List<Vector2Int>();
do {
region.Clear();
Vector2Int centerTile = new Vector2Int(UnityEngine.Random.Range(2, 18 - 3), UnityEngine.Random.Range(2, 10 - 3));
region.Add(centerTile);
int initialXCoordinate = (centerTile.x - (int)Mathf.Floor(sizeInTiles.x / 2));
int initialYCoordinate = (centerTile.y - (int)Mathf.Floor(sizeInTiles.y / 2));
for (int xCoordinate = initialXCoordinate; xCoordinate < initialXCoordinate + sizeInTiles.x; xCoordinate += 1) {
for (int yCoordinate = initialYCoordinate; yCoordinate < initialYCoordinate + sizeInTiles.y; yCoordinate += 1) {
region.Add(new Vector2Int(xCoordinate, yCoordinate));
}
}
} while(!IsFree (region));
return region;
}
private bool IsFree (List<Vector2Int> region) {
foreach (Vector2Int tile in region) {
if (this.population [tile.x, tile.y] != "") {
return false;
}
}
return true;
}
public void AddPopulationToTilemap (Tilemap tilemap, TileBase obstacleTile) {
for (int xIndex = 0; xIndex < 18; xIndex += 1) {
for (int yIndex = 0; yIndex < 10; yIndex += 1) {
if (this.population [xIndex, yIndex] == "Obstacle") {
tilemap.SetTile (new Vector3Int (xIndex - 9, yIndex - 5, 0), obstacleTile);
} else if (this.population [xIndex, yIndex] != "" && this.population [xIndex, yIndex] != "Player") {
GameObject prefab = GameObject.Instantiate (this.name2Prefab[this.population [xIndex, yIndex]]);
prefab.transform.position = new Vector2 (xIndex - 9 + 0.5f, yIndex - 5 + 0.5f);
}
}
}
}
}
any help would be awesome even if you can point me in the direction to a how to.
Nice procedural dungeon generator! Just as a suggestion, could you cache the first room at the beginning when you are generating the dungeon? Then you can grab the initialRoomForPlayerSpawn coordinates/ position as a reference point for the character placement.
Room initialRoomForPlayerSpawn = null;
while (roomsToCreate.Count > 0 && createdRooms.Count < numberOfRooms) {
Room currentRoom = roomsToCreate.Dequeue ();
this.rooms [currentRoom.roomCoordinate.x, currentRoom.roomCoordinate.y] = currentRoom;
createdRooms.Add (currentRoom);
AddNeighbors (currentRoom, roomsToCreate);
/* Cache First Room */
if(createdRooms != null && createdRooms.Count <= 1) {
initialRoomForPlayerSpawn = currentRoom;
}
}

¿int number does not repeat with random.range unity?

I have 2 numbers that are used with random.range what I need is that the combination of both is not repeated 2 times, that is to say the combination a1, b1 can never be repeated but now I can't get that to happen is for a card game that I have to develop where the same card cannot be repeated neither in the hand nor in the game.
class Meca
public List<carta> cardPlay2; //current card combination, each update resets the list
public List<carta> cartaJugada; // current combination of cards, these are saved so that in future
updates the combination is not repeated
public bool isChange;
if (isChange)
{
cardPlay2.Clear();
int num = 5;
for (int j = 0; j < num; j++)
{
cambioCarta();
}
isChange = false;
}
void cambioCarta()
{
GameObject temp = Instantiate(carta);
temp.transform.SetParent(parent);
GameObject tem2p = Instantiate(carta2);
tem2p.transform.SetParent(parent2);
}
script carta
public int Num_cartas, PaloCarta;
public Mecanic meca;
void Start()
{
meca = GameObject.FindObjectOfType<Mecanic>();
if(gameObject.tag == "carta1")
cartas();
if (gameObject.tag == "carta2")
carta2();
}
void cartas()
{
Num_cartas = UnityEngine.Random.Range(1, 11);
PaloCarta = UnityEngine.Random.Range(1, 5);
carta carta1 = new carta
{
numCarta = Num_cartas,
palo = PaloCarta
};
}
[Serializable]
public class carta
{
public int numCarta;
public int palo;
}
what I'm trying to do is this
private void controlCartaMano2()
{
Num_cartas = UnityEngine.Random.Range(1, 10);
PaloCarta = UnityEngine.Random.Range(1, 4);
for (int i = 0; i < meca.cardPlay2.Count; i++)
{
while (meca.cardPlay2[i].numCarta == Num_cartas && meca.cardPlay2[i].palo == PaloCarta)
{
Num_cartas = UnityEngine.Random.Range(1, 10);
PaloCarta = UnityEngine.Random.Range(1, 4);
}
}
}
private void controlCartaJugada()
{
for (int i = 0; i < meca.cartaJugada.Count; i++)
{
for(int j = 0; j < meca.cartaJugada.Count; j++)
{
if(meca.cartaJugada[i].numCarta == meca.cartaJugada[j].numCarta &&
meca.cartaJugada[i].palo == meca.cartaJugada[j].palo)
{
Num_cartas = UnityEngine.Random.Range(1, 10);
PaloCarta = UnityEngine.Random.Range(1, 4);
}
}
}
}
if you have any idea how to do it I would appreciate it
You can use a Fisher-Yates shuffle method. That will shuffle the array, in place. It's then a simple matter of passing over the array incrementally. Here's a generic method that will shuffle an array:
static void Shuffle<T> ( T [ ] array )
{
var _random = new System.Random ( );
for ( int i = 0, n = array.Length; i < ( n - 1 ); ++i )
{
var next = i + _random.Next ( n - i );
var item = array [ next ];
array [ next ] = array [ i ];
array [ i ] = item;
}
}
For more information, here's the Wiki page : https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

Spawning random platforms in unity

So in my quest to make a game like the very popular zigzag game, I am stuck at randomly generating platforms. The platforms generate randomly in X,-X,Z,-Z directions. I have written my code where it generates the platforms. I might have taken a very long approach (alternative approaches if any)
void Start ()
{
lastPos = platform.transform.position;
size = platform.transform.localScale.x;
InvokeRepeating("SpawnXZ",1f,0.2f);
}
void SpawnX()
{
Vector3 pos = lastPos;
pos.x += size;
lastPos = pos;
Instantiate(platform, pos, Quaternion.identity);
}
void SpawnZ()
{
Vector3 pos = lastPos;
pos.z += size;
lastPos = pos;
Instantiate(platform, pos, Quaternion.identity);
}
void SpawnNegX()
{
Vector3 pos = lastPos;
pos.x -= size;
lastPos = pos;
Instantiate(platform, pos, Quaternion.identity);
}
void SpawnNegZ()
{
Vector3 pos = lastPos;
pos.z -= size;
lastPos = pos;
Instantiate(platform, pos, Quaternion.identity);
}
void SpawnXZ()
{
int rand = Random.Range(0, 6);
if (rand < 3)
{
SpawnX();
}
else if(rand >= 3)
{
SpawnZ();
}
if(--counter == 0) { CancelInvoke("SpawnXZ"); };
if(counter == 0)
{
counter = 25;
int r = Random.Range(0,2);
if(r == 0)
{
InvokeRepeating("SpawnNegXZ",0f,0.2f);
}
else
{
InvokeRepeating("SpawnXNegZ",0f,0.2f);
}
}
}
void SpawnNegXZ()
{
int rand = Random.Range(0, 6);
if (rand < 3)
{
SpawnNegX();
}
else if(rand >= 3)
{
SpawnZ();
}
if(--counter == 0) { CancelInvoke("SpawnNegXZ"); };
if(counter == 0)
{
counter = 25;
int r = Random.Range(0,2);
if(r == 0)
{
InvokeRepeating("SpawnXZ",0f,0.2f);
}
else
{
InvokeRepeating("SpawnNegXNegZ",0f,0.2f);
}
}
}
void SpawnXNegZ()
{
int rand = Random.Range(0, 6);
if (rand < 3)
{
SpawnX();
}
else if(rand >= 3)
{
SpawnNegZ();
}
if(--counter == 0) { CancelInvoke("SpawnXNegZ"); };
if(counter == 0)
{
counter = 25;
int r = Random.Range(0,2);
if(r == 0)
{
InvokeRepeating("SpawnXZ",0f,0.2f);
}
else
{
InvokeRepeating("SpawnNegXNegZ",0f,0.2f);
}
}
}
void SpawnNegXNegZ()
{
int rand = Random.Range(0, 6);
if (rand < 3)
{
SpawnNegX();
}
else if(rand >= 3)
{
SpawnNegZ();
}
if(--counter == 0) { CancelInvoke("SpawnNegXNegZ"); };
if(counter == 0)
{
counter = 25;
int r = Random.Range(0,2);
if(r == 0)
{
InvokeRepeating("SpawnNegXZ",0f,0.2f);
}
else
{
InvokeRepeating("SpawnXNegZ",0f,0.2f);
}
}
}
I have clubbed xz, -xz , x -z and -x -z. I call platform spawning in X and Z direction first, then switching to -XZ or x -Z and so on. But there are 2 main issues.
PS : those small black squares are nothing but diamonds (ignore them).
They either form a 2X2 block or overlap each other.
How do I avoid these? or is there a simpler way of generating platforms that I am missing.
You need an array to indicate which tiles are occupied:
bool[,] tiles = new bool[N,N];
or a dictionary
Dictionary<XZ, bool> tiles = new Dictionary<XZ, bool>();
public struct XZ { public int X; public int Z; }
whenever a tile is spawned check the value to see if it is possible to spawn or not:
void SpawnXZ()
{
int x = (int) (lastpos.x / size);
int z = (int) (lastpos.z / size);
int rand = Random.Range(0, 6);
if (rand < 3 && !tiles[x + 1, z])
{
SpawnX();
tiles[x + 1, z] = true;
}
else if(rand >= 3 && && !tiles[x, z + 1])
{
SpawnZ();
tiles[x, z + 1] = true;
}
else
{
...
}
Note that this code will not work, and it's just a starting point for you to develop it further.

Unity stops responding upon hitting play only when I uncomment a method

When I uncomment the line "ConnectMaze(maze)" in the Start() method, Unity instantly stops responding when I hit play. None of the Debug.Log statements show up in the console. If I comment out that specific line, I am able to see the Debug.Log statements in the console and Unity does respond. I am thinking that there could be an infinite loop in the ConnectMaze while loop, however wouldn't the Debug.Log statements prior to the loop still show up in the console? Below is the code that is causing the issue.
using UnityEngine;
using System.Collections;
public class MazeBase : MonoBehaviour {
public const int mazeLength = 11;
private int[,] maze = new int[mazeLength,mazeLength];
private int numWalls;
// Use this for initialization
void Start () {
Debug.Log ("Initialize Start");
InitializeMaze (maze);
Debug.Log ("Initialize End");
Debug.Log ("Connectivity Start");
ConnectMaze (maze);
Debug.Log ("Connectivity End");
MazeGenerator.Generate (transform,maze);
}
// Update is called once per frame
void Update () {
}
private void CreateMazeBlock(){
Vector3 mousePos = Input.mousePosition;
mousePos.z = 10;
Vector3 cameraPos = Camera.main.ScreenToWorldPoint (mousePos);
int cameraPosX = (int)Mathf.Round (cameraPos.x);
int cameraPosZ = (int)Mathf.Round (cameraPos.z);
if (maze [cameraPosX, cameraPosZ] != 1) {
maze [cameraPosX, cameraPosZ] = 1;
MazeGenerator.GenerateSingleBlock (transform, cameraPosX, cameraPosZ);
}
}
private void DeleteMazeBlock(){
Vector3 mousePos = Input.mousePosition;
mousePos.z = 10;
Vector3 cameraPos = Camera.main.ScreenToWorldPoint (mousePos);
int cameraPosX = (int)Mathf.Round (cameraPos.x);
int cameraPosZ = (int)Mathf.Round (cameraPos.z);
if (maze [cameraPosX, cameraPosZ] == 1) {
maze [cameraPosX, cameraPosZ] = 0;
MazeGenerator.DeleteSingleBlock (cameraPosX, cameraPosZ);
}
}
private void InitializeMaze(int[,] maze){
for (int i = 0; i < mazeLength; i++) {
for (int j = 0; j < mazeLength; j++) {
if (i == 0 || i == mazeLength - 1 || j == 0 || j == mazeLength - 1) {
maze [i, j] = -1;
numWalls++;
} else if (Random.Range (0, 100) < 50) {
bool createWall = true;
//Following if statements prevent a 2x2 square of walls
if (IsWall (maze, i - 1, j - 1) && IsWall (maze, i - 1, j) && IsWall (maze, i, j - 1)) {
createWall = false;
}else if (IsWall (maze, i - 1, j + 1) && IsWall (maze, i - 1, j) && IsWall (maze, i, j + 1)) {
createWall = false;
}else if (IsWall (maze, i + 1, j - 1) && IsWall (maze, i + 1, j) && IsWall (maze, i, j - 1)) {
createWall = false;
}else if (IsWall (maze, i + 1, j + 1) && IsWall (maze, i + 1, j) && IsWall (maze, i, j + 1)) {
createWall = false;
}
if(createWall){
maze [i, j] = -1;
numWalls++;
}
}
}
}
}
private bool IsWall(int[,] maze, int i, int j){
return maze [i, j] < 0;
}
private void ConnectMaze(int[,] maze){
Debug.Log ("GetNextTile Start");
ArrayList startTile = GetNextTile (maze,0);
Debug.Log ("GetNextTile End");
int startX = (int)startTile[0];
int startZ = (int)startTile[1];
int numberOfFloods = 1;
Debug.Log ("Flood Fill 1 Start");
int numFound = FloodFill(maze,startX,startZ,numberOfFloods);
Debug.Log ("Flood Fill 1 End");
while (numFound != (mazeLength * mazeLength) - numWalls) {
ArrayList nextWallTile = GetNextTile (maze, 1);
int wallX = (int)nextWallTile[0];
int wallZ = (int)nextWallTile[1];
maze [wallX, wallZ] = 0;
numWalls--;
numberOfFloods++;
int numFound2 = FloodFill(maze,startX,startZ,numberOfFloods);
if(numFound2 == (mazeLength*mazeLength)-numWalls){
break;
}
if (numFound2 - numFound > 1) {
numFound = numFound2;
} else {
maze [wallX, wallZ] = 2;
numWalls++;
}
int temp = (mazeLength * mazeLength) - numWalls;
Debug.Log ("Number of empty tiles: " + temp);
Debug.Log ("Number of tiles found: " + numFound);
}
}
private int FloodFill(int[,] maze, int x, int z,int value){
int numEmptyTilesFound = 0;
if (x < 0 || z < 0 || x >= mazeLength || z >= mazeLength) {
return 0;
}
if (maze [x, z] == -1 || maze [x, z] == value) {
return 0;
}
maze [x, z] = value;
numEmptyTilesFound++;
numEmptyTilesFound += FloodFill (maze, x - 1, z, value);
numEmptyTilesFound += FloodFill (maze, x + 1, z, value);
numEmptyTilesFound += FloodFill (maze, x, z - 1, value);
numEmptyTilesFound += FloodFill (maze, x, z + 1, value);
return numEmptyTilesFound;
}
private ArrayList GetNextTile(int[,] maze,int value){
int startX = 0;
int startZ = 0;
bool search = true;
for (int i = 0; i < mazeLength; i++) {
for (int j = 0; j < mazeLength; j++) {
if (maze [i, j] == value) {
startX = i;
startZ = j;
search = false;
}
if(!search){
break;
}
}
if(!search){
break;
}
}
ArrayList startingPoint = new ArrayList ();
startingPoint.Add (startX);
startingPoint.Add (startZ);
return startingPoint;
}
}

C# Quickly checking if two pictureboxes touch each other?

I'm creating my first non-console game in Visual C#.
I have a player which is a picturebox, and obstacles which are also pictureboxes.
Now when I create an obstacle (picturebox) at a random position, I would like to check if it already touches an other obstacle.
Here's what I have now:
Picturebox obstacles = new Picturebox[20];
for (int i = 0; i < obstacles.Length; i++)
{
DateTime date = DateTime.Now;
Random randomNumber = new Random(date.Second * (date.Minute / 2) ^ 2 + date.Hour * 123 + (i ^ 9 + i / 2));
obstacles[i] = new PictureBox();
obstacles[i].Image = Properties.Resources.es;
obstacles[i].Size = new Size(25, 50);
obstacles[i].Location = new Point(randomNumber.Next(640 - obstacles[i].Image.Width), randomNumber.Next(topBar.Height, 480 - obstacles[i].Image.Height));
if (IsTouching(obstacles[i], player))
{
i--;
}
else
{
bool tmp = true;
for (int j = 0; j < obstacles.Length; j++)
{
if (obstacles[j] != null && j != i)
{
if (IsTouching(obstacles[j], obstacles[i]))
{
tmp = false;
break;
}
}
}
if (tmp)
{
Controls.Add(obstacles[i]);
}
else
{
i--;
}
}
}
So that's my way, but I know it's not really effective, so any better ideas, cause it takes a while (~5 seconds) to create those obstacles.
And here's my IsTouching method, which also kinda sucks, anyone have better ideas?
private bool IsTouching(PictureBox obj1, PictureBox obj2)
{
Point[] obj1Points = new Point[(obj1.Width * obj1.Height) - ((obj1.Width - 2) * (obj1.Height - 2))];
int count = 0;
for (int x = obj1.Left + 1; x < obj1.Left + obj1.Width - 1; x++)
{
obj1Points[count] = new Point(x, obj1.Top);
obj1Points[count + 1] = new Point(x, obj1.Top + obj1.Height);
count += 2;
}
for (int y = obj1.Top; y < obj1.Top + obj1.Height; y++)
{
obj1Points[count] = new Point(obj1.Left, y);
obj1Points[count + 1] = new Point(obj1.Left + obj1.Width, y);
count += 2;
}
Point[] obj2Points = new Point[(obj2.Width * obj2.Height) - ((obj2.Width - 2) * (obj2.Height - 2))];
count = 0;
for (int x = obj2.Left + 1; x < obj2.Left + obj2.Width - 1; x++)
{
obj2Points[count] = new Point(x, obj2.Top);
obj2Points[count + 1] = new Point(x, obj2.Top + obj2.Height);
count += 2;
}
for (int y = obj2.Top; y < obj2.Top + obj2.Height; y++)
{
obj2Points[count] = new Point(obj2.Left, y);
obj2Points[count + 1] = new Point(obj2.Left + obj2.Width, y);
count += 2;
}
for (int obj2Point = 0; obj2Point < obj2Points.Length; obj2Point++)
{
for (int obj1Point = 0; obj1Point < obj1Points.Length; obj1Point++)
{
if (obj2Points[obj2Point].X == obj1Points[obj1Point].X && obj2Points[obj2Point].Y == obj1Points[obj1Point].Y)
{
return true;
}
}
}
return false;
}
What it does: Checks if the given two parameters edges touch each other. So basically just a collision-detection, anyone have any ideas, cause I'm kinda new at this stuff?
If we assume that all the obstacles are solid (i.e. 2 obstacles touch if the other is inside the other), you can use the following method:
private bool IsTouching(PictureBox p1, PictureBox p2)
{
if (p1.Location.X + p1.Width < p2.Location.X)
return false;
if (p2.Location.X + p2.Width < p1.Location.X)
return false;
if (p1.Location.Y + p1.Height < p2.Location.Y)
return false;
if (p2.Location.Y + p2.Height < p1.Location.Y)
return false;
return true;
}
I tested your current IsTouching method and found out that it fails in some corner cases, such as in this one (it claims they are not touching although they are). My method works in these corner cases too.
There is one simple line of code for this but it might also fail for some corner pieces sometimes.
if(player1.Bounds.IntersectWith(player2.Bounds){
//Do something
}
Replace player1 with the name of the picture box and the same with player2 ofc.