danilaxxl danilaxxl

CollectableItemData.cs

[CreateMenuItem(fileName = "newItem", menuName = "Data/Items/Collectable", order = 51]

GoloGames GoloGames

vadya_ivan, рад, что вам игра показалась интересной : )

P.S. Кстати уже доступна бесплатная демо-версия в Steam

vadya_ivan vadya_ivan

Визуал, задумка, музыка , механики, все в цель

GoloGames GoloGames

Ato_Ome, спасибо за позитивные эмоции, будем стараться : )

Ato_Ome Ato_Ome

Потрясающий результат, все так четенько, плавненько)
То ли саунд, то ли плавность напомнили мне игрушку World of Goo, удачи вам в разработке и сил побольше дойти до релиза!)

Cute Fox Cute Fox

Graphics are a little cool, good HD content. But this game doesn't cause nary interest me.
However the game is well done.

GMSD3D GMSD3D

Почему действие после всех условий выполняется?
[step another object]

Zemlaynin Zemlaynin

Jusper, Везде, но наугад строить смысла нет. Нужно разведать сперва территорию на наличие ресурсов.

Jusper Jusper

Zemlaynin, а карьеры можно будет везде запихать?
Или под них "особые" зоны будут?

Zemlaynin Zemlaynin

Это так скажем тестовое строительство, а так да у города будет зона влияния которую нужно будет расширять.

Jusper Jusper

А ссылка есть?

Jusper Jusper

Я не оч понял из скриншота, как вообще работает стройка. У игрока будет как бы поле строительства?

split97 split97

в игру нужно добавить время песочные часы в инвентаре, пока бегаешь наберается усталость и ты очень тормозной мобильный враг просто убевает

split97 split97

в игру нужно добавить время песочные часы в инвентаре, пока бегаешь наберается усталость и ты очень тормозной мобильный враг просто убевает

ViktorJaguar ViktorJaguar

Почему я нигде не могу найти нормальный туториал, где покажут как экипировать предмет (например, меч) в определенную (выделенную под оружие) ячейку???

Логотип проекта Unity

Сшиватель мешей для Unity

Сшиватель мешей для Unity

Предисловие

В недавнем скриншотнике мы говорили, что работали над оптимизацией. Slash Polygon: Tournament предназначен прежде всего для мобильных платформ, поэтому вопрос производительности для нас почти номер 1.

Mesh Composer

Мы сделали небольшой скрипт, который сшивает меши в один, экономя отрисовку на устройстве. Инструкция использования простая:

Пример структуры объектов — Сшиватель мешей для Unity — Unity — DevTribe: инди-игры, разработка, сообщество (mesh composer, tool, Скрипт, скрипт)
Пример структуры объектов
  • Создайте пустой Game Object
  • В качестве Child к созданному объекту добавьте те модели, которые хотите сшить (для них должен использоваться 1 материал, иначе от сшивание нет смысла)
  • Добавьте компонент на Game Object - Mesh Composer
  • (опционально) Для подчиненных объектов можно включить Mesh Collider
Можно было еще включить нашу отрисовку теней, но она кастомная и вам не понадобится.
Компонент на объекте — Сшиватель мешей для Unity — Unity — DevTribe: инди-игры, разработка, сообщество (mesh composer, tool, Скрипт, скрипт)
Компонент на объекте

Вcпомогательная информация:

  • Total Childs (сколько подчиненных объектов в группе)
  • Total Verts (сколько в итоге вертексов получается в сшитом объекте)
  • Ругань, если подчиненные сшитые объекты имеют разный материал
  • Ругань, если максимальное количество вершин в одном сшитом объекте > 65536

Код

using UnityEngine;

namespace Visual
{
    [RequireComponent(typeof(MeshFilter))]
    [RequireComponent(typeof(MeshRenderer))]
    public class MeshComposer : MonoBehaviour
    {
        public MeshFilter MyFilter;
        public MeshRenderer MyRenderer;
        public MeshFilter[] InternalFilters;
        public Material SharedMaterial;
        [SerializeField] private bool _useMeshCollider;

        private void Awake()
        {
            Compose();
        }

        private void Compose()
        {
            var combineMeshes = new CombineInstance[InternalFilters.Length];
            for (int i = 0; i < combineMeshes.Length; i++)
            {
                combineMeshes[i].mesh = InternalFilters[i].mesh;
                combineMeshes[i].transform = InternalFilters[i].transform.localToWorldMatrix;
                InternalFilters[i].gameObject.SetActive(false);
            }

            MyFilter.mesh = new Mesh();
            MyFilter.mesh.CombineMeshes(combineMeshes, true, true, false);
            MyRenderer.material = SharedMaterial;

            if (_useMeshCollider)
            {
                var collider = gameObject.AddComponent<MeshCollider>();
                collider.sharedMesh = MyFilter.mesh;
            }
        }
    }
}
using System.Linq;
using UnityEditor;
using UnityEngine;

namespace Visual.Editor
{
    [CustomEditor(typeof(MeshComposer))]
    public class MeshComposerInspector : UnityEditor.Editor
    {
        private MeshComposer _instance;

        private void OnEnable()
        {
            _instance = (MeshComposer) target;
        }

        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();

            _instance.MyFilter = _instance.GetComponent<MeshFilter>();
            _instance.MyRenderer = _instance.GetComponent<MeshRenderer>();

            // fetch childs
            _instance.InternalFilters = _instance.GetComponentsInChildren<MeshFilter>()
                .Where(filter => filter != _instance.MyFilter).ToArray();

            EditorUtility.SetDirty(_instance);

            EditorGUILayout.HelpBox($"total childs:{_instance.InternalFilters.Length}", MessageType.Info);

            if (_instance.InternalFilters == null || _instance.InternalFilters.Length == 0)
                return;

            var totalVerts = _instance.InternalFilters.Select(filter => filter.mesh.vertices.Length)
                .Aggregate((total, next) => total += next);

            var messageType = MessageType.Info;
            if (totalVerts > uint.MaxValue)
                messageType = MessageType.Error;

            EditorGUILayout.HelpBox($"total verts: {totalVerts}", messageType);

            var useSameMaterial = true;

            var material = _instance.InternalFilters[0].GetComponent<MeshRenderer>().sharedMaterial;
            foreach (var meshFilter in _instance.InternalFilters)
            {
                var rend = meshFilter.GetComponent<MeshRenderer>();
                if (rend.sharedMaterial != material)
                {
                    useSameMaterial = false;
                    break;
                }
            }

            if (!useSameMaterial)
            {
                EditorGUILayout.HelpBox($"Internal meshses uses different materials, must be the same!",
                    MessageType.Error);
            }
            else
            {
                _instance.SharedMaterial = material;
            }

            EditorUtility.SetDirty(_instance);
        }
    }
}

Скачать Mesh Composer

Два готовых скрипта для использования в Unity.

Результат

В видео показан игровой процесс с устройства. В видео стоит ограничитель на максимальный FPS - 30 кадров. Количество Batches и Tris уменшилось на порядок, игра из конкретно нестабильного куска гов билда превратилась в нормальный рабочий прототип.

Смотрите также:


Комментарии



Возможно глупый вопрос, но я пока только вникаю в юнити.

Лоды при этом методе у мешей сохраняются? Какие объекты выгоднее всего таким образом объединять?

Taske,

Возможно глупый вопрос, но я пока только вникаю в юнити.

Лоды при этом методе у мешей сохраняются? Какие объекты выгоднее всего таким образом объединять?

LOD-ы нет вроде, не делали.
Все существующие меши отключаются на старте, остается только инстансы внутри группировки.

Лучше всего объединять мелкие объекты (мы сшивали лесной участок).

Справка