Ни для кого не секрет, что использованные объекты надо "чистить" и удалять со сцены. Однако в действительности это достаточно вредный процесс. Особенно когда мы говорим об объектах которые очень часто создаются/удаляются.
Это могут быть и мобы, и пули, или любые другие мелкие и возобновляемые объекты. Суть в том, чтобы не уничтожать а изначально вгрузить на уровень предполагаемое кол-во объектов и активировать их понадобности, возвращая потом обратно в пул.
Вот скрипт. Обзывать обязательно GameObjectPool.cs
Code
using UnityEngine; using System; using System.Collections; namespace pools { public class GameObjectPool {
available = (initialCapacity > 0) ? new Stack((int) initialCapacity) : new Stack(); all = (initialCapacity > 0) ? new ArrayList((int) initialCapacity) : new ArrayList(); }
#endregion // ---- public methods ---- #region public methods
public GameObject Spawn(Vector3 position, Quaternion rotation) { GameObject result;
if (available.Count == 0){
// create an object and initialize it. result = GameObject.Instantiate(prefab, position, rotation) as GameObject;
// run optional initialization method on the object if (initAction != null) initAction(result);
all.Add(result);
} else { result = available.Pop() as GameObject;
// get the result's transform and reuse for efficiency. // calling gameObject.transform is expensive. Transform resultTrans = result.transform; resultTrans.position = position; resultTrans.rotation = rotation;
SetActive(result, true); }
return result; }
public bool Destroy(GameObject target) { if (!available.Contains(target)) { available.Push(target);
SetActive(target, false); return true; }
return false; }
// Unspawns all the game objects created by the pool. public void DestroyAll() { for (int i=0; i<all.Count; i++) { GameObject target = all[i] as GameObject;
if (target.active) Destroy(target); } }
// Unspawns all the game objects and clears the pool. public void Clear() { DestroyAll(); available.Clear(); all.Clear(); }
public bool Unspawn (GameObject obj) { if (!available.Contains (obj)) { // Make sure we don't insert it twice. available.Push (obj); SetActive (obj, false); return true; // Object inserted back in stack. } return false; // Object already in stack.
}
// Applies the provided function to some or all of the pool's game objects. public void ForEach(Action<GameObject> action, bool activeOnly) { for (int i=0; i<all.Count; i++){ GameObject target = all[i] as GameObject;
if (!activeOnly || target.active) action(target); } }
public void prePopulate (int num) { GameObject[] array = new GameObject[num]; for (int i = 0; i < num; i++) { array[i] = Spawn (Vector3.zero, Quaternion.identity); SetActive (array[i], true); } for (int j = 0; j < num; j++) { Unspawn (array[j]); } }
// Activates or deactivates the provided game object using the method // specified by the setActiveRecursively flag. protected void SetActive(GameObject target, bool value) { if (setActiveRecursively) target.SetActiveRecursively(value); else target.active = value; }
#endregion } }
Как пользоваться. В скрипте где создаем пул объектов прописываем в начале
using pools;
Code
GameObjectPool bulletPull; public GameObject bulletPrefab;
наши переменные, bulletPrefab хранит объект пули который будет загружен в сцену.
Code
void Start(){ bulletPull = new GameObjectPool(bulletPrefab,99,bulletHandler,true); bulletPull.prePopulate(99); }
bulletPull = new GameObjectPool(bulletPrefab,99,bulletHandler,true);
= создаем новый пул первый аргумент это игровой объект который надо создать, второй это начальное кол-во, третий аргумент запускает функцию для установки первоначальных данных для объектов если они есть, последний аргумент либо деактивирует только объект, либо объект и его дочерние объекты если таковы имеются.
Стартовая функция для созданных объектов пула - обязательно должна иметь аргумент игрового объекта ( это только что созданная пуля в нашем примере), собственно тут можно прописать все начальные параметры для объекта.
Все - теперь нам нужно правильно активировать объект и при необходимости возвращать его обратно в пул.
Code
bulletPull.Spawn (new Vector3 (0, 0, 0), Quaternion.identity);
- Spawn отвечает за активацию объекта из пула по позиции и вращению. Возврат в пул выглядит так:
Code
bulletPull.Unspawn(myGameObject);
- где myGameObject - игровой объект который нужно вернуть обратно в конкретный (bulletPull) пул.
Создаем список с элементами под тегом уровень. Это нужно для того чтобы при необходимости загружать все уровни разом. В нашем примере правда значение позиции игрока будет переписано много раз если уровней будет несколько. Это просто пример чтобы показать как все работает.
Загружаем значения с атрибутов и сразу добавляем их в наши временные переменные. Convert.ToSingle перегоняет значения во float. Это нужно так как изначально данные идут как текст.
Code
playerPosition = new Vector3(x_coord,y_coord,z_coord);
- назначаем позиции игрока новые значения из временных переменных. ACTORS - мой фреймворк на Unity Until We Die - игра над которой работаю
Сообщение отредактировал pixeye - Четверг, 19 Апреля 2012, 19:45
Мне это тоже приносит удовольствие, но вот сколько проектов дошли только до рисования спрайта ГГ - не счесть. Думаю: а нафига я всё это делаю? И сажусь играть на 2 часа. Потом опять...
)) А зафига ты играешь 2 часа?) Пойми - ты не обременен никакими заботами и делать игры для тебя такая же игра, в том плане что тебя это ни чем и ни к чему не обязывает. Хочешь делаешь, не хочешь - не делаешь. Это нормально и уж в 12 лет точно) ACTORS - мой фреймворк на Unity Until We Die - игра над которой работаю
Всякий раз как объявляется новый проект в голове, я начинаю его делать, позже проект становится не интересным, и хочется что то другое Как с этим бороться?
Никак, мне тоже к концу не интересно то что я делаю ( хотя мне и нравится сам процесс ). Вопрос в том заканчивать свою игру или бросать лежит исключительно в вопросе мотивации и целеустремленности. В 16 лет для меня это было хобби, потом работа мечты, потом разачарование, теперь попытки осмысленные найти свое место и делать то что нравится. У тебя еще есть выбор чем заниматься в жизни и что делать. У меня на самом деле тоже, но я люблю свое дело, и ничего другого не умею. Если я перестану доделывать свои игрушки у меня не будет портфолио, у меня не будет расти опыт, как следствие маловероятно что я подниму свою компанию или найду работу в той компании в которую тыкну пальцем. Если всего этого не будет мне неначто будет жить, начну худеть и в конце концов сдохну с голода;-))
Соответственно тебе сейчас надо делать то, что приносит удовольствие. Доделывать работу до конца это дисциплина,опыт,обязанность. Так что получай опыт и пусть это будет тебе фор фан. ACTORS - мой фреймворк на Unity Until We Die - игра над которой работаю
Кстати, подозреваю, что и в команде девелоперов самостоятельной игры дизайнера уровней посадят опять за редактор карт, с той лишь разницей, что будет обратная связь и с автором того редактора, и с художником, и с 3D моделером.
Левел-дизайнер это узкоспециализированный гейм дизайнер. Работает он с художниками и программистами. Навыки программирования при левел дизайне строго индивидуальны, однако как правило за скриптинг в некоторых компаниях отвечают именно левел дизайнеры. Так что навыки программирования это очень жирный плюс. ACTORS - мой фреймворк на Unity Until We Die - игра над которой работаю
Мы будем набирать группой, то есть 2-4 человека, каждый желающий будет протестирован. По окончанию работы группа получит 1000 евро (любые средства переводов).
Если работа будет сделана быстрее , то каждому будет начислен бонус, если нет, но в минус.
Звучит как пирамида. В минус это бедный человек должен будет платить за то что работал? '-) Может все станет проще если ты назовешь компанию-работодателя и название проекта мм? Хорошо если "СЕКРЕТ". То уж компания точно не является секретом.
Quote (Aspirine)
Вы ошиблись - в Японии.
Что в японии? Ищите программистов? Гцуп в россии и его посещают в среднем 90 % школьников и для тех кого разработка хобби. Не ошибся?) На дтф такую вакансию размести;-)
Смею предположить что работа вдобавок без договора, так как с этого надо было начинать? ACTORS - мой фреймворк на Unity Until We Die - игра над которой работаю
Все - теперь циклом для каждого игрового объекта objs создастся в xml строчка c атрибутами. Название элемента будет objs[i].typeOf.ToString(); Это наш enum в objs (player,monster,npc)
Если допустим для monster - нужны отличные от всех остальных атрибуты, то просто в цикле пишем
if (objs[i].typeOf == myObjects.TYPEOF.monster){ Ваш код } ACTORS - мой фреймворк на Unity Until We Die - игра над которой работаю
Сообщение отредактировал pixeye - Понедельник, 16 Апреля 2012, 18:51
Unity 3d огромный раздел на нашем с вами форуме. Много новичков каждый день задают свои вопросы и увы реже чем хотелось бы получают ответы. Многие из их вопросов однотипные, а хорошие ответы и решения затираются в потоках бесполезных тем и оффтопа. Эта тема создана для того, чтобы люди максимально быстро и эффективно находили ответы на свои типовые вопросы, прежде чем озвучивать их в разделах помощи.
Структура
Все скрипты поделены по вкладкам разделов. Разделы состоят из подразделов. Подразделы представляют из себя список линков на темы форума или ссылки в интернете. Так как половина людей на этом сайте не изъясняется на английском, то приниматься будут ссылки/темы русскоязычные в первую очередь. Разумеется 90% информации хранится зарубежом, что ж - потрудитесь сделать качественный перевод.
У меня есть отличный скрипт/урок. Как его разместить?
Отправить мне в лс ссылкой с указанием имени автора , пометкой о языке,( дабы люди знали заранее ), раздел, подраздел, название. Напоминаю, если источник информации не ваш, то и не надо подписываться своим именем, напишите автора. Если у источника есть общедоступная почта, или блог или сайт, то можете указать и это, в таком случае к имени будет прикреплен линк, дабы люди знали к кому обратиться с вопросами. Как это будет выглядеть линк [ Имя_автора ] [RUS]
pixeye, Хмм... Спасибо) Но вот есть один вопросик... А если объектов на карте очень много, то их всех и прописывать в xml вручную? А можно как-нибудь искать их по тегу или по чему ещё?..
Отвечу чуть позже;-) конечно можно ACTORS - мой фреймворк на Unity Until We Die - игра над которой работаю
Чуть ли не каждый день слышу "как сделать сохранение". Показываю простой пример в учебных целях. Для сохранения используем xml документ. Для начала очень краткий экскурс для тех кто видит xml в первый раз.
Где красным выделен корневой элемент, зеленым элементы, а синим атрибуты. Можно предположить что в этом документе прописаны координаты игрока и некоего монстра.
Все скрипты я буду писать на C#, перевод на US если и будет то не сейчас, однако ничего сложного нет, поэтому просто обязаны справиться;-) Итак создаем скрипт.
Назовем его SaveController.cs
Добавляем using System.Text; using System.Xml; using System.IO;
void Update(){ if (Input.GetKeyDown (KeyCode.S)) { SaveGame(); } } }
Теперь по порядку.
string filepath = "data.xml"; - путь к файлу, в данномслучае файл находится в папке с проектом. Не очень хорошо, однако ничего не мешает вампрописать другой путь.
XmlDocument xmlDoc = new XmlDocument (); - создаем новый xml документ.
XmlElement elmNew = xmlDoc.CreateElement ("player"); - создаем элемент игрока
XmlAttribute position_X = xmlDoc.CreateAttribute ("position_x"); - создаем атрибут позиции по X;
position_X.Value = playerTransform.position.x.ToString(); - присваиваеи атрибуту position_X значение позиции игрока по X - обязательно переведите значение в текст ( .ToString() )
elmNew.SetAttributeNode (position_X); - присваиваем атрибут position_X элементу игрока
rootNode.AppendChild (elmNew); - вкладывает элемент игрока в корневой элемент "level"
xmlDoc.Save (filepath); - сохраняем наш xml документ по нашему пути.
Вот впринципе и все, могут быть ошибки так как довольно трудно писать коды в сообщение без подсветки;-) Если что поправлю.
Если все сделано правильно то вы сможете 1) Создавать xml файл 2) Прописывать туда данные 3) Вписывать данные в уже созданный xml файл
Все значения будут каждый раз перезаписаны.
Если пригодилось/пригодится - добавлю еще пару уроков по сохранению.
Ответ на вопрос как сохранять за раз несколько объектов На самом деле все просто.
Для начала создадим некий абстрактный класс который будет хранить в себе переменные объекта.
Code
public class myObjects : MonoBehaviour {
public enum TYPEOF{ player,monster,npc } public TYPEOF typeOf; public Transform selfTransform;
void Awake(){ selfTransform = transform; } }
Это у нас рыба.
Вернемся к сейтКонтроллеру ( SaveController ) Добавляем using System.Collections.Generic;
Code
//К переменным List<myObjects> objs = new List<myObjects>();
Где непосредственно запись в документ переписываем
Code
for (int i=0;i<objs.Count;i++){ XmlElement elmNew = xmlDoc.CreateElement (objs[i].typeOf.ToString());
Все - теперь циклом для каждого игрового объекта objs создастся в xml строчка c атрибутами. Название элемента будет objs[i].typeOf.ToString(); Это наш enum в objs (player,monster,npc)
Если допустим для monster - нужны отличные от всех остальных атрибуты, то просто в цикле пишем
if (objs[i].typeOf == myObjects.TYPEOF.monster){ Ваш код } ACTORS - мой фреймворк на Unity Until We Die - игра над которой работаю
Сообщение отредактировал pixeye - Понедельник, 16 Апреля 2012, 18:49
почему в Unity 3.5.1 не работает то что работало в версии 3.4 ?
Потому что читать надо ченджлоги. Давно уже было сказано, что теперь US в юнити по умолчанию работает с строгой типизацией данных - так как это единственный способ на US писать игры на айфоны и андроиды.
Так что да, такого безобразия как ты делал больше не будет. ACTORS - мой фреймворк на Unity Until We Die - игра над которой работаю
Максималистичное отрицание очевидного. Я во первых сомневаюсь, что ты будешь играть в зуму год подряд;-) Во вторых, зума рассчитана на широкий спектр игроков и управление там наипростейшие. Это из разряда easy to learn but hard to master ACTORS - мой фреймворк на Unity Until We Die - игра над которой работаю
Если знаешь английский http://unitynoobs.blogspot.com/2011/02/xml-loading-data-from-xml-file.html - читай здесь.
Если нет, то постараюсь в ближайшие дни составить тутор, это не на один короткий ответ вопрос увы(. ACTORS - мой фреймворк на Unity Until We Die - игра над которой работаю
Кто-нибудь знает, как сделать сохранение игры игроком. То есть в любой момент залез в меню и сохранил её. А потом можно было загрузить.
знает. Впринципе моего плохого настроения должно хватит чтобы сказать что я ответил на твой вопрос;-) Но мне кажется правильнее было бы спросить как сделать?')
Это самый простой метод, не очень эффективный и не позволяет сохранять многие значения такие как вектор или булево значение например. (Хотя есть скрипты которые позволяют это делать). Другой вариант это xml документы. ACTORS - мой фреймворк на Unity Until We Die - игра над которой работаю
Но он не хочет так действовать,объясни что добавить
Это связано с тем, что нельзя в Update сувать yield. Тебе нужно это делать через сопрограммы. Вообще по хорошему надо отучаться писать в Update - а делать все через сопрограммы.
Как эт овыглядит.
Code
IEnumerator CountAmmo(){
while(true){
if(Input.GetMouseButton(0)) { yield return new WaitForSeconds(1.0); Ammo-=1; }
1) Назначение параметра distance в GetLinePoint. Не могу понять как и где можно использовать GetLinePoint.
Поиск точки по длине отрезка, насколько мне известно. Я этим непользовался. В любом случае это позволяет выявлять отдельно взятые точки отрезков, а GetLineLength - величину длины.
Quote (mrResident)
2) Хочу сделать такую вещь, при наведении курсора на один из сегментов линии (например 3 точки, 2 линии) подкрасить линию на котором находиться курсор другим цветом. Как это можно сделать?
Первое что нужно сделать, это добавить коллайдеры к твоим отрезкам.
Что у нас тут - line, это уже созданная линия - .vectorObject - это игровой объект линии. Тут следует понимать что надо чертить "3d линии" - они являются игровыми объектами и с ними можно взаимодействоваться. .AddComponent<MeshCollider>(); - добавляем мешколайдер line.vectorObject.GetComponent<MeshCollider> ().isTrigger = true; - делаем его тригером, чтобы взаимодействовать только с мышкой.
Дальше дело техники;-) можно хоть как кнопку использовать. Однако у нас задача по сложнее. Я ее не решал, однако пару мыслей есть.
Первое, VectorLine line = new VectorLine ("Line", linePoints, cols[globalScript.use.levelMode], lineMaterial, 10f, LineType.Continuous, Joins.Weld); когда ты объявляешь линию выставляй на LineType.Discrete - это будут тогда рванные не соединенные отрезки.
Сохраняй свои отрезки в массив. Каждому новому созданному отрезку приписывай id, (это нужно для индекса в массиве линий ) , каждый раз когда жмешь линию, вытаскивай айдишник линии и по нему линию из массива и меняй ей цвет.
Как линии присвоить айдишник или вообще код.
Создаешь скрипт.
Code
public class lineHandler : MonoBehaviour { public int selfID; }
Теперь добавляешь его как и коллайдер line.vectorObject.AddComponent<lineHandler>();
Все это пособие к действию и общий ход работ. Я бы начал с такого варианта. Если возникнут более конкретные вопросы по ходу этого сценария попробую ответить.
1. Создавать массивы линий присваивая им коллайдер и скрипт, прописывая индекс 2. Обработка нажатия мыши по линии и вытаскивания индекса 3. Обращение в массиве по индексу и смене цвета.
Сразу предостерегаю вопрос о том, а что будет если линию удалить. Чтож в таком случае тебе нужен List линий а не просто массив, и нужно позаботится о том, чтобы линии своевременно меняли свой индекс в случае изменений, либо по новой им все прописывать. ACTORS - мой фреймворк на Unity Until We Die - игра над которой работаю
Сообщение отредактировал pixeye - Воскресенье, 15 Апреля 2012, 11:31
но вот скрин увидел тут, так что продолжу, чтобы до других уровней дойти. Но начальное однообразие, как по мне, сильно уж затянуто.
Эх...долго же тебе идти) То были последние уровни. Я понял о чем ты, это то как раз будет исправить относительно не сложно, поработаю на свежую голову над дизайном уровней. ACTORS - мой фреймворк на Unity Until We Die - игра над которой работаю
pixeye, А почему именно Thrower 2.0?Как по мне,так с первой версией общее только то,что надо что-то запускать.
Я не придумал названия лучше. Thrower - лаконично и понятно, это одно из простых слов которое даже не было забито на программы/приложения у аппл. Я был очень удивлен когда смог зарегить игру как Thrower. Многие буржуи что играли часто оставляли в коментах, что запустили только из за названия. Некоторые даже шутили что название лучше игры;-) Так это или нет дело десятое, но найти замену лучше не смог.
Разумеется) если у кого то будут лаконичные и простые слова для названия - это еще можно исправить, до того момента когда игра отправится на апрувы. ACTORS - мой фреймворк на Unity Until We Die - игра над которой работаю