First, I created a list that filters objects.

To make it clearer, I will describe what the player is doing. The player comes to the rack with a book. The camera is approaching the table (done), and after n seconds, characters from the list appear, in an amount of 3 pieces. You can click on each of the characters, and then his biography will appear. After that, you can kill one of the characters. Then all 3 are removed and 3 new characters are created. But do not create those that were already on the table.

public void characterFilter() { List<CharactersDie> FilteredData = new List<CharactersDie> (); foreach (CharactersDie C in characters) { // если объект еще не создавался, то это значение равно 0 // если создавался, то оно равно 1 if (C.characterReads == 0) FilteredData.Add (C); } Как из этого списка мне создать 3 рандомных и не повторяющихся объекта? 

If it helps, here is the complete code.

 using UnityEngine; using System.Collections; using UnityStandardAssets.Characters.FirstPerson; using System.Collections.Generic; public class LevelManagerScript: MonoBehaviour { public UnityStandardAssets.Characters.FirstPerson.FirstPersonController controller; private Books playerReadings; private RayCastScript rayCast; public GameObject openBook; private OpenBook openBooks; private CharactersDie[] characters; public GameObject deathBookCamera; public GameObject characterControll; public float loadDelay; // Use this for initialization void Awake() { controller = FindObjectOfType<FirstPersonController>(); playerReadings = FindObjectOfType<Books>(); rayCast = FindObjectOfType<RayCastScript>(); Cursor.visible = false; characters = FindObjectsOfType<CharactersDie>(); //openBook = GameObject.FindGameObjectWithTag ("OpenBook"); } void Start() { } // Update is called once per frame void Update() { //if (playerReadings.playerReading) { // Cursor.visible = true; //} else // Cursor.visible = false; } public void reading() { controller.enabled = false; rayCast.enabled = false; Cursor.visible = true; } public void StopReading() { openBooks = FindObjectOfType<OpenBook>(); rayCast.enabled = true; //openBook.TextCanvas.SetActive(false); openBooks.OpenBookTextCanvas.SetActive(false); openBooks.oneText.SetActive(false); openBooks.twoText.SetActive(false); openBooks.threeText.SetActive(false); openBooks.fourText.SetActive(false); playerReadings.playerReading = false; controller.enabled = true; Cursor.visible = false; } public void characterFilter() { List <CharactersDie> FilteredData = new List<CharactersDie>(); foreach(CharactersDie C in characters) { if (C.characterReads == 0) FilteredData.Add(C); } foreach(CharactersDie C in FilteredData) { int prefabIndex = UnityEngine.Random.Range(0, C); // это не работает Instantiate(FilteredData[prefabIndex]); } } public void deathBookCameraActivate() { characterControll.SetActive(false); deathBookCamera.SetActive(true); Cursor.visible = true; } public void deathBookCameraDisActivate() { characterControll.SetActive(true); deathBookCamera.SetActive(false); Cursor.visible = false; } } 
  • And // это не работает what does it mean? method does not work? or does not work as you expect? - Alexey Shimansky
  • If you are given an exhaustive answer, mark it as correct (a daw opposite the selected answer). - Nicolas Chabanovsky
  • @dreenline added just in case even a way with LINQ - Alexey Shimansky

2 answers 2

First, when you do Range(0, C); You are trying to make random numbers in the range from 0 to an object of type CharactersDie . Range takes two numbers as parameters. That is, in general there should have been an error and no compilation in principle. How it did not show a mistake - I do not understand.

Secondly, to generate random and unique elements, most likely you need to create another sheet that will store the generated values. For example:

 List<int> randomList = new List<int>(); for ( ; randomList.Count < 3; ) { var random = UnityEngine.Random.Range(0, FilteredData.Count); if (!randomList.Contains(random)) { randomList.Add(random); Instantiate(FilteredData[random]); } } randomList.Clear(); 

Here is how it looks simple in C #: http://ideone.com/dhBT3J

What's going on here?

A cycle is organized until 3 objects are accumulated in the random list. How unique will get there? It's simple: in the cycle we say "hey, randomist, but do you (Contains) already generated a number (random)? No? Well then add to me and install at the same time. And if you do, go to a new circle!" At the end of the cycle clean the sheet. Just in case.

Thirdly: I am sure that instead of two cycles it is possible to make everything shorter using LINQ . but you can try to do this yourself by reading about this language.


Here's something you can do with LINQ (in your example):

 public void characterFilter() { var filteredData = charactersDie.Where(item => item.characterReads == 1).ToList(); var numbers = Enumerable.Range(0, filteredData.Count).OrderBy(n => n * n * (new Random()).Next()).Take(3); // Инстанциировать рандомные объекты foreach (var number in numbers) { Instantiate(filteredData[number]); } } 

As an example: http://ideone.com/QviKXq

    If the list is small, you can create two more lists: Put the original copy of the original into the first one and drag the item to the second list by looping over the random with decreasing maximum value. Get an unordered initial list from which you will pull out 3 objects each.

     List<object> Original = new List<object>(10); //как то его заполнили List<object> OriginalCopy = Original.ToList(); //ну или как нибудь по другому скопировать List<object> RandomList = new List<object>(); int count = OriginalCopy.Count; int maxRange = count; for (int i = 0; i < count - 1; i++) { //честно не помню, выдает рандом ошибку если min-max одинаковые или нет, //если нет, тогда цикл до count прогоняете, а 2 последние строчки не нужны. int index = UnityEngine.Random.RandomRange(0, maxRange--); RandomList.Add(OriginalCopy[index]); OriginalCopy.RemoveAt(index); } RandomList.Add(OriginalCopy[0]); OriginalCopy.Clear(); 

    Then, if repeated cycles are needed, you can assign OriginalCopy used RandomList to OriginalCopy, and run the already mixed list.