Ошибка при сборке игры юнити

Ошибки в консоли:

UnityEditor.BuildPlayerWindow+BuildMethodException: Error building Player because scripts have compile errors in the editor
  at UnityEditor.BuildPlayerWindow+DefaultBuildMethods.BuildPlayer (UnityEditor.BuildPlayerOptions options) [0x002da] in <99feab6f3db6407493924fe4a179a95b>:0 
  at UnityEditor.BuildPlayerWindow.CallBuildMethods (System.Boolean askForBuildLocation, UnityEditor.BuildOptions defaultBuildOptions) [0x00080] in <99feab6f3db6407493924fe4a179a95b>:0 
UnityEditor.EditorApplication:Internal_CallGlobalEventHandler ()
Exception occurred inside BeeDriver: System.IO.FileNotFoundException: Could not find file "D:unityGameLibraryBeeartifacts1900b0aPDevDbg.dagUnityEngine.UI.dll.mvfrm"
File name: 'D:unityGameLibraryBeeartifacts1900b0aPDevDbg.dagUnityEngine.UI.dll.mvfrm'
  at System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.Boolean anonymous, System.IO.FileOptions options) [0x0019e] in <9aad1b3a47484d63ba2b3985692d80e9>:0 
  at System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.IO.FileOptions options) [0x00000] in <9aad1b3a47484d63ba2b3985692d80e9>:0 
  at (wrapper remoting-invoke-with-check) System.IO.FileStream..ctor(string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,int,System.IO.FileOptions)
  at System.IO.StreamReader..ctor (System.String path, System.Text.Encoding encoding, System.Boolean detectEncodingFromByteOrderMarks, System.Int32 bufferSize) [0x00055] in <9aad1b3a47484d63ba2b3985692d80e9>:0 
  at System.IO.StreamReader..ctor (System.String path, System.Text.Encoding encoding) [0x00000] in <9aad1b3a47484d63ba2b3985692d80e9>:0 
  at (wrapper remoting-invoke-with-check) System.IO.StreamReader..ctor(string,System.Text.Encoding)
  at System.IO.File.InternalReadAllLines (System.String path, System.Text.Encoding encoding) [0x00006] in <9aad1b3a47484d63ba2b3985692d80e9>:0 
  at System.IO.File.ReadAllLines (System.String path) [0x0002c] in <9aad1b3a47484d63ba2b3985692d80e9>:0 
  at NiceIO.NPath+SystemIOFileSystem.File_ReadAllLines (NiceIO.NPath path) [0x00007] in <99feab6f3db6407493924fe4a179a95b>:0 
  at NiceIO.NPath+WindowsFileSystem.File_ReadAllLines (NiceIO.NPath path) [0x00017] in <99feab6f3db6407493924fe4a179a95b>:0 
  at NiceIO.NPath.ReadAllLines () [0x00005] in <99feab6f3db6407493924fe4a179a95b>:0 
  at UnityEditor.Scripting.ScriptCompilation.PotentiallyUpdatableErrorMessages.IsAnyPotentiallyUpdatable (UnityEditor.Scripting.Compilers.CompilerMessage[] messages, Bee.BeeDriver.NodeResult nodeResult, Bee.BeeDriver.BeeDriver beeDriver) [0x000ba] in <99feab6f3db6407493924fe4a179a95b>:0 
  at UnityEditor.Scripting.ScriptCompilation.UnityScriptUpdater.ContainsUpdatableCompilerMessage (Bee.BeeDriver.NodeResult nodeResult, Bee.BeeDriver.BeeDriver beeDriver) [0x0008e] in <99feab6f3db6407493924fe4a179a95b>:0 
  at UnityEditor.Scripting.ScriptCompilation.UnityScriptUpdater.StartIfYouCanFixProblemsInTheseMessages (Bee.BeeDriver.NodeResult nodeResult, Bee.BeeDriver.BeeDriver beeDriver) [0x00001] in <99feab6f3db6407493924fe4a179a95b>:0 
  at Bee.BeeDriver.RunSourceFileUpdatingPhase.StartIfNeedToRunFor (System.Collections.Generic.IEnumerable`1[T] nodeResults) [0x00047] in <8090e176693344d890ff5ce732f8fade>:0 
  at Bee.BeeDriver.RunBackendPhase.Tick () [0x001f2] in <8090e176693344d890ff5ce732f8fade>:0 
  at Bee.BeeDriver.PhaseBase.Tick (System.Boolean blocked) [0x00009] in <8090e176693344d890ff5ce732f8fade>:0 
  at Bee.BeeDriver.BeeDriver.Tick (System.Boolean block) [0x00000] in <8090e176693344d890ff5ce732f8fade>:0 

Время на прочтение
6 мин

Количество просмотров 41K

Не так давно в Unity вышла из беты возможность создания проектов для WebGL. Делюсь своим опытом сборки под эту платформу большого игрового проекта.

Disclaimer: Статья только для тех, кто сам собирается сделать что-то подобное — она очень техническая и использует специфическую для Unity терминологию.

1. Загрузка типа через reflection

Первая проблема: вот такой простой код будет работать неправильно:

    var type = Type.GetType("TypeName");

Он работает, но тип возвращается неправильный и «пустой». Проблемы начинаются при работе с этим типом — почти все его методы возвращают пустые значения. Чтобы всё стало правильно, надо писать так:

    var assembly = Assembly.Load("Assembly-CSharp"); //или другое имя assembly

    var type = assembly.GetType("TypeName");

Вот тут заявлено, что это — ожидаемое поведение.

2. Динамическая загрузка ресурсов

Следующая проблема возникает при использовании методов Resources.Load или Resources.LoadAll. Эти методы сказочно долго работают. Для однопоточного браузера это легко становится критичным. Динамическую загрузку ресурсов этими и схожими методами лучше не использовать вовсе. Где возможно, надо менять её на статическую (заранее проставлять ссылки на нужные префабы). Разница во времени загрузки на моем проекте доходила до десяти секунд.

3. Синхронизация файловой системы

Если вы пользуетесь файловой системой, то нужно знать, что она реализована как wrapper над базой данной, встроенной в браузер. Но самое главное — синхронизация браузера с этой базой происходит только по прямой яваскриптовой команде:

FS.syncfs(false,function (err) {
     //alert('syncing fs');
});
}

Если её не вызывать, то после выключения браузера данные могут и не сохраниться. Вызывать её можно так:

1) Добавляем это в WebGL template:

<script type = "text/javascript" language = "javascript" >
 function SyncFiles()
 {
 FS.syncfs(false,function (err) {
     //alert('syncing fs');
 });
 }
 </script>

2) Вызываем это из c#:

private void Sync()
    {
#if UNITY_WEBGL
            Application.ExternalCall("SyncFiles");
#endif
     }

4. Инициализация WebGL и компиляция шейдеров

При старте приложения существенное время может занимать инициализация WebGL. Это очень важно, потому что данное время учитывается браузером в общее время непрерывной работы скрипта, которое ограничено (в Firefox, например, оно 10 секунд по умолчанию).

Основное время при инициализации WebGL занимает компиляция шейдеров. Причем компилируются только те шейдеры, которые есть на сцене или в префабах, на которые есть со сцены ссылки. Если вы (как я) просто брали в свою игру много разных ассетов из разных источников, то шейдеров у вас будет неприлично много и их компиляция может занять более 10 секунд.

Что нужно делать?

1) Минимизировать число различных шейдеров, используемых в проекте. Часто проект использует почти одинаковые шейдеры, которые приехали в него из разных покупных ассетов.

2) Если этого недостаточно, придется переносить часть ассетов в динамически загружаемые ресурсы или бандлы . Да, это дольше, чем статическая загрузка. Но динамическую загрузку можно сдедать отложенной и загружать свои ассеты частями так, чтобы загрузка каждой из частей точно занимала не более 10с. В итоге суммарное время загрузки вырастет. Но, по крайней мере, браузер перестанет назойливо предлагать игроку остановить зависший скрипт.

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

5. Кэш Firefox

Если вы собираетесь отлаживать ваш проект, используя локальный сервер и Firefox, то столкнётесь с тем, что браузер неверно кэширует часть WebGL проекта.

Сценарий такой:

Я делаю и запускаю версию 1. Она работает. Затем делаю версию 2. Запускаю — падает с непонятной ошибкой.

Лечится это ручной чисткой кэшей FF по адресу:

1) C:Users{ИМЯЮЗЕРА}Application DataMozillaFirefoxProfiles{ИМЯПРОФИЛЯ}storagetemporary

Тут можно удалять вообще всё.

2) C:Users{ИМЯЮЗЕРА}Application DataMozillaFirefoxProfiles{ИМЯПРОФИЛЯ}storagedefault

Тут надо удалить только ваш сайт. Например

«http+++127.0.0.1+7888»

Замечание: Это происходит только при работе с HTTP сервером. Если запускать проект из файлов ошибки не происходит, поскольку кэши для каждого пути к файлам — разные. А вот для сервера один кэш, независимо от пути.

6. Script does not respond for a long time. Stop it?

Firefox спросит у вас об этом почти наверняка. Если проект большой, то может спросить и несколько раз.

Частично об этой проблеме говорилось выше — в пункте, посвященном инициализации WebGL. Но важно понимать как происходит загрузка WebGL проекта и какое время учитывает браузер, когда предлагает отстрелить зависший скрипт.

Этапы запуска:

1) Идет загрузка данных браузером с сервера. Тут мы ничего ускорить не можем, но это время браузер и не ограничивает.

2) Идет декомпрессия данных.

Например:

Decompressed Release/w69.memgz in 100ms. You can remove this delay if you configure your web server to host files using gzip compression. UnityLoader.js:1:775
Decompressed Release/w69.jsgz in 391ms. You can remove this delay if you configure your web server to host files using gzip compression. UnityLoader.js:1:775
Decompressed Release/w69.datagz in 2764ms. You can remove this delay if you configure your web server to host files using gzip compression.

Как следует из пояснения, при правильной настройке сервера декомпрессия будет происходить налету и это время станет равным нулю. В любом случае, оно тоже не ограничивается.

3) Идет компиляция asm.js.

Successfully compiled asm.js code (total compilation time 9088ms; stored in cache)1 56937f89-a8fd-4b65-94aa-453e33be78d8

Может занимать 5-10 сек, но тоже не ограничивается браузером, так как код игры еще не стартовал.

4) А вот дальше стартует код игры

И, с точки зрения браузера, код Unity (такой, как инициализация WebGL) не отличается от кода самой игры. Причем выполняются они одним куском, подряд. Поэтому тут за 10 секунд должна пройти и инициализация WebGL и пользовательский код. Учитывая, что время инициализации WebGL обычно не может быть сокращено сильнее, чем до 4-5 секунд на хорошем компьютере, тут лучше не рисковать и снизить время инициализации пользовательского кода до минимума. В идеале, он вообще ничего не должен делать. А как же тогда инициализировать игру? Её можно отложить. Например, так:

        void Awake()
        {
            DontDestroyOnLoad(gameObject);

            StartCoroutine(Init());
        }

        IEnumerator  Init()
        {
           yield return new WaitForSeconds(0.1f);

           //Инициализация тут
        }

Смысл — сразу вернуть управление браузеру и через 0.1 секунду запускать свой код. После такого трюка браузер начнёт отсчёт 10 секунд заново. Соответсвенно, если инициализация у вас длинная, то можно и далее разбивать её на части таким же образом (хотя лучше постараться сократить — пользователь не любит ждать).

И последнее: ограничение на 10секунд непрерывного исполнения скрипта применяется не только во время инициализации.

7. Использование бандлов

При использовании asset bundles важно помнить, что они должны быть загружены с того же сервера, что и сама игра. Иначе работать не будет из-за нарушения single origin policy.

Второй момент — чтобы избежать задержки на декомпрессию бандла после загрузки лучше при создании бандла использовать не gz (по умолчанию), а lz4:

//Используйте ChunkBasedCompression (это и есть lz4)
  BuildPipeline.BuildAssetBundles (outputPath, BuildAssetBundleOptions.ChunkBasedCompression, EditorUserBuildSettings.activeBuildTarget);

8. Ограничение на 512 mb

На моей машине ни один браузер не был в состоянии выделить игре более 512mb. Хотя памяти на машине много. Полагаю, что не нужно выделять играм, собираемым под WebGL, больше памяти, чем 512mb. И саму игру нужно делать так, чтобы ей этого хватало. В идеале вообще оставить 256mb которые стоят по умолчанию.

9. Strip engine code

Strip engine code — это галочка в настройках сборки, которая заставляет Unity выбрасывать из сборки неиспользуемые системные скрипты.
Это позволяет значительно сокращать итоговый объем сборки. Проблема здесь в том, что если какой-то код используется только ассетами, попавшими в бандл, он тоже будет выброшен. А итоговая сборка работать не будет. Причем exception будет абсолютно непонятный.

Выводы:

1) Если получили непонятный exception, попробуйте собрать убрав эту галочку;
2) Можно прямо использовать скрипты, нужные ассетам из бандлов в коде или использовать специальую возможность Unity — файл link.xml.

10. Developer builds — no fast builds!

Когда собираешь developer build есть возможность выбора между быстрой сборкой и быстрым исполнением. На самом деле быстрая сборка занимает почти такое же (громадное) количество времени и при этом, на большом проекте часто совсем не работает из-за нехватки памяти. Лучше её не использовать.

11. Crunched textures

Для проектов под WebGL всегда используйте crunched texture. Иначе объем игры будет неприлично большим для web приложения.
Чтобы не выставлять тип каждой текстуре вручную, можно использовать вот такую технику (нужно перегрузить метод OnPostprocessTexture).

А двенадцатой пробемы нет, просто «двенадцать проблем» звучит лучше, чем одиннадцать.

UPDATE от 1го июня 2017г:

Двенадцатая проблема все-таки есть. Связана она с передачей строковых параметров между Unity и WebGL плагинами. Передача строки из Unity в webgl работает нормально. А вот наоборот — не всегда.
Unity предлагает использовать такой вот snippet:

var buffer = _malloc(val.length + 1);
writeStringToMemory(val, buffer);

Здесь — val — строка в javascript.
Это работает до тех пор, пока длина строки совпадает с количеством байтов в ней. Как только в строке встречаются неоднобайтовые (например, русские) символы, этот код приводит к записи за пределы выделенной памяти, что выражается в случайных крэшах вашего приложения в произвольных местах.

Так что либо используйте encode, чтобы ваши строки использовали лишь символы из latin1, либо перепишите этот snippet так, чтобы он использовал количество байт, а не символов в строке.

#unity3d

#unity3d

Вопрос:

Когда я пытаюсь собрать игру, появляется ошибка 22, когда я пытаюсь играть в редакторе, все в порядке.

Я новичок в Unity, поэтому извините, если я допустил какую-то глупую ошибку.

Ошибки:

(Местоположение) (): ошибка CS0234: имя типа или пространства имен «XXXX» не существует в пространстве имен » (вам не хватает ссылки на сборку?)

где XXXX: GraphView (библиотека UnityEditor.Экспериментальный), UIElements (библиотека UnityEditor)

(Местоположение)): ошибка CS0246: не удалось найти тип или имя пространства имен ‘ГГГГ’ (вам не хватает директивы using или ссылки на сборку?)

ГГГГ = Edge, Node, Port, Direction, EditorWindow, MenuItemAttribute, MenuItem

и еще одна ошибка

UnityEditor.BuildPlayerWindow BuildMethodException: 20 ошибок в UnityEditor.BuildPlayerWindow defaultbuildметоды.BuildPlayer (UnityEditor.Параметры BuildPlayerOptions)[0x002bb] в :0

Вот код:

DialogueGraphView

 using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.UIElements;
using Button = UnityEngine.UIElements.Button;

public class DialogueGraphView : GraphView
{
        public readonly Vector2 DefaultNodeSize = new Vector2(200, 150);
        public readonly Vector2 DefaultCommentBlockSize = new Vector2(300, 200);
        public DialogueNode EntryPointNode;

        public DialogueGraphView(DialogueGraph editorWindow)
        {
            styleSheets.Add(Resources.Load<StyleSheet>("NarrativeGraph"));
            SetupZoom(ContentZoomer.DefaultMinScale, ContentZoomer.DefaultMaxScale);

            this.AddManipulator(new ContentDragger());
            this.AddManipulator(new SelectionDragger());
            this.AddManipulator(new RectangleSelector());
            this.AddManipulator(new FreehandSelector());

            var grid = new GridBackground();
            Insert(0, grid);
            grid.StretchToParentSize();

            AddElement(GetEntryPointNodeInstance());
        }

        public void CreateNewDialogueNode(string nodeName, Vector2 position)
        {
            AddElement(CreateNode(nodeName, position));
        }

        public DialogueNode CreateNode(string nodeName, Vector2 position)
        {
            var tempDialogueNode = new DialogueNode()
            {
                title = nodeName,
                DialogueText = nodeName,
                GUID = Guid.NewGuid().ToString()
            };
            tempDialogueNode.styleSheets.Add(Resources.Load<StyleSheet>("Node"));
            var inputPort = GetPortInstance(tempDialogueNode, Direction.Input, Port.Capacity.Multi);
            inputPort.portName = "Input";
            tempDialogueNode.inputContainer.Add(inputPort);
            tempDialogueNode.RefreshExpandedState();
            tempDialogueNode.RefreshPorts();
            tempDialogueNode.SetPosition(new Rect(position,
                DefaultNodeSize)); //To-Do: implement screen center instantiation positioning

            var textField = new TextField("");
            textField.RegisterValueChangedCallback(evt =>
            {
                tempDialogueNode.DialogueText = evt.newValue;
                tempDialogueNode.title = evt.newValue;
            });
            textField.SetValueWithoutNotify(tempDialogueNode.title);
            tempDialogueNode.mainContainer.Add(textField);

            var button = new Button(() => { AddChoicePort(tempDialogueNode); })
            {
                text = "Add Choice"
            };
            tempDialogueNode.titleButtonContainer.Add(button);
            return tempDialogueNode;
        }

        public void AddChoicePort(DialogueNode nodeCache, string overriddenPortName = "")
        {
            var generatedPort = GetPortInstance(nodeCache, Direction.Output);
            var portLabel = generatedPort.contentContainer.Q<Label>("type");
            generatedPort.contentContainer.Remove(portLabel);

            var outputPortCount = nodeCache.outputContainer.Query("connector").ToList().Count();
            var outputPortName = string.IsNullOrEmpty(overriddenPortName)
                ? $"Option {outputPortCount   1}"
                : overriddenPortName;


            var textField = new TextField()
            {
                name = string.Empty,
                value = outputPortName
            };
            textField.RegisterValueChangedCallback(evt => generatedPort.portName = evt.newValue);
            generatedPort.contentContainer.Add(new Label("  "));
            generatedPort.contentContainer.Add(textField);
            var deleteButton = new Button(() => RemovePort(nodeCache, generatedPort))
            {
                text = "X"
            };
            generatedPort.contentContainer.Add(deleteButton);
            generatedPort.portName = outputPortName;
            nodeCache.outputContainer.Add(generatedPort);
            nodeCache.RefreshPorts();
            nodeCache.RefreshExpandedState();
        }

        private void RemovePort(Node node, Port socket)
        {
            var targetEdge = edges.ToList()
                .Where(x => x.output.portName == socket.portName amp;amp; x.output.node == socket.node);
            if (targetEdge.Any())
            {
                var edge = targetEdge.First();
                edge.input.Disconnect(edge);
                RemoveElement(targetEdge.First());
            }

            node.outputContainer.Remove(socket);
            node.RefreshPorts();
            node.RefreshExpandedState();
        }

        private Port GetPortInstance(DialogueNode node, Direction nodeDirection,
            Port.Capacity capacity = Port.Capacity.Single)
        {
            return node.InstantiatePort(Orientation.Horizontal, nodeDirection, capacity, typeof(float));
        }

        private DialogueNode GetEntryPointNodeInstance()
        {
            var nodeCache = new DialogueNode()
            {
                title = "START",
                GUID = Guid.NewGuid().ToString(),
                DialogueText = "ENTRYPOINT",
                EntryPoint = true
            };

            var generatedPort = GetPortInstance(nodeCache, Direction.Output);
            generatedPort.portName = "Next";
            nodeCache.outputContainer.Add(generatedPort);

            nodeCache.capabilities amp;= ~Capabilities.Movable;
            nodeCache.capabilities amp;= ~Capabilities.Deletable;

            nodeCache.RefreshExpandedState();
            nodeCache.RefreshPorts();
            nodeCache.SetPosition(new Rect(100, 200, 100, 150));
            return nodeCache;
        }
}
 

GraphSaveUtility

 using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.UIElements;

public class GraphSaveUtility
{
    private DialogueGraphView _targetGraphView;
    private DialogueContainer _containerCache;

    private List<Edge> Edges => _targetGraphView.edges.ToList();
    private List<DialogueNode> Nodes => _targetGraphView.nodes.ToList().Cast<DialogueNode>().ToList();
    public static GraphSaveUtility GetInstance(DialogueGraphView targetGraphView) {
        return new GraphSaveUtility {
            _targetGraphView = targetGraphView
        };
    }

    public void SaveGraph(string Filename) 
    {
        if(!Edges.Any()) return;

        var dialogueContainer = ScriptableObject.CreateInstance<DialogueContainer>();

        var connectedPorts = Edges.Where(x => x.input.node!=null).ToArray();

        for (var i = 0; i < connectedPorts.Length; i  ) 
        {
            var outputNode = connectedPorts[i].output.node as DialogueNode;
            var inputNode = connectedPorts[i].input.node as DialogueNode;

            dialogueContainer.NodeLinks.Add(new NodeLinkData {
                BaseNodeGuid = outputNode.GUID,
                PortName = connectedPorts[i].output.portName,
                TargetNodeGuid = inputNode.GUID
            });
        }

        foreach(var DialogueNode in Nodes.Where(node=>!node.EntryPoint)) 
        {
            dialogueContainer.DialogueNodeData.Add(new DialogueNodeData{
                GUID = DialogueNode.GUID,
                DialogueText = DialogueNode.DialogueText,
                Position = DialogueNode.GetPosition().position
            });
        }

        if(!AssetDatabase.IsValidFolder("Assets/Resources"))
            AssetDatabase.CreateFolder("Assets", "Resources");

        AssetDatabase.CreateAsset(dialogueContainer, "Assets/Resources/{fileName}.asset");
        AssetDatabase.SaveAssets();
    }

    public void  LoadGraph(string Filename) {
        _containerCache = Resources.Load<DialogueContainer>(Filename);
        if(_containerCache == null) {
            EditorUtility.DisplayDialog("File not Found", "Target dialogue graph file does not exists!", "OK");
            return;
        }

        ClearGraph();
        CreateNodes();
        ConnectNodes();
    }

    private void ClearGraph() {
        Nodes.Find(x => x.EntryPoint).GUID = _containerCache.NodeLinks[0].BaseNodeGuid;

        foreach (var node in Nodes) {
            if (node.EntryPoint) return;

            Edges.Where(x => x.input.node==node).ToList()
            .ForEach(edge => _targetGraphView.RemoveElement(edge));

            _targetGraphView.RemoveElement(node);
        }
    }

private void ConnectNodes() {
    for (var i = 0; i < Nodes.Count; i  )  {
        var connections = _containerCache.NodeLinks.Where(x=> x.BaseNodeGuid == Nodes[i].GUID).ToList();
        for (var j = 0; j < connections.Count; j  ) {
            var TargetNodeGuid = connections[j].TargetNodeGuid;
            var targetNode = Nodes.First( x => x.GUID == TargetNodeGuid);
            LinkNodes(Nodes[i].outputContainer[j].Q<Port>(), (Port) targetNode.inputContainer[0]);

            targetNode.SetPosition(new Rect(_containerCache.DialogueNodeData.First(x =>x.GUID==TargetNodeGuid).Position, _targetGraphView.DefaultNodeSize));
        }
    }
}

private void LinkNodes(Port output, Port input) {

    var tempEdge = new Edge {
        output = output,
        input = input
    };

    tempEdge.input.Connect(tempEdge);
    tempEdge.output.Connect(tempEdge);
    _targetGraphView.Add(tempEdge);

}


    private void CreateNodes() {
        foreach (var nodeData in _containerCache.DialogueNodeData) {
            var tempNode = _targetGraphView.CreateNode(nodeData.DialogueText, Vector2.zero);
            tempNode.GUID = nodeData.GUID;
            _targetGraphView.AddElement(tempNode);

            var nodePorts = _containerCache.NodeLinks.Where(x => x.BaseNodeGuid==nodeData.GUID).ToList();
            nodePorts.ForEach(x => _targetGraphView.AddChoicePort(tempNode, x.PortName));
        }
    }

}
 

DialogueNode

 using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor.Experimental.GraphView;
using UnityEngine;

    public class DialogueNode : Node
    {
        public string DialogueText;
        public string GUID;
        public bool EntryPoint = false;
    } 

DialogueGraph

 using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

    public class DialogueGraph : EditorWindow
    {
        private string _fileName = "New Narrative";

        private DialogueGraphView _graphView;
        private DialogueContainer _dialogueContainer;

        [MenuItem("Graph/Narrative Graph")]
        public static void CreateGraphViewWindow()
        {
            var window = GetWindow<DialogueGraph>();
            window.titleContent = new GUIContent("Narrative Graph");
        }

        private void ConstructGraphView()
        {
            _graphView = new DialogueGraphView(this)
            {
                name = "Narrative Graph",
            };
            _graphView.StretchToParentSize();
            rootVisualElement.Add(_graphView);
        }

        private void GenerateToolbar()
        {
            var toolbar = new Toolbar();

            var fileNameTextField = new TextField("File Name:");
            fileNameTextField.SetValueWithoutNotify(_fileName);
            fileNameTextField.MarkDirtyRepaint();
            fileNameTextField.RegisterValueChangedCallback(evt => _fileName = evt.newValue);
            toolbar.Add(fileNameTextField);

            toolbar.Add(new Button(() => RequestDataOperation(true)) {text = "Save Data"});

            toolbar.Add(new Button(() => RequestDataOperation(false)) {text = "Load Data"});
            // toolbar.Add(new Button(() => _graphView.CreateNewDialogueNode("Dialogue Node")) {text = "New Node",});
            rootVisualElement.Add(toolbar);
        }

        private void RequestDataOperation(bool save)
        {
            if (!string.IsNullOrEmpty(_fileName))
            {
                var saveUtility = GraphSaveUtility.GetInstance(_graphView);
                if (save)
                    saveUtility.SaveGraph(_fileName);
                else
                    saveUtility.LoadGraph(_fileName);
            }
            else
            {
                EditorUtility.DisplayDialog("Invalid File name", "Please Enter a valid filename", "OK");
            }
        }

        private void OnEnable()
        {
            ConstructGraphView();
            GenerateToolbar();
            GenerateMiniMap();
        }

        private void GenerateMiniMap()
        {
            var miniMap = new MiniMap {anchored = true};
            var cords = _graphView.contentViewContainer.WorldToLocal(new Vector2(this.maxSize.x - 10, 30));
            miniMap.SetPosition(new Rect(cords.x, cords.y, 200, 140));
            _graphView.Add(miniMap);
        }

        private void OnDisable()
        {
            rootVisualElement.Remove(_graphView);
        }
    } 

Комментарии:

1. Материал редактора недоступен для окончательной сборки

2. Значит, я должен отключать эти скрипты, когда хочу создать игру?

Ответ №1:

Как сказал кто-то в комментариях, Unity не может создавать материалы, использующие UnityEditor пространство имен. Однако при сборке Unity будет игнорировать все, что находится внутри папок с именем «Редактор». Поместите все те сценарии, которые вызывают проблемы, в папку с именем «Редактор», и она должна скомпилироваться без ошибок. У вас также может быть более одной папки «Editor», поэтому, если вам нужно различать ваши скрипты редактора, не стесняйтесь это делать.

Студворк — интернет-сервис помощи студентам

Всем привет, ниже ошибка при сборке игры, может кто встречал?

CommandInvokationFailure: Gradle build failed.
C:Program FilesJavajdk1.8.0_201binjava.exe -classpath «C:gradle-7.2libgradle-launcher-7.2.jar» org.gradle.launcher.GradleMain «-Dorg.gradle.jvmargs=-Xmx4096m» «bundleRelease»

stderr[

FAILURE: Build failed with an exception.

* Where:
Build file ‘C:New Unity ProjectTempgradleOutlauncherbuild.gradle’ line: 66

* What went wrong:
A problem occurred evaluating project ‘:launcher’.
> Could not set unknown property ‘assetPacks’ for extension ‘android’ of type com.android.build.gradle.internal.dsl.BaseAppModuleExtension.

* Try:
Run with —stacktrace option to get the stack trace. Run with —info or —debug option to get more log output. Run with —scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 19s
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
]
stdout[
Starting a Gradle Daemon, 1 incompatible Daemon could not be reused, use —status for details

> Configure project :launcher
WARNING: The option setting ‘android.bundle.enableUncompressedNativeLibs=false’ is experimental and unsupported.
The current default is ‘true’.

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use ‘—warning-mode all’ to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See https://docs.gradle.org/7.2/us… e_warnings
]
exit code: 1
UnityEditor.Android.Command.WaitForProgramToRun (UnityEditor.Utils.Program p, UnityEditor.Android.Command+WaitingForProcessToExit waitingForProcessToExit, System.String errorMsg) (at <f94168442e634613b6a5965ed17c38f4>:0)
UnityEditor.Android.Command.Run (System.Diagnostics.ProcessStartInfo psi, UnityEditor.Android.Command+WaitingForProcessToExit waitingForProcessToExit, System.String errorMsg) (at <f94168442e634613b6a5965ed17c38f4>:0)
UnityEditor.Android.Command.Run (System.String command, System.String args, System.String workingdir, UnityEditor.Android.Command+WaitingForProcessToExit waitingForProcessToExit, System.String errorMsg) (at <f94168442e634613b6a5965ed17c38f4>:0)
UnityEditor.Android.AndroidJavaTools.RunJava (System.String args, System.String workingdir, System.Action`1[T] progress, System.String error) (at <f94168442e634613b6a5965ed17c38f4>:0)
UnityEditor.Android.GradleWrapper.Run (UnityEditor.Android.AndroidJavaTools javaTools, System.String workingdir, System.String task, System.Action`1[T] progress) (at <f94168442e634613b6a5965ed17c38f4>:0)
Rethrow as GradleInvokationException: Gradle build failed
UnityEditor.Android.GradleWrapper.Run (UnityEditor.Android.AndroidJavaTools javaTools, System.String workingdir, System.String task, System.Action`1[T] progress) (at <f94168442e634613b6a5965ed17c38f4>:0)
UnityEditor.Android.PostProcessor.Tasks.BuildGradleProject.Execute (UnityEditor.Android.PostProcessor.PostProcessorContext context) (at <f94168442e634613b6a5965ed17c38f4>:0)
UnityEditor.Android.PostProcessor.PostProcessRunner.RunAllTasks (UnityEditor.Android.PostProcessor.PostProcessorContext context) (at <f94168442e634613b6a5965ed17c38f4>:0)
Rethrow as BuildFailedException: Exception of type ‘UnityEditor.Build.BuildFailedException’ was thrown.
UnityEditor.Android.PostProcessor.CancelPostProcess.AbortBuild (System.String title, System.String message, System.Exception ex) (at <f94168442e634613b6a5965ed17c38f4>:0)
UnityEditor.Android.PostProcessor.PostProcessRunner.RunAllTasks (UnityEditor.Android.PostProcessor.PostProcessorContext context) (at <f94168442e634613b6a5965ed17c38f4>:0)
UnityEditor.Android.PostProcessAndroidPlayer.PostProcess (UnityEditor.BuildTarget target, System.String stagingAreaData, System.String stagingArea, System.String playerPackage, System.String installPath, System.String companyName, System.String productName, UnityEditor.BuildOptions options, UnityEditor.RuntimeClassRegistry usedClassRegistry, UnityEditor.Build.Reporting.BuildReport report) (at <f94168442e634613b6a5965ed17c38f4>:0)
UnityEditor.Android.AndroidBuildPostprocessor.PostProcess (UnityEditor.Modules.BuildPostProcessArgs args, UnityEditor.BuildProperties& outProperties) (at <f94168442e634613b6a5965ed17c38f4>:0)
UnityEditor.PostprocessBuildPlayer.Postprocess (UnityEditor.BuildTargetGroup targetGroup, UnityEditor.BuildTarget target, System.String installPath, System.String companyName, System.String productName, System.Int32 width, System.Int32 height, UnityEditor.BuildOptions options, UnityEditor.RuntimeClassRegistry usedClassRegistry, UnityEditor.Build.Reporting.BuildReport report) (at <83a38f5397d94e36a22efa3369c82390>:0)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&)

SALAZAR

9.04.2022

Не совсем понял о чем речь. Скажу так. Инвентарь реализовывается через ScriptableObject. И после выхода из игры данные не будут сохраняться сами, если ты их не сохранишь в ручную.

Ответить

Развернуть ветку

SALAZAR

9.04.2022

К примеру если ты запустил билд, собрал в какой-то префаб (зачем в префаб вообще?) айтемы, то когда выйдешь из игры и зайдешь обратно. Инвентарь будет пустой, а айтемы будут на своих местах.

Ответить

Развернуть ветку

Денис Кадыков

9.04.2022

Сталкивался с другим. Физика работала по другому когда собирал ехе. Дело оказалось в настройках Ригибоди. В частности столкновений и интерполяции. Выставил по дефолту и проблемы исчезли. Что конечно жесть.

Думаю что для вашей проблемы можно попробовать что то подобное.

Ответить

Развернуть ветку

mx

9.04.2022

Тот, кто подбирает CharacterController? Если просто Collider, то добавь Kinetic Rigidbody.

Ответить

Развернуть ветку

Александр Бессонов

9.04.2022

Ещё иногда со статиком проблемы при компиляции возникают. Так например текст меш про со статиком у меня при компиляции ставился в 000 координаты.

Ответить

Развернуть ветку

Понравилась статья? Поделить с друзьями:
  • Ошибка при сбое active directory
  • Ошибка при розжиге газового котла что делать
  • Ошибка при решении элементарной задачи
  • Ошибка при речи замена букв
  • Ошибка при репликации днк какая изменчивость