Just as the title says, I have a waveManaging system that spawnsEnemies based on enemies that are yet to spawn and remain alive.
for (int enemiesRemainingToSpawn = currentWaveNumber ; enemiesRemainingToSpawn > 0;enemiesRemainingToSpawn -- , enemiesRemainingAlive ++)
{
print("enemies spawning" + enemiesRemainingToSpawn);
print("enemies alive" + enemiesRemainingAlive);
}
This is just a test right now, but it seems that 'enemiesRemaingToSpawn --' is not working while 'enemiesRemainingAlive ++' is.
On the GameDev Discord, no one has found anything wrong with it which is why I am here. It looks fine to me as well. I have tried putting it within the body of the loop but that does not work as well. i have specified it within the initializing(first) section of the for loop and again this does not work.
What is the problem at hand?
edit:
public int enemiesRemainingToSpawn;
public int enemiesRemainingAlive;
public float afterWavePrepTime = 5f;
public GameObject basicEnemyPreFab;
public Transform[] spawnPoints;
private bool isWaveFinished = false;
private bool startNewWave = false;
public int currentWaveNumber;
void spawnEnemies ()
{
int spawnPointIndex = Random.Range(0, spawnPoints.Length);
for (int enemiesRemainingToSpawn = currentWaveNumber ; enemiesRemainingToSpawn > 0;enemiesRemainingToSpawn -- , enemiesRemainingAlive ++)
{
print("enemies spawning" + enemiesRemainingToSpawn);
print("enemies alive" + enemiesRemainingAlive);
}
}
The output is that enemiesRemainingAlive constantly goes up because EnemiesRemainingToSpawn does not go down, concluding in an endless loop.
remainingtospawn = 1, enemiesremainingalive ++
Hi I try to run your code in locally by excluding your objects .Its running well
public static void spawnEnemies()
{
int enemiesRemainingAlive = 0;
double afterWavePrepTime = 5.0;
bool isWaveFinished = false;
bool startNewWave = false;
int currentWaveNumber;
Random x = new Random();
currentWaveNumber = x.Next(1, 7);
for (int enemiesRemainingToSpawn = currentWaveNumber; enemiesRemainingToSpawn > 0; enemiesRemainingToSpawn--, enemiesRemainingAlive++)
{
Console.WriteLine("enemies spawning" + enemiesRemainingToSpawn);
Console.WriteLine("enemies alive" + enemiesRemainingAlive);
}
Console.ReadLine();
}
//out put
// enemies spawning2
//enemies alive0
//enemies spawning1
//enemies alive1
Related
I'm making a simple game in C# where the player fights until they have no more health:
public void FightLoop(int currentHealth) {
bool death = false;
do{
hit = false;
if(currentHealth == 0){
death = true;
}
turn = turn + 1;
string turnRecord = turn.ToString();
string firstPlayerChoiceString = GetPlayerInput();
string secondPlayerChoiceString = GetRandomWeapon ();
string gameResult = DetermineWinner(firstPlayerChoiceString, secondPlayerChoiceString, currentHealth, turnRecord);
if(hit == true){
currentHealth = currentHealth - 1;
}
FightRecord();
AddRecord(firstPlayerChoiceString, secondPlayerChoiceString, gameResult, turnRecord, turn);
}while (death == false);
DisplayFightHistory ();
}
At the end of each fight, a summary of the whole thing should be shown (array with turns, attacks and results).
public void FightRecord(int recordSize = 100)
{
try
{
fightRecordSize = recordSize;
fightRecord = new string[fightRecordSize, 4];
}
catch (OverflowException e)
{
System.Console.WriteLine("OverflowException during FightRecord initialization: \"{0}\"\nrecordSize given was [{1}]\nSetting recordSize to 10", e.Message, recordSize);
fightRecordSize = 100;
fightRecord = new string[fightRecordSize, 4];
}
fightRecordCurrentSize = fightRecordCurrentSize++;
}
public void AddRecord(string playerOneChoice, string playerTwoChoice, string gameResult, string turnRecord, int turn)
{
// Insert the record data
fightRecord[fightRecordCurrentIndex, 0] = playerOneChoice;
fightRecord[fightRecordCurrentIndex, 1] = playerTwoChoice;
fightRecord[fightRecordCurrentIndex, 2] = gameResult;
fightRecord[fightRecordCurrentIndex, 3] = turnRecord;
// Increment the fight index counter and current history size
fightRecordCurrentIndex = (fightRecordCurrentIndex + 1) % fightRecordSize;
if (fightRecordCurrentSize < fightRecordSize)
{
fightRecordCurrentSize++;
}
}
public void DisplayFightHistory () {
System.Console.WriteLine ("\nPodsumowanie:");
for (int i = 0; i < fightRecordCurrentSize; i++){
System.Console.WriteLine ("Tura #{0}:\t{1}\t-\t{2},\t{3} {4}",
fightRecord[i,3], fightRecord[i,0], fightRecord[i,1], fightRecord[i,2], i);
}
}
However, every time I get only the last value, like this:
Summary:
Turn #: - ,
Turn #: - ,
Turn #: - ,
Turn #: - ,
Turn #: - ,
Turn #: - ,
Turn #8: Sword - Spear, You lose
By following the whole process of creating the array, it seems like the values are being put in it correctly at first, but with each new turn, only the last value remains.
Does anyone have any idea why it's happening?
Use the loop variable as the index.
Change
fightRecord[displayRecordIndex,3], fightRecord[displayRecordIndex,0], fightRecord[displayRecordIndex,1], fightRecord[displayRecordIndex,2], displayRecordIndex);
To
fightRecord[i,3], fightRecord[i,0], fightRecord[i,1], fightRecord[i,2], i);
https://simmer.io/#JammerLamma/~c09dd45e-0528-01ce-e641-e4a56fb9cfed
https://github.com/JammerLamma/Number-Muncher-Clone
I'm creating a number munchers clone, and the integer variables are not getting properly assigned. It works for a few games, but after a few times of winning, and/or clicking quit, and choosing another game it appears the for loop goes through properly. The game says there are 5 maxCorrect, and correctOnBoard is also set to 5, so I assume the loop goes through 5 times, however, only 4 tiles get set as correct, then sometimes 2, or 4, but never 5 again. It always works as intended the first game.
If I comment out //AssignRest(); the problem still persists.
public void GenerateEven()
{
//GameObject smasher = Instantiate(smasherPF, transform.position, transform.rotation);
remainingNumbers = totalTiles - maxCorrect;
GetLists();
GetTiles();
AssignEven();
RemoveDuplicates(evenNumbers);
AssignRest();
}
private void AssignEven()
{
int maxCorrect = 5;
for (int i = 1; i <= maxCorrect; i++)
{
randomChild = children[UnityEngine.Random.Range(0, children.Count)];
int maxLength = evenNumbers.Count;
int tempTileNum = evenNumbers[UnityEngine.Random.Range(0, maxLength)];
randomChild.GetComponent<Tile>()._TileNumber = tempTileNum;
randomChild.GetComponent<Tile>()._IsCorrect = true;
correctOnBoard++;
randomChild.GetComponent<SpriteRenderer>().sprite = numberSprite[tempTileNum - 1];
Debug.Log(tempTileNum);
}
}
Some things are serialized for debugging purposes. All of the lists get generated correctly.
Changed the code to
private void AssignEven()
{
for (int i = 1; i <= maxCorrect;)
{
randomChild = children[UnityEngine.Random.Range(0, children.Count)];
if(randomChild.GetComponent<Tile>()._IsCorrect == false)
{
int maxLength = evenNumbers.Count;
int tempTileNum = evenNumbers[UnityEngine.Random.Range(0, maxLength)];
randomChild.GetComponent<Tile>()._TileNumber = tempTileNum;
randomChild.GetComponent<Tile>()._IsCorrect = true;
correctOnBoard++;
randomChild.GetComponent<SpriteRenderer>().sprite = numberSprite[tempTileNum - 1];
Debug.Log(tempTileNum);
i++;
}
}
}
Thanks to John Wu!
I am having a bit of a problem figuring out how to randomly get an object out of a list that wasn't picked on the last update of a script. When this randomly instantiated object is spawned and reaches a certain y value, it will set itself to inactive. So when this object is not active, it will go through an array and pick another object at random. However, I do not want to include the previous active object.
example: blue ball was first active. Moves on the Y axis. Becomes inactive. Next object spawn should have no chance of being a blue ball. Any ideas and help will be greatly appreciated.
My code is below
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ballGeneratorShooter : MonoBehaviour
{
private int ballSelector;
private TagNumber theTagNumber;
public ObjectPooler[] theObjectballPools;//In my inspector, I have 5 prefab gameObjects attached
List<ObjectPooler> changingBalls;
public bool changeBalls;
public GameObject currentBall;
public GameObject newBall;
// Use this for initialization
void Start()
{
changingBalls = new List<ObjectPooler>();
currentBall = newBall;
}
// Update is called once per frame
void Update()
{
if (newBall == null)
{
ballSelector = Random.Range(0, theObjectballPools.Length);
newBall = theObjectballPools[ballSelector].GetPooledObject();
newBall.transform.position = transform.position;
newBall.transform.rotation = transform.rotation;
newBall.SetActive(true);
}
if (newBall.activeInHierarchy == false)
{
if (changeBalls)
{
for (int i = 0; i < theObjectballPools.Length; i++)
{
if (theObjectballPools[i].GetPooledObject().GetComponent<TagNumber>().tag != currentBall.GetComponent<TagNumber>().tag)
{
changingBalls.Add(theObjectballPools[i]);
}
//changingballs.Add(theObjectballPools[i]);
}
ballSelector = Random.Range(0, changingBalls.Count);
newBall = theObjectballPools[ballSelector].GetPooledObject();
Debug.Log(changingBalls.Count);
newBall.transform.position = transform.position;
newBall.transform.rotation = transform.rotation;
newBall.SetActive(true);
currentBall = newBall;
changeBalls = false;
changingBalls.Clear();
}
}
}
}
You need to store the random number to variable (lastRandomNum) each time you generate a random number. Now, use the function below that can generate a random number with exclusion.
int RandomWithExclusion(int min, int max, int exclusion)
{
var result = UnityEngine.Random.Range(min, max - 1);
return (result < exclusion) ? result : result + 1;
}
You pass in 0 to min, then theObjectballPools.Length or changingBalls.Count to the max, then finally, lastRandomNum value to the exclusion parameter.
You also need a boolean variable to determine if this is the first run. If this is the first run, use the Unity's Random.Range function then set the firstRun to false. If it is not the firstRun, use the RandomWithExclusion function from this answer and pass in the lastRandomNum value to exclude it. Also, store the generated random number to the lastRandomNum variable to be used next frame.
Below is a simplified version of what I said above. You have to incorporate that to your code.
GameObject[] yourItem = null;
bool firstRun = true;
int lastRandomNum = 0;
void Update()
{
if (firstRun)
{
firstRun = false;
//First run, use Random.Range
lastRandomNum = UnityEngine.Random.Range(0, yourItem.Length);
}
else
{
//Not First run, use RandomWithExclusion
lastRandomNum = RandomWithExclusion(0, yourItem.Length, lastRandomNum);
}
//Do something with the lastRandomNum value below
newBall = theObjectballPools[lastRandomNum].GetPooledObject();
}
int RandomWithExclusion(int min, int max, int exclusion)
{
var result = UnityEngine.Random.Range(min, max - 1);
return (result < exclusion) ? result : result + 1;
}
Try linq :
public class Ball
{
public static List<Ball> balls = new List<Ball>();
public int value { get; set; }
public Boolean active { get; set; }
public Ball() {}
public Ball(int size)
{
// initial class
Random rand = new Random();
for (int i = 0; i < size; i++)
{
balls.Add(new Ball(){ value = rand.Next(), active = false});
}
}
public Ball GetRandom()
{
Random rand = new Random();
Ball randomBall = balls.Where(x => x.active == false).Select((x) => new { value = x, randX = rand.Next() }).OrderBy(x => x.randX).FirstOrDefault().value;
randomBall.active = true;
return randomBall;
}
}
im frenchi so sorry first sorry for my english .
I have an error on visual studio (index out of range) i have this problem only with a Parallel.For not with classic for.
I think one thread want acces on my array[i] and another thread want too ..
It's a code for calcul Kmeans clustering for building link between document (with cosine similarity).
more information :
IndexOutOfRange is on similarityMeasure[i]=.....
I have a computer with 2 Processor (12logical)
with classic for , cpu usage is 9-14% , time for 1 iteration=9min..
with parallel.for , cpu usage is 70-90% =p, time for 1 iteration =~1min30
Sometimes it works longer before generating an error
My function is :
private static int FindClosestClusterCenter(List<Centroid> clustercenter, DocumentVector obj)
{
float[] similarityMeasure = new float[clustercenter.Count()];
float[] copy = similarityMeasure;
object sync = new Object();
Parallel.For(0, clustercenter.Count(), (i) => //for(int i = 0; i < clustercenter.Count(); i++) Parallel.For(0, clustercenter.Count(), (i) => //
{
similarityMeasure[i] = SimilarityMatrics.FindCosineSimilarity(clustercenter[i].GroupedDocument[0].VectorSpace, obj.VectorSpace);
});
int index = 0;
float maxValue = similarityMeasure[0];
for (int i = 0; i < similarityMeasure.Count(); i++)
{
if (similarityMeasure[i] > maxValue)
{
maxValue = similarityMeasure[i];
index = i;
}
}
return index;
}
My function is call here :
do
{
prevClusterCenter = centroidCollection;
DateTime starttime = DateTime.Now;
foreach (DocumentVector obj in documentCollection)//Parallel.ForEach(documentCollection, parallelOptions, obj =>//foreach (DocumentVector obj in documentCollection)
{
int ind = FindClosestClusterCenter(centroidCollection, obj);
resultSet[ind].GroupedDocument.Add(obj);
}
TimeSpan tempsecoule = DateTime.Now.Subtract(starttime);
Console.WriteLine(tempsecoule);
//Console.ReadKey();
InitializeClusterCentroid(out centroidCollection, centroidCollection.Count());
centroidCollection = CalculMeanPoints(resultSet);
stoppingCriteria = CheckStoppingCriteria(prevClusterCenter, centroidCollection);
if (!stoppingCriteria)
{
//initialisation du resultat pour la prochaine itération
InitializeClusterCentroid(out resultSet, centroidCollection.Count);
}
} while (stoppingCriteria == false);
_counter = counter;
return resultSet;
FindCosSimilarity :
public static float FindCosineSimilarity(float[] vecA, float[] vecB)
{
var dotProduct = DotProduct(vecA, vecB);
var magnitudeOfA = Magnitude(vecA);
var magnitudeOfB = Magnitude(vecB);
float result = dotProduct / (float)Math.Pow((magnitudeOfA * magnitudeOfB),2);
//when 0 is divided by 0 it shows result NaN so return 0 in such case.
if (float.IsNaN(result))
return 0;
else
return (float)result;
}
CalculMeansPoint :
private static List<Centroid> CalculMeanPoints(List<Centroid> _clust)
{
for (int i = 0; i < _clust.Count(); i++)
{
if (_clust[i].GroupedDocument.Count() > 0)
{
for (int j = 0; j < _clust[i].GroupedDocument[0].VectorSpace.Count(); j++)
{
float total = 0;
foreach (DocumentVector vspace in _clust[i].GroupedDocument)
{
total += vspace.VectorSpace[j];
}
_clust[i].GroupedDocument[0].VectorSpace[j] = total / _clust[i].GroupedDocument.Count();
}
}
}
return _clust;
}
You may have some side effects in FindCosineSimilarity, make sure it does not modify any field or input parameter. Example: resultSet[ind].GroupedDocument.Add(obj);. If resultSet is not a reference to locally instantiated array, then that is a side effect.
That may fix it. But FYI you could use AsParallel for this rather than Parallel.For:
similarityMeasure = clustercenter
.AsParallel().AsOrdered()
.Select(c=> SimilarityMatrics.FindCosineSimilarity(c.GroupedDocument[0].VectorSpace, obj.VectorSpace))
.ToArray();
You realize that if you synchronize the whole Content of the Parallel-For, it's just the same as having a normal synchrone for-loop, right? Meaning the code as it is doesnt do anything in parallel, so I dont think you'll have any Problems with concurrency. My guess from what I can tell is clustercenter[i].GroupedDocument is propably an empty Array.
In my code I have a nested loop which does not iterate with the exception of an if statement that always occurs no matter what the condition. Without the if statement the portion of the for loop's code which iterates the loop becomes unreachable. No matter what I have tried I have not been able to get the inside loop to iterate.
class Map
{
public int Width { get; set; }
public int Height { get; set; }
public Vector2[] positions = new Vector2[500*500];
private GroundVoxel[,] map = new GroundVoxel[500, 500];
private Vector2 voxelPosition = new Vector2(0,0);
private static int sizeX = 499, sizeY = 499, airLevel = 425;
private int positionX = 0, positionY = 0, vectorNumber = 0;
public Map()
{
}
public Vector2[] Initialize()
{
for (int i = 0; i <= sizeY; i++)
{
for (int j = 0; j <= sizeX; j++) <-- This does not iterate.
{
map[positionX, positionY] = new GroundVoxel(voxelPosition);
voxelPosition.X += 80;
positions[vectorNumber] = voxelPosition;
vectorNumber += 1;
if (j == sizeX) <-- This always executes even though j != sizeX.
{
break;
}
}
voxelPosition.Y += 80;
voxelPosition.X = 0;
}
return positions;
}
}
}
You have to use the fully qualified name to refer to a static class member variable like your sizeX and sizeY. Here is an article on the subject.
Hope this helps!
I think we'll need more code. I've copied your code into a basic winforms test application and both of my loops iterates as expected.
I'm not familiar with XNA or what a "VoxelPosition" is, but I think you have a lurking bug here:
voxelPosition.X += 80;
positions[vectorNumber] = voxelPosition;
You are simply storing the same pointer in a very large array -- all of the entries will be pointing to the same object.
You will need to declare another object every time through the loop to store individal vector entries.
Hope this helps?