void Start() {
rch = Random.Range(0, 20);
ball = GameObject.FindGameObjectWithTag("Ball");
if (rch % 2 == 0) {
ball.GetComponent<SpriteRenderer>().sprite = s1;
}
else
{
ball.GetComponent<SpriteRenderer>().sprite = s2;
}
Debug.Log(rch);
}
I have the following code which is supposed to select a number between 0 and 20 and if the number is divisible with 2 spawn one spite and otherwise the other.
The code is called every time the object is destroyed and that's why I use the start function. With Debug.Log(rch), I print the random number and even if the number is not divisible by 2, I only get the ball1.
Related
So here's the thing. I have a game in which I have a spawner - to spawn obstacles. And I want after every 5th obstacle to increase the speed. Example: 1st, 2nd, 3rd, 4th, 5th obstacles have default speed = 5 and I want 6th, 7th, 8th, 9th, 10th to have an increased speed to speed = 10 and etc. I already have some nested if statements,but I want to inscrease the speed infitely for example to have speed = 1000 for the 100th obstacle. Here's my code:
IEnumerator SpawnObstacles()
{
int i = 0;
do
{
var randomTime = Random.Range(minTime, maxTime);
var randomObstacle = Random.Range(0, obstacles.Length);
yield return new WaitForSeconds(randomTime);
var obstacle = Instantiate(obstacles[randomObstacle], transform.position, Quaternion.identity);
Destroy(obstacle, 10f);
i++;
if(i >= 10)
{
IncreaseSpeed();
if(i >= 20)
{
IncreaseSpeed();
if(i >= 30)
{
IncreaseSpeed();
}
}
}
}
while (true);
}
private void IncreaseSpeed()
{
Obstacle obs = FindObjectOfType<Obstacle>();
obs.speed += 5f;
}
The modulo operator % helps with things like this. It gives the remainder of the division operation, for example:
3%5 is 3
4%5 is 4
5%5 is 0
6%5 is 1
7%5 is 2
8%5 is 3
9%5 is 4
10%5 is 0
So if your x is starting at 0, and you want to increase speed every 5, you just look at whenever the modulo is 4..
x can go as high as you like (well, int.MaxValue) but the modulo will always be 0..4:
//do some stuff
//should we increase speed?
if(x % 5 == 4)
IncreaseSpeed();
Handy tool for making circular arrays too.. someArray[i % someArray.Length] will never go out of bounds, because the result of a modulo is always between 0 and one less than the length
What you could do instead is either :
Keep track of how many obstacle instances you've spawned so far using a variable(maybe a static variable https://www.c-sharpcorner.com/UploadFile/1ce252/static-variables-and-static-methods-in-C-Sharp/ ) and make sure to simply increase the speed for every 5 instances using modulo %. You can take a look for more information here : https://blog.mattclemente.com/2019/07/12/modulus-operator-modulo-operation.html
A quick introduction to Modulos:
//It essentially shows the rest of a division
5 / 5 == 1
//Since there's no rest there,
5 % 5 == 0
//But in the case of where there is a rest
6 / 5 == 1 (Rest 1)
//Hence
6 % 5 == 1
//Other examples :
7 % 5 == 2
8 % 5 == 3
9 % 5 == 4
10 % 5 == 0 //!! The result is back to zero here as 10/5 == 2 with no Rest
Implement a recursive function that's in the Object that spawns in another object with the same attributes but pass on a parameter which indicates how many instances have been spawned so far and check if it's the 5th instance, if so add speed to it.
You have a Coroutine in an infinite loop anyway ... why not simply do
IEnumerator SpawnObstacles()
{
do
{
for(var x = 0; x < 5; x++)
{
var randomTime = Random.Range(minTime, maxTime);
var randomObstacle = Random.Range(0, obstacles.Length);
yield return new WaitForSeconds(randomTime);
var obstacle = Instantiate(obstacles[randomObstacle], transform.position, Quaternion.identity);
Destroy(obstacle, 10f);
}
// These lines are automatically reached after every 5 iterations
// no need for any módulo or other magic check
Obstacle obs = FindObjectOfType<Obstacle>();
obs.speed += 5f;
}
while (true);
}
Or since I'm not sure of this entire FindObjectWithTag thingy ... actually it seems to me it is the same object you Instantiate right? So why not simply
IEnumerator SpawnObstacles()
{
var speed = 5;
do
{
for(var x = 0; x < 5; x++)
{
var randomTime = Random.Range(minTime, maxTime);
var randomObstacle = Random.Range(0, obstacles.Length);
yield return new WaitForSeconds(randomTime);
var obstacle = Instantiate(obstacles[randomObstacle], transform.position, Quaternion.identity);
obstacle.GetComponent<Obstacle>().speed = speed;
Destroy(obstacle, 10f);
}
// These lines are automatically reached after every 5 iterations
// no need for any módulo or other magic check
speed += 5f;
}
while (true);
}
Though to me it stays a bit unclear how exactly your speed shall grow. From your description it sounds like you want to add 5 after every group of iterations .. however this would mean you have speed = 100 (20*5) for the 100th object .. not speed = 1000 as you wrote
The simplest thing i can think of is setting a counter for the spawned obstacles and incrementing the speed after it reaches 5 and resetting the counter to zero. You don't really need to get into the fancy stuff for something so simple just use an if statement to check the counter.Hope I helped, cheers!
I am trying to make a program for a game of pig where there user enters a point total to play for and then takes turns with a computer player until one player reaches the point total. For the human turn the player rolls and if they roll 2-6 then they can use r to roll again or h to hold. when hold is selected it adds up the total points and goes to the next turn. If 1 is rolled then they get 0 points for the round and it goes to the computers turn. For some reason when I select h to hold it just keeps going and when it does end the points don't get added up. Not sure how to fix this
any help would be appericated
static int pigRoll()
{
Random random = new Random();
int die1 = 0;
die1 = random.Next(1, 6);
Console.WriteLine($"You rolled {die1}");
return die1;
}
static double humanTurn()
{
double pointTotal = 0;
string gameSelect = null;
var pigDiceRoll = 0;
Console.WriteLine("It's your turn");
do
{
pigDiceRoll = pigRoll();
if (pigDiceRoll != 1)
{
Console.WriteLine("r to roll or h to hold (r/h)");
gameSelect = Console.ReadLine();
pointTotal = pointTotal + pigDiceRoll;
}
else if(pigDiceRoll ==1)
{
pointTotal = 0;
}
} while (gameSelect != "r" || pigDiceRoll != 1);
Console.WriteLine($"Your turn point total is {pointTotal}");
return pointTotal;
}
The while statement should read:
while (gameSelect == "r" && pigDiceRoll != 1)
This translates to keep looping while the user wants to roll again and they didn't roll a 1.
Alternatively you could use:
while (!(gameSelect != "r" || pigDiceRoll == 1))
Both are logically the same, but the first is probably easier to read.
I have 4 colors. I want to make it so that the player can't be the same color 2 times in a row. When a player collides with an object, the RandomColor() is called. So this function is called many times during the game and sometimes the player does not change his color.
using UnityEngine;
public class ColorManager : MonoBehaviour {
public SpriteRenderer player;
public string playerColor;
public Color[] colors = new Color[4];
private void Awake()
{
RandomColor();
}
public void RandomColor()
{
int index = Random.Range(0, 4);
switch (index)
{
case 0:
player.color = colors[0]; //colors[0] is orange
playerColor = "orange";
break;
case 1:
player.color = colors[1]; //colors[1] is pink
playerColor = "pink";
break;
case 2:
player.color = colors[2]; //colors[2] is blue
playerColor = "blue";
break;
case 3:
player.color = colors[3]; //colors[3] is purple
playerColor = "purple";
break;
}
}
}
Tried using while loop, do while loop, but I'm obviously doing it wrong, since I receive the same color twice in a row sometimes. It would be great if anyone figures it out and explains how/why it works, because I spent a big chunk of time on the issue and I am very curious.
First, you need a function that can generate a random number with exclusion. Below is what I use for that:
int RandomWithExclusion(int min, int max, int exclusion)
{
int result = UnityEngine.Random.Range(min, max - 1);
return (result < exclusion) ? result : result + 1;
}
Each time you call it, you need to store the result in a global variable so that you will pass that to the exclusion parameter next time you call it again.
I modified the function so that you don't have to do that each time it is called. The new RandomWithExclusion function will do that for you.
int excludeLastRandNum;
bool firstRun = true;
int RandomWithExclusion(int min, int max)
{
int result;
//Don't exclude if this is first run.
if (firstRun)
{
//Generate normal random number
result = UnityEngine.Random.Range(min, max);
excludeLastRandNum = result;
firstRun = false;
return result;
}
//Not first run, exclude last random number with -1 on the max
result = UnityEngine.Random.Range(min, max - 1);
//Apply +1 to the result to cancel out that -1 depending on the if statement
result = (result < excludeLastRandNum) ? result : result + 1;
excludeLastRandNum = result;
return result;
}
Test:
void Update()
{
Debug.Log(RandomWithExclusion(0, 4));
}
The last number will never appear in the next function call.
For your specific solution, simply replace
int index = Random.Range(0, 4);
with
int index = RandomWithExclusion(0, 4);
What you need to do is add a judgement if the RandomColor returns a same color as prev one, just call it again, easy right?
I am trying to assigned a Enemy enemy class instance to a random newenemy instance.
For example:
public Enemy GetEnemy()
{
Random rand = new Random();
Enemy newenemy = new Enemy(string.Empty, 0, 0, 0, 0, 0);
if (Main.level == 1)
{
int z = rand.Next(0, 2);
if (z == 0)
{
newenemy = new Enemy("Chicken", 50, 0, 4, 11, 32);
}
else if (z == 1)
{
newenemy = new Enemy("Common Goblin", 67, 0, 8, 14, 36);
}
else if (z == 2)
{
newenemy = new Enemy("Rabbit", 50, 0, 15, 25, 9);
}
}
return newenemy;
}
Which is then used in my Battle function: (I'll post some cause it is somewhat long)
if (whathappen == 2 || whathappen == 4 || whathappen == 6 || whathappen == 8 || whathappen == 10) //battle code
{
Console.Write("You were engaged by the enemy! \nYou are fighting an enemy {0}\n", GetEnemy().name);
while (Main.health > 0 || GetEnemy().health > 0)
{
Console.Write("1) Attack With Weapon ");
int choose;
int.TryParse(Console.ReadLine(), out choose);
if (choose == 1)
{
int miss = r.Next(0, 6);
if (miss < 6)
{
int totaldamage = (r.Next(0, Main.RHand.damage) + r.Next(0, Main.LHand.damage)) - GetEnemy().armor;
GetEnemy().health -= totaldamage;
Console.WriteLine("You attack the {0} with a {1} and deal {2} damage!", GetEnemy().name, Main.RHand.name, totaldamage);
Console.WriteLine("The {0} has {1} health remaning!", GetEnemy().name, GetEnemy().health);
However, when I am testing my game, no enemy is assigned during the battle and I don't understand why. This is the output:
You were engaged by the enemy!
You are fighting an enemy! (The enemy name should come after enemy)
You attack the (name should be here again) with a Bronze Dagger and deal 15 damage!
Can anyone explain why this is happeneing?
There's a few problems with your code:
Based on your description of your problem, my guess is that Main.level is not equal to 1
You're not quite using Random.Next correctly: Random.Next(0, 2) will never equal 2
But even after you fix those problems, you have a bigger issue that you're creating way too many instances of your Enemy and you aren't saving them anywhere.
Every time you call your GetEnemy() method you're making a brand new instance of your class, accessing one property on it, then it's getting discarded. You are attempting to maintain the state of your enemy, you will need to save the instance you create and reuse it, e.g.:
Enemy enemy = GetEnemy();
while (Main.health > 0 || enemy.health > 0)
{
.
.
.
}
I implemented code that would check whether the ufo's X position is greater than the width of the game screen. Then if it is, the ufo is dead.
I have also implemented code that generates a new number if the ufo is dead, in which case, when the right number is generated, then the saucer should fly across the screen.
I don't know why it isn't doing that. The saucer only flys across once, randomly.
The code for the saucer is below:
if (ufo.alive == true)
{
// also, we need to make it move
ufo.Xpos = ufo.Xpos + 1;
if (MissileFired != null)
{
// if you miss, and the ufo carries on, it will go forever.
//so
if (ufo.Xpos > 1000)
{
// kill the ufo if it goes off the screen.....
ufo.alive = false;
}
the code to generate the random number is:
if (ufo.alive == false)
{
Random random = new Random();
int randomNumber = random.Next(0, 100);
{
if (randomNumber == 1)
ufo.alive = true;
}
As you can see, I don't know why it doesn't generate the ufo again after it has flown across and off the screen.
Dont create a new random every cycle.
take out of your Update method and declare it as:
class Game1: Game {
public static readonly Random random = new Random(DateTime.Now.Millisecs);
....
}
....
if (ufo.alive == false) {
int randomNumber = Game1.random.Next(0, 100);
if (randomNumber == 1)
{
ufo.alive = true;
ufo.Xpos = 0;
}
}