KamiRonin, а будет легко использовать rigidbody fps walker c photon? Может быть этот вопрос очень тупой и к фотону можно прицепить что угодно... Я просто почти ничего не знаю как это всё делается и сервера всякие эти... Когда сделаю нормальную часть игры, основную механику тогда буду искать второго программиста который мне будет помогать с фотоном.. один я уже такое не потяну
Т.е. мне тогда лучше выбрать Character Controller ? Вот тут например кто то говорит что CC фигня For Unity Users...
Кстати я уже давно написал свою систему передвижения на rigidbody, только само перемещение писал не я , а написанный для всех очень хороший RigidbodyFPSWalker что скажите про него?
Добавлено (17.11.2013, 23:55) --------------------------------------------- Тогда вопрос что писал я ? Добавил перемещение в приседании , ползжение (?) (ползти чтоб можно было) . Сделал FPS Input Manager свой. С которого считываю что нажато, врубаю анимацию в меканиме и отправляю в RigidbodyFPSWalker что нужно сделать с персонажем и его скоростью.
Добавлено (17.11.2013, 23:56) --------------------------------------------- И всё работает довольно неплохо.
Добавлено (18.11.2013, 00:05) --------------------------------------------- Вот даже демка: W A S D ходить, если ещё нажать левый Shift можно будет бежать Left Ctrl - приседание X - лежать, можно ползти.
На анимацию внимание не обращайте, это как то работает на моём велосипеде и есть небольшие баги и недоработки, потому что я сделал это и потом начал оптимизировать (темы про кубы). Оптимизировал, теперь возвращаюсь к системе передвижения и создал тему (эту). Баги с анимациями легко исправить.
Также , помимо RigidbodyFPSWalker, моего FPS Input Manager ещё написаны мною такие вещи как Camera Controller, Capsule Collider Controller Camera Controller позволяет мне в два клика создать 2 точки для камеры, и легко добавить её плавное передвижение. Я это применил для плавного передвижения камеры когда садишься или ложишься. А Capsule Collider Controller мне позволяет легко менять размеры коллайдера персонажа. Это для того что бы когда лежишь можно было пролезть под 1 блоком высотой. К приседанию это пока не сделано. Всё это вы можете протестировать в демке.
KamiRonin, просто у CC уже огромный готовый код и мне кажется что будет трудно его переделывать. Просто мне нужно будет добавлять потом ещё другие позиции : сидеть, лежать. И что именно нужно делать в CC что бы этого достичь - я не знаю. Я всегда когда пишу скрипты я не беру ничей код, и делаю свой , может не правильный но работающий и мне понятный как работает.
Всем привет. У меня стоит выбор между двумя системами передвижения. Их существует два : физическая и математическая. Физическая - rigidbody, AddForct Математическая - всем известный CharacterController
Оба работают неплохо. Но у каждого есть свои плюсы и свои минусы. Я хочу что бы вы мне помогли найти ещё другие плюсы и минусы и помогли мне определится с выбором
Плюсы RigidbodyController: Взаимодействие с другими rigidbody Передвижение кажется более плавным
Плюсы CharacterController: Ничего городить не нужно, большинство кода уже готово Быстро работает (математика)
Минусы CharacterController: Нету взаимодействия с rigidbody Не очень плавное передвижение
Конечно выбор зависит ещё и от того для чего будет использоваться та или иная система передвижения. Что будет у меня в игре: Здания, которые можно будет разрушать, большие небоскребы будут падать посредством rigidbody (прошу не писать что rigidbody в юнити очень медленный, это мои проблемы и тем более я уже решил все проблемы с оптимизацией) . Нужно будет что бы падающие обломки могли убить персонажа. Нужно нормальная синхронизация позиции персонажа с сервером. В качестве серверной платформы будет использоваться Photon. В качестве персонажа - человек.
Как это сделано в других играх ? Как это сделано в Battlefield 3,4 ? Что используют чаще ? Почему и зачем? Мне хочется узнать побольше, т.к. выбор нужно сделать раз и навсегда..
Добавлено (16.11.2013, 23:00) --------------------------------------------- Заранее спасибо за подробные внятные и понятные ответы
Ranger, возможно не ищется потому что в референсе только UnityEngine. Ещё есть UnityEditor, где и есть этот UnityStats. UnityEditor.UnityStats.vboTotal Можно прописать в using.
Накидал код по быстрому взяв за основу пример. Сам меши не ковырял, но ,думаю, ты допилишь до рабочего.
Незнаю зачем Вы сделали для меня этот пример... Хотя я вроде не говорил что всё уже готово.. Мой код-велосипед из 318 строчек, выполняющий покадровое комбинирование. Я всё таки выложу это.
Код
using UnityEngine; using System; using System.Collections; using System.Collections.Generic;
public class CombineQueue : MonoBehaviour { public GameObject destroyObj; public int maxFrame = 100; //Указывает максимальное колличество комбинирования в 1 кадр int curFrame; //Указывает сколько будет обработано объектов в текущий кадр. Current Frame
List<BuildingClass> InstanceList = new List<BuildingClass> (); List<GameObject> Buildings = new List<GameObject> (); List<CombineInstance> Instance = new List<CombineInstance> (); List<Transform> Objects = new List<Transform> ();
public void AddToQueue (CombineInstance[] insList, Transform[] cube, GameObject caller) { //Debug.Log ("New instances! Count : " + insList.Length + " . Caller: " + caller.name); for (int i = 0; i < insList.Length - 1; i++) { //Внимание! Мы не проверяем последний item, так как он дубликат первого item!!! BuildingClass newInstance = new BuildingClass (); newInstance.instance = insList [i]; newInstance.cube = cube [i]; newInstance.gameobject = caller; InstanceList.Add (newInstance); } /* foreach (CombineInstance ins in insList) { BuildingClass newInstance = new BuildingClass (); newInstance.instance = ins; newInstance.gameobject = caller; InstanceList.Add (newInstance); } */ //Debug.Log ("Instances added! Length: " + InstanceList.Count); }
IEnumerator CoroutineCombine (GameObject go, CombineInstance[] instances, int verts) { BuildingMeshes bMeshes = go.GetComponent<BuildingMeshes> (); if (bMeshes.Meshes.Count == 0) { //Если у здания нету ещё не одной скомбинированной группы GameObject obj = new GameObject (); obj.AddComponent ("MeshFilter"); obj.AddComponent ("MeshRenderer"); obj.renderer.material = emptyMat; obj.transform.parent = go.gameObject.transform; obj.name = go.name + "_Combined_1"; obj.GetComponent<MeshFilter> ().mesh = new Mesh (); obj.GetComponent<MeshFilter> () .mesh.CombineMeshes (instances); obj.AddComponent ("MeshCollider"); obj.gameObject.active = true;
CombinedMeshes newInstance = new CombinedMeshes (); newInstance.mesh = obj; newInstance.vertices = obj.GetComponent<MeshFilter> ().mesh.vertexCount; bMeshes.Meshes.Add (newInstance); } else if (bMeshes.Meshes.Count > 0) { //Если у здания уже есть хотя бы одна скомбинированная группа int vCount = bMeshes.Meshes [bMeshes.Meshes.Count - 1].vertices; if (vCount < 60000) { if (60000 - vCount >= verts) { GameObject newOne = bMeshes.Meshes [bMeshes.Meshes.Count - 1].mesh; //bMeshes.Meshes[bMeshes.Meshes.Count -1].mesh.GetComponent<MeshFilter> () .mesh.CombineMeshes (AddOne(instances,newOne)); //bMeshes.Meshes[bMeshes.Meshes.Count -1]
void Update () { if (Input.GetKeyDown (KeyCode.H)) { Resources.UnloadUnusedAssets(); }
//Считаем сколько объектов будет обработано в следующий кадр if (InstanceList.Count - 1 >= maxFrame) { curFrame = maxFrame - 1; curStatus = "maxFrame "; } else if (InstanceList.Count - 1 < maxFrame) { curFrame = InstanceList.Count - 1; curStatus = "elseFrame "; //Debug.Log(InstanceList.Count + " " + curFrame); }
if (InstanceList.Count != 0) {
//Считаем сколько разных групп for (int i = 0; i <= curFrame; i++) { GameObject go = InstanceList [i].gameobject; if (!Exists (go)) Buildings.Add (go); } //Пробуем работать с каждой группой foreach (GameObject go in Buildings) { Instance.Clear (); //Очищаем список для создания нового списка комбинирования Objects.Clear (); //Очищаем список для создания нового списка объектов (это для распределения по мешам в 60к вершин) for (int i = 0; i <= curFrame; i++) { //Копаем 100 первых BuildingClass объектов GameObject instanceObj = null; if (i < InstanceList.Count) instanceObj = InstanceList [i].cube.gameObject; else if (i >= InstanceList.Count) instanceObj = InstanceList [InstanceList.Count - 1].cube.gameObject;
void Combine (GameObject go, CombineInstance[] instances, int verts) { BuildingMeshes bMeshes = go.GetComponent<BuildingMeshes> (); if (bMeshes.Meshes.Count == 0) { //Если у здания нету ещё не одной скомбинированной группы GameObject obj = new GameObject (); obj.AddComponent ("MeshFilter"); obj.AddComponent ("MeshRenderer"); obj.renderer.material = emptyMat; obj.transform.parent = go.gameObject.transform; obj.name = go.name + "_Combined_1"; obj.GetComponent<MeshFilter> ().mesh = new Mesh (); obj.GetComponent<MeshFilter> () .mesh.CombineMeshes (instances); obj.AddComponent ("MeshCollider"); obj.gameObject.active = true;
CombinedMeshes newInstance = new CombinedMeshes (); newInstance.mesh = obj; newInstance.vertices = obj.GetComponent<MeshFilter> ().mesh.vertexCount; bMeshes.Meshes.Add (newInstance); } else if (bMeshes.Meshes.Count > 0) { //Если у здания уже есть хотя бы одна скомбинированная группа int vCount = bMeshes.Meshes [bMeshes.Meshes.Count - 1].vertices; if (vCount < 60000) { if (60000 - vCount >= verts) { GameObject newOne = bMeshes.Meshes [bMeshes.Meshes.Count - 1].mesh; //bMeshes.Meshes[bMeshes.Meshes.Count -1].mesh.GetComponent<MeshFilter> () .mesh.CombineMeshes (AddOne(instances,newOne)); //bMeshes.Meshes[bMeshes.Meshes.Count -1]
public class BuildingClass { public CombineInstance instance; public Transform cube; public GameObject gameobject; }
Добавляются туда меши с помощью функции AddToQueue, до этого обрабатывается в моём MeshMerger:
Код
using UnityEngine; using System.Collections; using System.Threading;
public class MeshMerger : MonoBehaviour { //Этот скрипт получает объект который нужно скомбинировать //Сортирует, делит по массивам, отправляет на переработку в CombineQueue
//Функция Combine с массивом объектов пока отключена! public void Combine(GameObject[] GameObjects,GameObject father){ for(int i = 0;i < GameObjects.Length;i++){ meshFilters[i] = GameObjects[i].GetComponent<MeshFilter> (); }
combine = new CombineInstance[meshFilters.Length]; int a = 0; while (a < meshFilters.Length) { combine [a].mesh = meshFilters [a].mesh; combine [a].transform = meshFilters [a].transform.localToWorldMatrix; //meshFilters [i].gameObject.active = false; a++; } //GetComponent<CombineQueue>().AddToQueue(combine,GameObjects,father); //Debug.Log("Request from CombineMesh. Sent request to CombineQueue as multiple objects"); } public void Combine (GameObject GameObj) { meshFilters = GameObj.GetComponentsInChildren<MeshFilter> (); cubes = GameObj.GetComponentsInChildren<Transform> (); cubes[0] = cubes[cubes.Length - 1]; cubes[cubes.Length - 1] = null; combine = new CombineInstance[meshFilters.Length]; int i = 0;
while (i < meshFilters.Length) { combine [i].mesh = meshFilters [i].mesh; combine [i].transform = meshFilters [i].transform.localToWorldMatrix; //meshFilters [i].gameObject.active = false; i++; } GetComponent<CombineQueue>().AddToQueue(combine,cubes,GameObj); //Debug.Log("Request from CombineMesh. Sent request to CombineQueue as one object"); } }
Если нужно скомбинировать меш, то просто нужно вызвать что то типо такого: GameObject.Find("Another Scripts").GetComponent<MeshMerger> ().Combine(gameObject);
Добавлено (15.11.2013, 17:26) --------------------------------------------- В скрипте CombineQueue очень много закомментированных строчек если что)
1. Проверяешь нет ли на них ссылок. Если нашел - обнуляешь, или лучше перестраиваешь приложение так, чтобы этих ссылок просто не было.
Нету, всё было обнулено.
Не то это всё. Прочитал на ансверсах юнити3д.ком о таких вещах, как : не нужно делать new Mesh(); . на unity3d.ru прочитал что нужно делать resources.unloadunusedassets(); и что это связанно с VBO. Однако это не повлияло ни на что. Память всё равно заполняется. Сейчас повторю ещё тесты с Resources. Говорят это как раз то что очищает память после Destory и делать это нужно желательно
ЦитатаRanger ()
я не помню как это назвается отображение DC и вершин.UnityStats.drawCalls ,UnityStats.triangles ,UnityStats.vertices
что это ? В юнити такого нету. А кстати, можно ли как то в OnGUI вывести из статистики что то конкретное? Например сколько сейчас памяти видео заполнено.
Добавлено (14.11.2013, 23:31) --------------------------------------------- Повторил тесты с unloadunusedassets : потрясающая вещь, очищает кучу памяти, одно здание с примерно 2300 кубов комбинировалось по 100 кубов за 1 кадр а потом в один целый меш и без очистки набирается 42 МБ , а после очистки 8 МБ. Конечно прирост большой На одну проблему меньше, вопросы выше ещё в силе, тему пока не заканчиваю.
1. возможна ошибка в скрипте : в новый меш входит старый меш + все(!) меши объектов, а не только новорожденные
Комбинирую я меш так: сначала беру первые 100 кубов из массива, комбинирую, потом следующие 100 + тот который уже скомбинирован и так делается меш.
ЦитатаRanger ()
Возможно, что Destroy убивает объект, а не удаляет меш.
Destroy(GameObject) Удаляю тот объект, который в компонентах содержит Mesh Filter (здесь сам скомбинированный меш) и Mesh Renderer. Из памяти он не пропадает.
seaman, Ваши слова мне почти ничего не сказали понятного... Просто VBO этот , это как бы уникальный объект которого ещё небыло на сцене. После комбинирования он и создается. Даже если его удалить он ещё остается в памяти. Тут вот я и не знаю что делать. Как удалить объект отовсюду ? Со сцены, из памяти..
Ranger, удалять со сцены эти кубы нельзя. Это для того что бы я потом мог удалить скомбинированный меш изменить что то в этих кубах и опять скомбинировать. setenable отключает рендеринг ,все скрипты и компоненты которые у объекта.
Ranger, допустим здание состоит из кубов, в сумме получается 2000 вершин, при комбинировании создается один меш, тоже 2000к вершин, а те кубы отключаются (setEnable)