Как создать 3 рандомных неповторяющихся объекта из списка? Сначала я создал список, который фильтрует объекты.
Код
public void characterFilter() { List<CharactersDie> FilteredData = new List<CharactersDie> (); foreach (CharactersDie C in characters) { if (C.characterReads == 0) // если объект еще не создавался, //то это значение равно 0, если создавался, то оно равно 1 FilteredData.Add (C); }
Как из этого списка мне создать 3 рандомных и не повторяющихся объекта? Если поможет, вот полный код
Код
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;
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]); } }
* Не понял, что ты хочешь сделать. Что значит "рандомных неповторяющихся"? Объясни "что" тебе надо, а не "как". * Конечно это не работает:
Код
int prefabIndex = UnityEngine.Random.Range (0, C); // это не работает
нужно передавать два числа. * Возможно ты хочешь перемешать список FilteredData, чтобы потом создать в случайной последовательности? Реализация Shuffle здесь http://stackoverflow.com/questions/273313/randomize-a-listt. Только всё равно не понимаю, какая разница в какой последовательности создавать.
Lertmind, у меня в игре есть много персонажей. Я хочу, что бы 3 из них появлялись, и что бы те, которые появились в этот раз, не появлялись в следующие разы. Ну и, конечно же, что бы не появлялись одновременно одинаковые персонажи. Сейчас опишу последовательность которую делает игрок. Игрок подходит к стойке с книгой. Камера приближается к столу(сделано), и на нем спустя n секунд появляются персонажи из списка, в количестве 3х штук. На каждого из персонажей можно нажать, и тогда появится его биография. После этого, можно убить одного из персонажей. Тогда все 3 удаляются и создаются 3 новых персонажа. Но не создаются те, которые уже были на столе. Вот картинка со столом, что бы было понятнее.
Сообщение отредактировал dreenline - Среда, 08 Июня 2016, 21:31
Добавлено (08 июня 2016, 21:26) --------------------------------------------- Тогда смотри ссылку выше, что дал. После "фильтрации" используешь функцию из документации и отмечаешь тех, которые были.
Добавлено (08 июня 2016, 21:28) --------------------------------------------- Ещё вместо специальной переменной, можно просто из списка characters удалять персонажей, которые были, тогда не придётся фильтровать каждый раз.
Добавлено (08 июня 2016, 21:32) --------------------------------------------- На самом деле, можно просто один раз перемешать с помощью Shuffle в Awake() массив characters и без фильтра брать первые 3 элемента и удалять их (лучше characters сделать списком).
Добавлено (08 июня 2016, 21:42) --------------------------------------------- Как-то так:
Код
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 List<CharactersDie> characters; public GameObject deathBookCamera; public GameObject characterControll; public float loadDelay;
public void characterFilter() { int count = Mathf.Min(3, characters.Count); for (int i = 0; i < count; i++) { Instantiate(characters[i]); } characters.RemoveRange(0, count); }
public static void Shuffle<T>(this IList<T> list) { int n = list.Count; while (n > 1) { n--; int k = rng.Next(n + 1); T value = list[k]; list[k] = list[n]; list[n] = value; } }
Shuffle надо перенести в отдельный класс хелперов, рандом заменить можно на тот, что у Unity. Код не компилировал.
Добавлено (08 июня 2016, 22:01) ---------------------------------------------
Цитатаdreenline ()
и на нем спустя n секунд появляются персонажи из списка, в количестве 3х штук. На каждого из персонажей можно нажать, и тогда появится его биография. После этого, можно убить одного из персонажей. Тогда все 3 удаляются и создаются 3 новых персонажа. Но не создаются те, которые уже были на столе.
Сейчас увидел дополнение. Проблем нет, можно поступить разными путями. Один из них, как ты фильтровал, а потом вместо твоего нерабочего кода делаешь "Выбор элементов из набора без повторений" и отмечаешь, которые были. Это я уже писал, только другими словами.
Сообщение отредактировал Lertmind - Среда, 08 Июня 2016, 22:03
characters = new List<CharactersDie>(GameObject.FindGameObjectsWithTag("Character"));
на
Код
characters = new List<CharactersDie>(GameObject.FindGameObjectsWithTag("Character"));
потому что выскакивала ошибка
Сейчас вылазит 2 ошибки
Type `System.Collections.Generic.List<CharactersDie>' does not contain a definition for `Shuffle' and no extension method `Shuffle' of type `System.Collections.Generic.List<CharactersDie>' could be found (are you missing a using directive or an assembly reference?)
На сколько я понимаю, он не находит к чему применить shuffle И
Assets/scripts/LevelManagerScript.cs(99,37): error CS1061: Type `UnityEngine.Random' does not contain a definition for `Next' and no extension method `Next' of type `UnityEngine.Random' could be found (are you missing a using directive or an assembly reference?)
на сколько я понял, тут тоже самое.
В любом случае спасибо большое за помощь! Под конец дня голова уже не соображает, попробую разобраться утром
Первая ошибка кажется из-за Random, там использует из System. Попробуй заменить Random на System.Random:
Код
private static System.Random rng = new System.Random();
public static void Shuffle<T>(this IList<T> list) { int n = list.Count; while (n > 1) { n--; int k = rng.Next(n + 1); T value = list[k]; list[k] = list[n]; list[n] = value; } }
Добавлено (08 июня 2016, 22:22) --------------------------------------------- Заметь, что мой код не учитывает твою переменную, где сохраняется, что персонаж уже был. Потому что, тебе возможно она нужна в другом коде.
Сообщение отредактировал Lertmind - Среда, 08 Июня 2016, 22:22
Lertmind, всё равно, та же самая ошибка LevelManagerScript.Shuffle<T>(this System.Collections.Generic.IList<T>)': Extension methods must be defined in a non-generic static class
dreenline, точно, забыл что все расширения надо в статических классах определять. Создай ещё файл и туда добавь класс, например static class MyExtensions, в него перенеси, кажется так:
Код
using System; using System.Collections.Generic;
static class MyExtensions { private static System.Random rng = new System.Random();
public static void Shuffle<T>(this IList<T> list) { int n = list.Count; while (n > 1) { n--; int k = rng.Next(n + 1); T value = list[k]; list[k] = list[n]; list[n] = value; } } }
Lertmind, Спасибо! Вроде работает! Можно еще вопрос? Почему, когда я меняю
Код
characters = new List<CharactersDie>(FindObjectsOfType<CharactersDie> ());
на
Код
characters = new List<CharactersDie>(GameObject.FindGameObjectsWithTag("Characters"));
мне выдает ошибки
The best overloaded method match for `System.Collections.Generic.List<CharactersDie>.List(System.Collections.Generic.IEnumerable<CharactersDie>)' has some invalid arguments
Argument `#1' cannot convert `UnityEngine.GameObject[]' expression to type `System.Collections.Generic.IEnumerable<CharactersDie>'