- Home /
How can I randomly create a number and then delete it to stop repeating
I am trying to create some code that randomly picks from 1 to 5 so it would come up with a result from 1 to 4 and once its randomly picked/generated I want to delete from the list therefore disabling repeating. Here is the code I have and the error I receive (Argument is out of range)
public class GameManager2 : MonoBehaviour
{
public GameObject Question1, Question2, Question3;
List<int> list = new List<int>();
private int i, index;
void Start ()
{
for (int n = 1; n < 5; n++)
{
list.Add(n);
}
CheckQuestion();
}
void Update ()
{
if (Input.GetKeyDown(KeyCode.UpArrow))
{
CheckQuestion();
}
if (i == 1)
{
Question1.SetActive(true);
Question2.SetActive(false);
Question3.SetActive(false);
}
if (i == 2)
{
Question2.SetActive(true);
Question1.SetActive(false);
Question3.SetActive(false);
}
if (i == 3)
{
Question3.SetActive(true);
Question1.SetActive(false);
Question2.SetActive(false);
}
}
void CheckQuestion()
{
index = Random.Range(0, list.Count - 1);
i = list[index];
Debug.Log(i);
list.RemoveAt(index);
}
Answer by Vega4Life · Nov 16, 2018 at 03:54 PM
Here is something I quickly made - Just link your question objects into the list:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Questions : MonoBehaviour
{
[SerializeField] List<GameObject> questionObjects;
List<GameObject> questionCopies;
GameObject currentQuestion;
void Awake()
{
questionCopies = new List<GameObject>(questionObjects);
HideAllQuestions();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.UpArrow))
{
GetQuestion();
}
}
void GetQuestion()
{
// If we have questions, show one - if not, hide them all
if (questionCopies.Count > 0)
{
GameObject newQuestion = questionCopies[Random.Range(0, questionCopies.Count)];
DisplayQuestion(newQuestion);
// Save the new current
currentQuestion = newQuestion;
// Remove so we don't get it again
questionCopies.Remove(currentQuestion);
}
else
{
HideCurrentQuestion();
}
}
void DisplayQuestion(GameObject question)
{
// Hide them all
HideCurrentQuestion();
// Show the new one
question.SetActive(true);
}
void HideCurrentQuestion()
{
if (currentQuestion != null)
{
currentQuestion.SetActive(false);
}
}
/// <summary>
/// Turn them off in case they were on in the editor
/// </summary>
void HideAllQuestions()
{
for (int i = 0; i < questionCopies.Count; i++)
{
questionCopies[i].SetActive(false);
}
}
}
This code to what I can see does not remove the question that has already appeared once. What I need to have is to activate my gameobject only once and then have that gameobject removed from the list to prevent any questions appearing two times or more
With this code, a question will only appear once. The question that is selected gets removed from questionsCopies, thus can never show again.
Hey sorry turned out I had not replace the gameobjects from the list thus duplicates. Sorry for the doubt.
Answer by UnityCoach · Nov 12, 2018 at 12:27 PM
There's a bit of confusion I guess with your values starting at 1, but indices starting at 0.
int Random.Range()
never returns the max value, so if you List contains 1, 2, 3, 4, and you want a random number from that list, you can use this :
index = Random.Range(0, list.Count);
Which will return a value between 0 and 3, mapping to the table containing 1 to 4.
Otherwise, Count -1 will eventually return -1 when the list is empty, hence your issue I guess.
Also, it's unrelated, but you can save yourself some complexity with the if statements by simply doing this :
Question1.SetActive(i == 1);
Question2.SetActive(i == 2);
Question3.SetActive(i == 3);
Hope this helps.
Forgot to mention, you want to take the SetActive() out of Update(), you can do it from CheckQuestion so that it doesn't trigger every frame.
Answer by Hellium · Nov 12, 2018 at 12:30 PM
public GameObject[] Questions;
private List<int> QuestionIndices ;
void Start ()
{
if( Questions.Length == 0 )
{
Debug.LogError("No question provided!");
enabled = false ;
return ;
}
PickQuestion( PickQuestionIndex() );
}
void Update ()
{
if (Input.GetKeyDown(KeyCode.UpArrow))
{
PickQuestion( PickQuestionIndex() );
}
}
private void FillQuestionIndices()
{
if( QuestionIndices == null )
QuestionIndices = new List<int>(Questions.Length);
for( int i = 0 ; i < Questions.Length ; ++i )
QuestionIndices.Add( i ) ;
}
private void PickQuestion( int questionIndex )
{
for( int i = 0 ; i < Questions.Length ; ++i )
Questions[i].SetActive( false ) ;
if( questionIndex >= 0 && questionIndex && < Questions.Length )
Questions[questionIndex].SetActive( true ) ;
}
private int PickQuestionIndex()
{
if( QuestionIndices.Count == 0 )
FillQuestionIndices();
int listIndex = Random.Range(0, QuestionIndices.Count) ;
int questionIndex = QuestionIndices[listIndex];
QuestionIndices.RemoveAt(listIndex);
return questionIndex ;
}
I tried your code but the lines : QuestionIndices[questionIndex].SetActive(true); int listIndex = Random.Range(0, list.Count); list.RemoveAt(listIndex); They show up as not correct can you please explain why ?
What do you mean by "they show up as not correct"? Do you have any error in the console?
Your answer
Follow this Question
Related Questions
How to make enemy prefab spawn at random times between 1.0f to 10.0f. 1 Answer
Script sets color to multiple objects from instead of only one object with Random.range() 0 Answers
How to instantiate prefabs at random postions in 2d 1 Answer
Random.Range is the same in each object with the script 0 Answers
Semi-Random Or Engine 1 Answer