I've been making this enemy generator, which is called on Start() and it freezes most of the time. Sometimes it let's to play once but as soon as I hit play second time, it freezes, unity needs to be restarted. Standalone version doesn't fix the problem. Logs last lines:
UnityEngine.DebugLogHandler:Internal_Log(LogType, LogOption, String, Object)
UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[])
UnityEngine.Logger:Log(LogType, Object)
UnityEngine.Debug:Log(Object)
EnemyGenerator:Start() (at Assets\Scripts\Utils\EnemyGenerator.cs:23)
(Filename: Assets/Scripts/Utils/EnemyGenerator.cs Line: 23)
Here is my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyGenerator : MonoBehaviour
{
public List<GameObject> camps;
public List<GameObject> enemies;
int threshold;
public List<GameObject> campAreas;
public List<GameObject> enemyAreas;
public int campsToSpawn;
public int enemiesPerAreaMin;
public int enemiesPerAreaMax;
void Start()
{
for (int i = 0; i < campsToSpawn; i++)
{
threshold = Random.Range(0, camps.Count - 1);
Debug.Log(threshold);
var campPlace = Random.Range(0, campAreas.Count - 1);
var camp = Instantiate(camps[threshold], campAreas[campPlace].transform.position, Quaternion.identity);
if (camp != null)
{
campAreas.RemoveAt(campPlace);
}
}
Debug.Break();
bool canSpawn = true;
for (int i = 0; i < enemyAreas.Count; i++)
{
threshold = Random.Range(0, enemies.Count - 1);
List<GameObject> enemiesSpawned = new List<GameObject>();
var enemyCount = Random.Range(enemiesPerAreaMin, enemiesPerAreaMax);
for (int j = 0; j < enemyCount; j++)
{
var pos = new Vector3(Random.Range(enemyAreas[i].GetComponent<BoxCollider>().bounds.min.x, enemyAreas[i].GetComponent<BoxCollider>().bounds.max.x), enemyAreas[i].transform.position.y,
Random.Range(enemyAreas[i].GetComponent<BoxCollider>().bounds.min.z, enemyAreas[i].GetComponent<BoxCollider>().bounds.max.z));
if (enemiesSpawned.Count == 0)
{
GameObject en = null;
enemiesSpawned.Add(en = Instantiate(enemies[threshold], pos, Quaternion.identity));
}
else
{
for (int x = 0; x < enemiesSpawned.Count; x++)
{
if (Vector3.Distance(enemiesSpawned[x].transform.position, pos) < 3f)
{
canSpawn = false;
}
}
if (!canSpawn)
{
j--;
}
else
{
enemiesSpawned.Add(Instantiate(enemies[threshold], pos, Quaternion.identity));
}
}
}
Debug.Break();
}
}
}
I tried to find something that would actually loop forever, but I don't think that's the problem. Wondering if it could be performance leak?
Thank you in advance.
Sry I though it was an issue with Debug.Break();
this is probably the problem
{
for (int x = 0; x < enemiesSpawned.Count; x++)
{
if (Vector3.Distance(enemiesSpawned[x].transform.position, pos) < 3f)
{
canSpawn = false;
}
}
if (!canSpawn)
{
j--;
}
else
{
enemiesSpawned.Add(Instantiate(enemies[threshold], pos, Quaternion.identity));
}
}
You getting a random position inside a certain bounds. If the position is too close u don't spawn and --j; to retry a new position. So if for some reason the bounds are wrong or barely engouth you might be running that function for a very long time.
A quick test is to add a counter before your j for loop.
int debugCounter = 0;
for (int j = 0; j < enemyCount; j++)
{
//at the very top
++debugCounter;
if(debugCounter > 100)//or a bigger number
{
Debug.Log("Too many attemps");
break;
}
...
Related
I have some code that is supposed to create a grid of voxels, and then rooms out of those voxels. However, a lot of the rooms still overlap, even when I wrote code specifically to prevent this from happening. Would anybody be able to tell me what's going?
I'm using an out variable for the first time, and I think that's part of the issues.
Basically, the code is supposed to create a list of voxels to turn into a room, turn them into a room, and repeat for the total number of rooms. If a voxel in the list is found to already be a room, it should clear the list and not create a room.
All the relevant code is below, you should be able to plug this into a new Unity project and see for yourself everything, complete with Gizmos.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum VoxelType{
Undefined = 0,
OpenRoom,
OpenHall,
Wall,
Buffer,
}
[System.Serializable]
public class Voxel {
public Vector3 position;
public VoxelType voxelType;
public int voxelX;
public int voxelY;
public Voxel(Vector3 newPosition, int x, int y, VoxelType newType = 0){
position = newPosition;
voxelType = newType;
voxelX = x;
voxelY = y;
}
}
public class VoxelManager : MonoBehaviour
{
public Vector2 mapSize;
public float voxelSize;
public int rooms;
public int maxRoomHeight;
public int minRoomHeight;
public int maxRoomWidth;
public int minRoomWidth;
List<Voxel> voxels = new List<Voxel>();
void OnDrawGizmosSelected(){
foreach(Voxel voxel in voxels){
if (voxel.voxelType == VoxelType.OpenRoom){
Gizmos.color = Color.red;
} else {
Gizmos.color = Color.blue;
}
switch (voxel.voxelType){
case VoxelType.Undefined:
Gizmos.color = Color.blue;
break;
case VoxelType.Wall:
Gizmos.color = Color.magenta;
break;
case VoxelType.OpenRoom:
Gizmos.color = Color.red;
break;
}
Gizmos.DrawCube(voxel.position, Vector3.one * voxelSize *.995f);
}
}
void Start(){
voxelSpawn = prefab;
for(int i = 0; i < mapSize.x; i++){
for (int j = 0; j < mapSize.y; j++){
float xLocation = voxelSize * i;
float zLocation = voxelSize * j;
float centerXLocation = (xLocation - (mapSize.x * voxelSize) / 2f) + voxelSize / 2f;
float centerZLocation = (zLocation - (mapSize.y * voxelSize) / 2f) + voxelSize / 2f;
string voxelName = i + "x" + j;
Vector3 center = new Vector3(centerXLocation, voxelSize / 2, centerZLocation);
voxels.Add(new Voxel(center, i, j));
}
}
for (int i = 0; i < rooms; i++){
List<Voxel> roomVoxels = new List<Voxel>();
int generatedHeight = Random.Range(minRoomHeight, maxRoomHeight);
int generatedWidth = Random.Range(minRoomWidth, maxRoomWidth);
int horizontalRoomIndex = Random.Range(0, ((int)mapSize.x));
int verticalRoomIndex = Random.Range(0, ((int)mapSize.y));
bool occupied = false;
foreach(Voxel voxel in voxels){
if(voxel.voxelX == horizontalRoomIndex && voxel.voxelY == verticalRoomIndex){
for (int j = 0; j < generatedHeight; j++){
for (int k = 0; k < generatedWidth; k++){
roomVoxels.Add(GetVoxelAtPosition(horizontalRoomIndex + j, verticalRoomIndex + k, out occupied));
}
}
}
}
if(occupied == true){
Debug.Log("Room occupied; unable to create! Clearing the current list to be turned into a room!");
roomVoxels.Clear();
i--;
} else {
Debug.Log("Making a room!");
foreach(Voxel roomVoxel in roomVoxels){
roomVoxel.voxelType = VoxelType.OpenRoom;
}
}
}
}
Voxel GetVoxelAtPosition(int x, int y, out bool occupied){
foreach(Voxel voxel in voxels){
if(voxel.voxelX == x && voxel.voxelY == y){
if (voxel.voxelType == VoxelType.Undefined){
occupied = false;
return voxel;
} else {
Debug.Log("Voxel occupied!");
occupied = true;
return voxels[0];
}
}
}
occupied = true;
return voxels[0];
}
}
I have a List<GameObject> and I need to remove doubles that have the same position.y and position.x (position.z is irrelevant).
I'm thinking that I need to compare all elements in a list and go through the previous elements of the same list and compare if they have the same positions and then, if not, populate the new List<GameObject>().
I don't really know how to do this as I'm not an experienced programmer.
If you wish to just remove the duplicates from an existing list, you don't necessarily have to create a new one. You can iterate over the list and use the RemoveAt method to get rid of the undesired elements.
Example
using System.Collections.Generic;
using UnityEngine;
public class TestScript : MonoBehaviour
{
public List<GameObject> collection = new List<GameObject>();
private void Start()
{
RemoveDuplicatesFrom(collection);
}
private void RemoveDuplicatesFrom(List<GameObject> collection)
{
for (int i = 0; i < collection.Count; i++)
{
for (int j = i + 1; j < collection.Count; j++)
{
if (!Match(collection[i], collection[j]))
continue;
collection.RemoveAt(j);
j--;
}
}
}
private bool Match(GameObject object1, GameObject object2)
{
return
object1.transform.position.x == object2.transform.position.x &&
object1.transform.position.y == object2.transform.position.y;
}
}
The function below should work just fine
public static List<GameObject> Delete_Doubles(List<GameObject> gameobjects){
List<Vector2> occupied_coord = new List<Vector2>();
List<GameObject> gameobjects_after = new List<GameObjects>();
Vector2 t_vector = new Vector2();
Vector3 pos = new Vector3();
pos = gameobjects[0].Transform.position;
t_vector.x = pos.x;
t_vector.y = pos.y;
gameobjects_after.Add(gameobjects[0]);
occupied_coord.Add(t_vector);
for(int i = 1; i < gameobjects.Count; i++)
{
pos = gameobjects[i].Transform.position;
t_vector.x = pos.x;
t_vector.y = pos.y;
if (!occupied_coord.Contains(t_vector))
{
gameobjects_after.Add(gameobjects[i]);
occupied_coord.Add(t_vector);
}
}
return gameobjects_after;
}
I have an array of gameObjects which I can deactivate easily with a loop. However I do not want to deactivate one gameObject from the lot. So I am providing an int value which is the position of the gameObject in that array. How do I deactivate others except for this particular object?
public GameObject[] myObjs;
int exceptionObj;
void Start()
{
exceptionObj = 2; //Position of object in the array
for(int i = 0; i<myObjs.Length; i++)
{
myObjs[i].SetActive(false);
}
}
public GameObject[] myObjs;
int exceptionObj;
void Start()
{
exceptionObj = 2; //Position of object in the array
for(int i = 0; i<myObjs.Length; i++)
{
if(exceptionObj != i)
myObjs[i].SetActive(false);
}
}
Or;
public GameObject[] myObjs;
int exceptionObj;
void Start()
{
exceptionObj = 2; //Position of object in the array
for(int i = 0; i<myObjs.Length; i++)
{
if(exceptionObj == i)
continue;
myObjs[i].SetActive(false);
}
}
Or perhaps even by simply reactivating at the end;
public GameObject[] myObjs;
int exceptionObj;
void Start()
{
exceptionObj = 2; //Position of object in the array
for(int i = 0; i<myObjs.Length; i++)
{
myObjs[i].SetActive(false);
}
myObjs[exceptionObj].SetActive(true);
}
Two ways:
With an if:
exceptionObj = 2; //Position of object in the array
for(int i = 0; i<myObjs.Length; i++)
{
if (i != exceptionObj) // If not the exception ID
myObjs[i].SetActive(false);
}
Or with two loops:
exceptionObj = 2; //Position of object in the array
for(int i = 0; i<exceptionObj; i++)
{
myObjs[i].SetActive(false);
}
for(int i = exceptionObj+1; i<myObjs.Length; i++)
{
myObjs[i].SetActive(false);
}
I need Help, I'm doing a smaller puzzle game but I have trouble getting the playing field to the center.
Playing field is still on the bottom/left
I tried to fix it using the forum but nothing happened.
Thanks for your help.
Problem
GameBoard.cs
using UnityEngine;
using System.Collections;
public class GameBoard : MonoBehaviour {
public int m_size;
public GameObject m_puzzlePiece;
public GameObject buttonNext;
private PuzzleSection[,] m_puzzle;
private PuzzleSection m_puzzleSelection;
public int m_randomPasses = 12;
void Start()
{
GameObject temp;
m_puzzle = new PuzzleSection[m_size, m_size];
for (int i=0; i< m_size; i++)
{
for (int j=0; j< m_size; j++)
{
temp = (GameObject)Instantiate(m_puzzlePiece,
new Vector2(i*700/m_size, j*700/m_size), Quaternion.identity);
temp.transform.SetParent(transform);
m_puzzle[i, j] = (PuzzleSection)temp.GetComponent<PuzzleSection>();
m_puzzle[i, j].CreatePuzzlePiece(m_size);
}
}
SetupBoard();
RandomizePlacement();
}
void RandomizePlacement()
{
VectorInt2[] puzzleLocation = new VectorInt2[2];
Vector2[] puzzleOffset = new Vector2[2];
do
{
for (int i = 0; i < m_randomPasses; i++)
{
puzzleLocation[0].x = Random.Range(0, m_size);
puzzleLocation[0].y = Random.Range(0, m_size);
puzzleLocation[1].x = Random.Range(0, m_size);
puzzleLocation[1].y = Random.Range(0, m_size);
puzzleOffset[0] = m_puzzle[puzzleLocation[0].x, puzzleLocation[0].y].GetImageOffset();
puzzleOffset[1] = m_puzzle[puzzleLocation[1].x, puzzleLocation[1].y].GetImageOffset();
m_puzzle[puzzleLocation[0].x, puzzleLocation[0].y].AssignImage(puzzleOffset[1]);
m_puzzle[puzzleLocation[1].x, puzzleLocation[1].y].AssignImage(puzzleOffset[0]);
}
} while (CheckBoard() == true);
}
void SetupBoard()
{
Vector2 offset;
Vector2 m_scale = new Vector2(1f / m_size, 1f / m_size);
for (int i=0; i< m_size; i++)
{
for (int j=0; j< m_size; j++)
{
offset = new Vector2(i * (1f / m_size), j * (1f / m_size));
m_puzzle[i, j].AssignImage(m_scale, offset);
}
}
}
public PuzzleSection GetSelection()
{
return m_puzzleSelection;
}
public void SetSelection(PuzzleSection selection)
{
m_puzzleSelection = selection;
}
public bool CheckBoard()
{
for (int i=0; i<m_size; i++)
{
for(int j=0; j< m_size; j++)
{
if (m_puzzle[i, j].CheckGoodPlacement() == false)
return false;
}
}
return true;
}
public void Win()
{
buttonNext.SetActive(true);
}
}
PuzzleSection.cs
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class PuzzleSection : MonoBehaviour {
Vector2 m_goodOffset;
Vector2 m_offset;
Vector2 m_scale;
GameBoard m_gameBoard;
void Start()
{
m_gameBoard = (GameBoard)GameObject.FindObjectOfType<Canvas>()
.GetComponentInChildren<GameBoard>();
}
public void CreatePuzzlePiece(int size)
{
transform.localScale = new Vector3(1.0f * transform.localScale.x / size,
1.0f * transform.localScale.z / size, 1);
}
public void AssignImage(Vector2 scale, Vector2 offset)
{
m_goodOffset = offset;
m_scale = scale;
AssignImage(offset);
}
public void AssignImage(Vector2 offset)
{
m_offset = offset;
GetComponent<RawImage>().uvRect = new Rect(offset.x, offset.y, m_scale.x, m_scale.y);
}
public void OnClick()
{
PuzzleSection previousSelection = m_gameBoard.GetSelection();
if (previousSelection != null)
{
previousSelection.GetComponent<RawImage>().color = Color.white;
Vector2 tempOffset = previousSelection.GetImageOffset();
previousSelection.AssignImage(m_offset);
AssignImage(tempOffset);
m_gameBoard.SetSelection(null);
if (m_gameBoard.CheckBoard() == true)
m_gameBoard.Win();
} else
{
GetComponent<RawImage>().color = Color.gray;
m_gameBoard.SetSelection(this);
}
}
public Vector2 GetImageOffset()
{
return m_offset;
}
public bool CheckGoodPlacement()
{
return (m_goodOffset == m_offset);
}
}
Hey guys, I need Help, I'm doing a smaller puzzle game but I have trouble getting the playing field to the center.
Playing field is still on the bottom/left
I tried to fix it using the forum but nothing happened.
Thanks for your help.
As i gather from the picture your gameboard gets drawn inside a Panel ui control.
You could set the position of this panel to the centre, so that all its children will be centred alongside it:
MyPanel.transform.position = new Vector3 (Screen.width * 0.5f, Screen.height * 0.5f, 0);
I am trying to figure out how to randomize my Perlin noise in C# but cannot find a way to do so with the code I currently have. Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PerlinCubeGenScript01 : MonoBehaviour {
public float perlinNoise = 0f;
public float refinement = 0f;
public int multiplier = 0;
public int cubes = 0;
public float darkness;
void Start () {
for (int i = 0; i < cubes; i++) {
for (int j = 0; j < cubes; j++) {
perlinNoise = Mathf.PerlinNoise(i * refinement, j * refinement);
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);
go.transform.position = new Vector3(i, Mathf.Round(perlinNoise * multiplier), j);
int cubeY = (int) Mathf.Round(perlinNoise * multiplier);
Debug.Log(cubeY);
go.GetComponent<Renderer>().material.color = new Color(1, 1, 1, 0f);
}
}
}
void Update () {
}
}
As long as Perlin Noise function allows you to pick any point in a 2D space, why not simply use a random number as your seed and start picking points from there?
void Start () {
Random rnd = new Random();
int seed = rnd.Next(Int32.MinValue, Int32.MaxValue);
for (int i = 0; i < cubes; i++) {
for (int j = 0; j < cubes; j++) {
perlinNoise = Mathf.PerlinNoise(seed + (i * refinement), seed + (j * refinement));
// Note that if refinement never changes you are always picking the same point
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);
go.transform.position = new Vector3(i, Mathf.Round(perlinNoise * multiplier), j);
int cubeY = (int) Mathf.Round(perlinNoise * multiplier);
Debug.Log(cubeY);
go.GetComponent<Renderer>().material.color = new Color(1, 1, 1, 0f);
}
}
}