• Advertisement


  • Content count

  • Joined

  • Last visited

Community Reputation

785 Good

About Liort

  • Rank
  1. Hey All ! The slides from our presentation on "Unity and WebGL" are now available here: http://bit.ly/1G8Ju5f We talked about the process of getting our game "Wonderball Heroes" to WebGL, and all the challenges, optimizations and other bugs we faced along the way. It's pretty technical, but may be really helpful for all of you planning to support this platform with Unity 5. Check it out, and feel free to comment / contact me in case you have any questions !
  2. Auto Save for Unity

    Actually this solution can also save the project when saving the scene. I did not add that part to the code here though.
  3. Auto Save for Unity

    Thanks hexaust. That link is actually mentioned under "Related Resources" in the bottom of the article :)
  4. Auto Save for Unity

    I am not familiar with the issue that Unity does not properly save the scene, so my guess is that there's 50/50 chance this code will help in that case.
  5. Auto Save for Unity

    This article was originally posted on Random Bits. Check it out for more Unity related content. What can you do when a team member suffers a recurring Unity editor crash, losing all level design work ? My answer was to write a small and helpful editor extension - auto save! (and then blog about it). TL;DR This post describes a simple solution for implementing auto save in Unity that saves the currently open scene every 5 minutes (configurable). The code is available for easy consumption in a few ways: GitHub - Also updated in case i get any feedback / future posts Gist The code is imported and works out of the box, import / paste it into your Unity project and you're good to go. Problem It started a few days ago: a member of our team started experiencing occasional Unity editor crashes a few times daily. We do not know the exact reason for crashes, but we suspect it may be related to memory issues combined with voodoo magic. No matter what the root cause was, these crashes caused real damage in lost data (game levels) which we could not afford having. In order to keep lost work to a minimum, I suggested to implement a basic auto save solution, so at least we can go back to a backup in case the editor crashes. Solution - AutoSave The solution uses pretty simple editor scripting to the rescue. The process can be described in 3 main steps: Hook a delegate to EditorApplication.update. In this method, check if the scene should be saved (if the configured time has elapsed. The default is 5 minutes). In case we need to save, generate a new unique name for the scene and save it to disk. In order to have the code up and running when you launch the editor, the class is marked with the [InitializeOnLoad] attribute and initialization is done in its static constructor. Show Me the Code This is the complete code, you can paste it into your project:using System;using System.IO;using System.Globalization;using UnityEditor;using UnityEngine; [InitializeOnLoad]public class AutoSaveScene{ private const string SAVE_FOLDER = "Editor/AutoSaves"; private static System.DateTime lastSaveTime = System.DateTime.Now; private static System.TimeSpan updateInterval; static AutoSaveScene() { EnsureAutoSavePathExists(); // Register for autosaves. // Change this number to modify the autosave interval. RegisterOnEditorUpdate(5); } public static void RegisterOnEditorUpdate(int interval) { Debug.Log ("Enabling AutoSave"); updateInterval = new TimeSpan(0, interval, 0); EditorApplication.update += OnUpdate; } /// /// Makes sure the target save path exists. /// private static void EnsureAutoSavePathExists() { var path = Path.Combine(Application.dataPath, SAVE_FOLDER); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } } /// /// Saves a copy of the currently open scene. /// private static void SaveScene() { Debug.Log("Auto saving scene: " + EditorApplication.currentScene); EnsureAutoSavePathExists(); // Get the new saved scene name. var newName = GetNewSceneName(EditorApplication.currentScene); var folder = Path.Combine("Assets", SAVE_FOLDER); EditorApplication.SaveScene(Path.Combine(folder, newName), true); EditorApplication.SaveAssets(); } /// /// Helper method that creates a new scene name. /// private static string GetNewSceneName(string originalSceneName) { var scene = Path.GetFileNameWithoutExtension(originalSceneName); return string.Format( "{0}_{1}.unity", scene, System.DateTime.Now.ToString( "yyyy-MM-dd_HH-mm-ss", CultureInfo.InvariantCulture)); } private static void OnUpdate() { if ((System.DateTime.Now - lastSaveTime) >= updateInterval) { SaveScene(); lastSaveTime = System.DateTime.Now; } }} Built In AutoSave It should be noted that apparently Unity does autosave the current scene every time you enter play mode. If this is enough for you (for example - the game crashed during play mode), a copy of the scene can be found in YourProject/Temp/__EditModeScene. Conclusion The code in this post helps ensuring no scene data is lost when experiencing editor crashes. I deliberately kept it short & simple so it can be easily "digested". Autosaving can be further visited by adding any of the following: Configuration - Allow controlling autosave (turning on/off, setting time interval) from an editor window or menu item. Capping number of autosaves - Nobody really needs 50 copies of the open scene; instead, only 1 or 2 copies can be saved and recycled on every new save. New save triggers - The current code saves every X minutes. The code can be adapted to save under different scenarios. Related Resources AutoSave (on Run) SaveScene
  6. Reducing Unity game file size

    We also have a component that does the texture loading, and we have implemented an editor helper script that automatically replaces a sprite renderer with the new system, as needed.   Whenever we find a sprite that is too large, we can right-click it and automatically switch to the .bytes solution.   This is done by adding code similar to this:   /// <summary> /// Creates a .bytes object equivalent from a Sprite. /// </summary> [MenuItem("CONTEXT/SpriteRenderer/Create .bytes texture")] private static void CreateBytes(MenuCommand command) { var spriteRenderer = command.context as SpriteRenderer; var sprite = spriteRenderer.sprite;   if (sprite != null) { // Copy sprite to .bytes (or rename) // Add a component to this game object } }
  7. While working with Untiy, missing references can occur for many different reasons. They are simply a broken "link" between objects and can result in the game not behaving correctly or even crash. I just posted a new article on my blog on how to find missing references in Unity: http://www.tallior.com/fixing-missing-references/ Check it out and let me know if it was helpful :)
  8. Attention attention, Unity developers. I have written a short post, summarizing all of Unity's public attributes (45 in total). Check it out here to see how many you already know, and to learn about the rest: http://www.tallior.com/unity-attributes/
  9. Our game - Wonderball Heroes, has recently hit the 500K download mark on Google Play. For more info (and the download link to check out the game), see this post: http://www.tallior.com/wonderball-heroes-500k-downloads/
  10. Hello fellow devs, I have posted an article (first one in a planned series) on extending the Unity editor. The first part deals with creating menu items, and it is available here: http://www.tallior.com/2014/09/16/unity-editor-extensions-menu-items/ Check it out, and feel free to share/leave comments.
  11. This is a call to all adventure game lovers - a good friend is running a Kickstarter campaign to raise funds for a cool adventure game called Bolt Riley. Please check it out: https://www.kickstarter.com/projects/soundguy/bolt-riley-a-reggae-adventure-game-chapter-1 If you like it - pledge to make it happen
  12. For those who are working with Unity and ScriptableObjects, one concern is how to actually instantiate scriptable objects. The editor does not have any out-of-the-box option for doing so, and you have to do that manually in code for every type of object you define. I have posted a new entry on my blog, containing a generic solution for this issue - an editor extension that will allow you to easily create ScriptableObject instances of any kind directly from the editor. Please check out the post here - http://www.tallior.com/2014/08/06/unity-scriptableobject-factory/ Let me know if you find it helpful !
  13. Introduction to Unity Test Tools

    Note that the example i gave for instantiating a MonoBehaviour derived class using its constructor is discouraged by Unity, as these are created by the engine itself. It is better off to use the "Humble Object" pattern, see this post for further details: http://blogs.unity3d.com/2014/06/03/unit-testing-part-2-unit-testing-monobehaviours/
  14. This article was originally posted on Random Bits Unity Test Tools is a package officially released by the folks at Unity in December 2013. It provides developers the components needed for creating and executing automated tests without leaving the comforts of the Unity editor. The package is available for download here. This article serves as a high level overview of the tools rather than an in-depth drill-down. It covers the 3 components the package is comprised of: Unit tests Integration tests Assertion component The package comes with detailed PDF documentation (in English and Japanese), examples and the complete source code so you can do modifications in case they are needed. Unit Tests There are many definitions to what a "unit test" is. In the context of this article it will be defined as a test that is: Written in code. Focuses on a single "thing" (method/class). Does not have "external dependencies" (e.g: does not rely on the Unity editor or needs to connect to an online service database). Writing Unit Tests To create unit tests, the package uses NUnit - a very popular framework that helps with the creation and execution of unit tests. Also included is NSubstitute - a mocking framework that can create "fake" objects. These fakes are objects that are passed to the method under test instead of a "real" object, in cases where the "real" object can't be created for testing since it relies on external resources (files, databases, remote servers, etc). For more information check out the NSubstitute site. The following example shows a simple script that manages player health: // A simple component that keeps track of health for game objects. public class HealthComponent : MonoBehaviour { public float healthAmount; public void TakeDamage(float damageAmount) { healthAmount -= damageAmount; } } Here is an example of a simple unit test for it: using Nunit.Framework; [TestFixture] public class HealthComponentTests { [Test] public void TakeDamage_PositiveAmount_HealthUpdated() { // Create a health component with initial health = 50. HealthComponent health = new HealthComponent(); health.healthAmount = 50f; health.TakeDamage(10f); // assert (verify) that healthAmount was updated. Assert.AreEqual(40f, health.healthAmount) } } In this unit test example, we can see that: A class containing tests should be decorated with the [TestFixture] attribute. A unit test method should be decorated with the [Test] attribute. The test constructs the class it is going to test, interacts with it (calls the TakeDamage method) and asserts (verifies) the expected results afterwards using NUnit's Assert class. *For more information on using NUnit, see the links section at the bottom of the article (Unit Testing Succinctly shows the usage of the NUnit API). Unit Test Runner After adding unit tests, we can run them using the unit test runner. The included unit test runner is opened from the toolbar menu: It is a basic runner that allows executing a single test, all tests in the project or all previously failed tests. There are other more advanced options, such as setting it to run automatically on code compilation. The test runner window displays all the tests in your project by organizing them under the class in which they were defined and can also display exception or log messages from their execution. The runner can also be invoked from code, making it possible to run all tests from the command line. Unity.exe -projectPath PATH_TO_YOUR_PROJECT -batchmode -quit -executeMethod UnityTest.Batch.RunUnitTests -resultFilePath=C:\temp\results.xml *The resultFilePath parameter is optional: It is used for specifying the path for storing the generated report of running all tests. Integration Tests Sometimes, unit tests are just too low-level. It is often desired to test multiple components, objects and the interaction between them. The package contains an Integration testing framework that allows creating and executing tests using real game objects and components in separate "test" scenes. Writing Integration Tests Integration tests, unlike unit tests, are not written in code. Instead, a new scene should be added to the project. This scene will contain test objects, each of which defines a single integration test. Step by Step Create a new scene used for testing (it can be helpful to have a naming convention for these scenes, so it's easier to remove them later on when building the game). Open the Integration Test Runner (from the toolbar menu). A new integration test is added using the + sign. When adding a test, a Test Runner object is also automatically added to the scene. Pressing + adds a new test object to the scene hierarchy. Under this test object, all game objects that are needed for the integration test are added. For example - a Sphere object was added under the new test: The CallTesting script is added to this sphere: Execution Flow The integration test runner will clean up the scene and, for every test, will create all game objects under that test (the Sphere in this case). The integration test runs in the scene with all the real game objects that were created. In this example, the Sphere uses the CallTesting helper script. This simply calls Testing.Pass() to pass the test. An integration test can pass/fail in other ways as well (see documentation). The nice thing is that each test is run independently from others (the runner cleans up the scene before each test). Also, real game objects with their real logic can be used, making integration tests a very strong way to test your game objects in a separate, isolated scene. The integration test runner can also be invoked from code, making it possible to run all tests from the command line: Unity.exe -batchmode -projectPath PATH_TO_YOUR_PROJECT -executeMethod UnityTest.Batch.RunIntegrationTests -testscenes=scene1,scene2 -targetPlatform=StandaloneWindows -resultsFileDirectory=C:\temp\ *See the documentation for the different parameters needed for command line execution. Assertion Component The assertion component is the final piece of the puzzle. While not being strictly related to testing per se, it can be extremely useful for debugging hard to trace issues. The way it works is by configuring assertions and when they should be tested. An assertion is an equality comparison between two given arguments and in the case where it fails, an error is raised (the editor can be configured to pause if 'Error Pause' is set in the Console window). If you're familiar with NUnit's Assert class (demonstrated above), the assertion component provides a similar experience, without having to writing the code for it. Working with Assertions After adding the assertion component to a game object you should configure what is the comparison to be performed and when should it be performed. Step by Step Select a comparer type (BoolComparer in the screenshot above, but there are more out of the box). This affects the fields that can be compared (bool type in this case). Select what to compare - the dropdown automatically gets populated with all available fields, depending on the comparer that was selected. These may come from the game object the assertion component was added to, from other added components on the game object or other static fields. Select what to compare to - under "Compare to type" you can select another game object or a constant value to compare to. Select when to perform the comparison (in the screenshot above the comparison is performed in the OnDestroy method). It is possible to have multiple selections as well. When running the game, the configured assertion is executed (in the screenshot above - on every OnDestroy method, MainCamera.Camera.hdr will be checked that it matches Cube.gameObject.isStatic. When setting up multiple assertions, the Assertion Explorer window provides a high level view of all configured assertions (accessed from the toolbar menu): The assertion component, when mixed with "Error Pause" can be used as a "smart breakpoint" - complex assertions and comparisons can be set up in different methods. When these fail the execution will break. Performing this while the debugger is attached can be an extremely efficient way to debug hard to find errors in your code. Conclusion Unity Test Tools provides a solid framework for writing and executing unit tests. For the first time, the tools needed for automated testing are provided in a single package. The fact that these are released and used internally by Unity shows their commitment and the importance of automated testing. In case you don't test your code and wanted to start out - now would be an awesome time to do so. Links Books The Art of Unit Testing / Roy Osherove (Amazon) Unit Testing Succinctly / SyncFusion (Free Download) xUnit Test Patterns / Gerard Meszaros (Amazon) Tools/Frameworks This is a list of a few mocking frameworks worth checking out: NUnit NSubstitute Moq FakeItEasy Blogs/Articles http://blogs.unity3d.com/2013/12/18/unity-test-tools-released/ http://blogs.unity3d.com/2014/03/12/unity-test-tools-1-2-have-been-released/
  • Advertisement