Giter Club home page Giter Club logo

starikcetin / eflatun.scenereference Goto Github PK

View Code? Open in Web Editor NEW
323.0 6.0 21.0 1.96 MB

Unity Scene References for Runtime and Editor. Strongly typed, robust, and reliable. Provides GUID, Path, Build Index, Name, and Address.

Home Page: https://openupm.com/packages/com.eflatun.scenereference/

License: MIT License

C# 69.84% ShaderLab 25.19% HLSL 4.38% Shell 0.58%
reference scene unity unity3d eflatun scenereference plugin unity-package unity-package-manager unity-plugin

eflatun.scenereference's Introduction

Eflatun.SceneReference


logo


Scene References for Runtime and Editor.

Strongly typed, robust, and reliable.

Provides GUID, Path, Build Index, Name, and Address.


GitHub badge   OpenUPM badge   Monthly downloads badge


Installation

Important

Minimum compatible Unity version is 2020.3.48f1.

Get Eflatun.SceneReference

With OpenUPM (recommended)

  1. Install openupm-cli via npm. You can skip this step if already have openupm-cli installed.
npm install -g openupm-cli
  1. Install com.eflatun.scenereference in your project. Make sure to run this command at the root of your Unity project.
openupm add com.eflatun.scenereference

With Git URL

Add the following line to the dependencies section of your project's manifest.json file. Replace 4.0.0 with the version you want to install.

"com.eflatun.scenereference": "git+https://github.com/starikcetin/Eflatun.SceneReference.git#4.0.0"

Although it is highly discouraged, you can replace 4.0.0 with upm to get the latest version instead of a specific one.

Optional Dependencies

Addressables Support

Eflatun.SceneReference has support for addressables. It will be enabled or disabled automatically depending on whether you have the addressables package installed in your project. Please refer to the Addressables Package Documentation for information on how to install addressables package in your project.

Note

As a deliberate design decision in accordance with the Principle of least astonishment, the public API and settings that concern addressables will still be visible even if addressables support is disabled. This way, if you later decide to uninstall addressables from your project, you will not face an overwhelming amount of compiler errors. This enables you to transition between using and not using addressables with only a minimal amount of refactors.

Usage

  1. Define your SceneReference serialized field:
// Import Runtime namespace
using Eflatun.SceneReference;

// You can define it by itself
[SerializeField] private SceneReference mySceneReference;

// Or in a collection
[SerializeField] private List<SceneReference> mySceneReferences;
  1. Assign your scene to your SceneReference field in the inspector:

.assets/inspector.png

  1. Use it!
// Import Runtime namespace
using Eflatun.SceneReference;

// You can access these anytime, anywhere
var sceneGuid = mySceneReference.Guid;
var scenePath = mySceneReference.Path;
var sceneBuildIndex = mySceneReference.BuildIndex;
var sceneName = mySceneReference.Name;

// You can only access these when the scene is currently loaded
var loadedScene = mySceneReference.LoadedScene

// You can only access these if you have addressables support enabled
var sceneAddress = mySceneReference.Address;

Validation

You can check State property to make sure a SceneReference is completely valid before using it. It will also give you information regarding the type of the scene it references.

// Import Runtime namespace
using Eflatun.SceneReference;

if (mySceneReference.State == SceneReferenceState.Unsafe)
{
    // The scene is not safe to use. Something is wrong.
}

if (mySceneReference.State == SceneReferenceState.Regular)
{
    // The scene is safe to use. It references a regular scene.
}

// If you have addressables support enabled, you can also get this state:
if (mySceneReference.State == SceneReferenceState.Addressable)
{
    // The scene is safe to use. It references an addressable scene.
}

If you need to know why a SceneReference is deemed unsafe, you can check the UnsafeReason property.

// Import Runtime namespace
using Eflatun.SceneReference;

if (mySceneReference.UnsafeReason == SceneReferenceUnsafeReason.None)
{
    // All good. Safe to use.
}

if (mySceneReference.UnsafeReason == SceneReferenceUnsafeReason.Empty)
{
    // mySceneReference is empty. It is not referencing anything. 
}

if (mySceneReference.UnsafeReason == SceneReferenceUnsafeReason.NotInMaps)
{
    // The scene referenced by mySceneReference is not found in any of the maps.
}

if (mySceneReference.UnsafeReason == SceneReferenceUnsafeReason.NotInBuild)
{
    // The scene referenced by mySceneReference is not added and enabled in build.
}

Important

  • Empty has priority over all other reasons.
  • NotInMaps has priority over NotInBuild.

Inline Inspector Utilities

A scene will be accessible in runtime only if one of the following is true:

  1. The scene is added and enabled in build settings.
  2. The scene is in an addressables group.

Eflatun.SceneReference on the other hand, allows you to assign onto it any scene you wish. This behaviour may cause runtime bugs when loading scenes. To prevent these potential bugs, Eflatun.SceneReference provides inline inspector utilities.

In this example:

.assets/validation_inspector.png

  • Scene A field is assigned a scene that is added and enabled in build settings. All good here.
  • Scene B field is assigned a scene that is disabled in build settings.
  • Scene C field is assigned a scene that is neither in build settings nor addressable.
  • Scene D filds is assigned an addressable scene. Again, all good here.
  • Scene E field is not assigned anything. It is empty.
  • Similarly for the Scene Reference List property.

Note

Addressable scenes are only available if addressables support is enabled.

If we click on the little gear (⚙️) icon to the right of the field, a toolbox popup will open that contains the fix utilities. For Scene B field, we get the following tools:

.assets/toolbox_disabled.png

And for Scene C field, we get the following tools:

.assets/toolbox_nowhere.png

Note

You will only see the Make addressable... tool if addressables support is enabled.

Clicking on the Enable in build... button gives us this prompt:

.assets/validation_enable_prompt.png

Add to build... button gives the following prompt:

.assets/validation_add_prompt.png

And Make addressable... button gives the following prompt:

.assets/validation_addressable_prompt.png

Using these prompts, we can quickly alleviate the situation, and prevent potential runtime bugs when using these scenes.

Settings

Eflatun.SceneReference provides settings under the Project Settings.

Open the project settings via Edit/Project Settings... menu item.

Look for the Eflatun category in the left panel. Select the Scene Reference item.

.assets/settings.png

Addressables Support

Settings regarding addressables support.

Note

Settings under this category are only relevant if addressables support is enabled.

Color Addressable Scenes

Should we color the property to draw attention for addressable scenes?

Addressable scenes should be handled differently than regular scenes in runtime, through the addressables API. Therefore, you would want quickly identify if an Eflatun.SceneReference references an addressable scene or not.

It is recommended to leave this option at 'true', as it will help you easily distinguish addressable scenes.

Note

This setting does not apply to regular scenes. They have their own coloring mechanism. It is controlled by the Color Based On Scene-In-Build State setting under the Property Drawer category.

Logging

Settings regarding logging.

Note

Exceptions will always be logged.

Editor Log Level

Log level for the editor logger. It is recommended to leave this at Warning.

Property Drawer

Settings regarding the property drawer.

Show Inline Toolbox

Should we show the inline gear (⚙️) button that opens a toolbox?

Unity only bundles scenes that are added and enabled in build settings, and addressables only pack scenes that are in an Addressable Group. Therefore, you would want to make sure the scene you assign to a SceneReference is either added and enabled in build settings, or is in an addressable group. The toolbox provides tools for you to quickly take action in these cases.

It is recommended to leave this option enabled, as the toolbox saves you a lot of time.

Color Based On Scene-In-Build State

Should we color the property to draw attention for scenes that are either not in build or disabled in build?

Unity only bundles scenes that are added and enabled in build settings. Therefore, you would want to validate whether the scene you assign to a SceneReference is added and enabled in build settings.

It is recommended to leave this option at 'true', as it will help you identify many potential runtime errors.

Note

This setting does not apply to addressable scenes. They have their own coloring mechanism. It is controlled by the Color Addressable Scenes setting under the Addressables Support category.

Scene Data Maps

Settings regarding the scene data maps and the generator.

Generation Triggers

Controls when the scene data maps get regenerated.

  • After Scene Asset Change: Regenerate the maps every time a scene asset changes (delete, create, move, rename).

  • Before Enter Play Mode: Regenerate the maps before entering play mode in the editor.

  • Before Build: Regenerate the maps before a build.

  • After Packages Resolve: Regenerate the maps after UPM packages are resolved.

  • After Addressables Change: Regenerate the maps after addressable group entries change. Only relevant if you have addressables support enabled.

It is recommended that you leave this option at All unless you are debugging something. Failure to generate the maps when needed can result in broken scene references in runtime.

Note

All and Everything are the same thing. They both represent all triggers.

JSON Formatting

Controls the Scene Data Maps Generator's JSON formatting.

It is recommended to leave this option at None as it will make the generated files smaller in size.

Fail Build If Generation Fails

Should we fail a build if scene data maps generation fails?

Only relevant if Before Build generation trigger is enabled.

It is recommended to leave this option at true, as a failed map generation can result in broken scene references in runtime.

Advanced Usage

Generation Outputs

Eflatun.SceneReference outputs generated maps to three locations:

  1. JSON files under Assets/Resources. They all start with Eflatun_SceneReference_ and end with .generated.json.
  2. UserSettings.
  3. Internal direct assign to the providers.

The steps 2 and 3 run for all generations. The JSON files on the other hand, will only be generated in two circumstances:

  1. Manaully running the generator via the relevant menu item.
  2. During a build if the Before Build generation trigger is enabled.

Note

If the Before Build generation trigger is enabled, JSON map files will also be cleaned up after a build.

Warning

Map files are auto-generated, do not edit them. Any edits will be lost at the next generation.

Running the Generator Manually

The generator runs automatically according to the triggers selected in the settings. However, if for some reason you need to run the generator yourself, you can do so.

Running the generator has no side-effects (other than the JSON file output if you select the corresponding option).

Via Menu Item

You can trigger the generator via a menu item. Find it under Tools/Eflatun/Scene Reference/Generate Scene Data Maps:

.assets/generator_menu.png

Tip

Automatic generation (i.e. generation triggers) only outputs files during a build. With menu items, you decide whether to output files or not.

In Editor Code

You can trigger the generator from your editor code:

// Import Editor namespace
using Eflatun.SceneReference.Editor;

// Run the generator and output files. Only do this in Editor code!
SceneDataMapsGenerator.Run(true);

// Run the generator and but do not output files. Only do this in Editor code!
SceneDataMapsGenerator.Run(false);

Accessing Settings in Editor Code

You can read and manipulate Eflatun.SceneReference settings from your editor code.

// Import the Editor namespace
using Eflatun.SceneReference.Editor;

// Access a setting. Only do this in Editor code!
var generationTriggers = SettingsManager.SceneDataMaps.GenerationTriggers;

// Change a setting. Only do this in Editor code!
SettingsManager.SceneDataMaps.GenerationTriggers = GenerationTriggers.All;

Warning

Changing settings from code may have unintended consequences. Make sure you know what you are doing.

Accessing the Maps Directly

You can access the maps directly from both runtime and editor code. There are no side effects of accessing the maps directly.

In runtime, there are no performance penalties. The generated file is parsed automatically either upon the first access to the maps from a provider or during RuntimeInitializeLoadType.BeforeSceneLoad, whichever comes first. It is guaranteed that the generated file is parsed only once. Each provider does this for itself, there is no coordination between them.

In editor, there are also no performance penalties except for one case. The generator assigns the map directly to the providers upon every generation. This prevents unnecessarily parsing the map file/store. However, if the providers lose the values assigned by the generator due to Unity reloading the domain, and some code tries to access the map before the generator runs again, then the providers have to parse the map file/store themselves. This is what happens in that scenario:

  1. Generator runs and directly assigns the map to the providers.
  2. Something happens which triggers Unity to reload the domain.
  3. You access the map from a provider.
  4. Provider checks to see if it still has the map values, and realizes they are lost.
  5. Provider parses the map file/store.

Scene GUID to Path Map

The SceneGuidToPathMapProvider static class is responsible for providing the scene GUID to scene path mapping to the rest of the code. There are two maps, one maps from GUIDs to paths, and the other one maps from paths to GUIDs. Both maps are inversely equivalent.

// Import the Runtime namespace
using Eflatun.SceneReference;

// Get the scene path from a scene GUID. You can do this both in runtime and in editor.
var scenePath = SceneGuidToPathMapProvider.SceneGuidToPathMap[sceneGuid];

// Get the scene GUID from a scene path. You can do this both in runtime and in editor.
var sceneGuid = SceneGuidToPathMapProvider.ScenePathToGuidMap[scenePath];

Scene GUID to Address Map

Note

This map is only relevant if addressables support is enabled.

The SceneGuidToAddressMapProvider static class is responsible for providing the scene GUID to scene address mapping to the rest of the code. Unlike SceneGuidToPathMapProvider, this class cannot provide an inverse map, because the address of an asset is not guaranteed to be unique due to the design of addressables. Instead, it provides two methods called GetGuidFromAddress and TryGetGuidFromAddress that serve the same purpose.

Getting the GUID from address can fail in following cases:

  1. No scene with the given address found in the map (AddressNotFoundException).
  2. Multiple scenes found with the given address in the map (AddressNotUniqueException).
  3. Addressables support is disabled (AddressablesSupportDisabledException).
// Import the Runtime namespace
using Eflatun.SceneReference;

// Get the scene address from a scene GUID. You can do this both in runtime and in editor.
var sceneAddress = SceneGuidToAddressMapProvider.SceneGuidToAddressMap[sceneGuid];

// Get the scene GUID from a scene address. You can do this both in runtime and in editor.

// First way. Will throw exceptions on faliure.
var sceneGuid = SceneGuidToAddressMapProvider.GetGuidFromAddress(sceneAddress);

// Second way. Returns a bool that represents success or failure.
if(SceneGuidToAddressMapProvider.TryGetGuidFromAddress(sceneAddress, out var sceneGuid)) 
{
    // Success. sceneGuid is valid.
}
else 
{
    // Failure. sceneGuid is invalid.
}

Overriding Inline Inspector Utility Settings Per Field

You can override the inline inspector utility project settings on a per-field basis using the [SceneReferenceOptions] attribute. For example, in order to disable all inline utilities, use the attribute as such:

[SceneReferenceOptions(SceneInBuildColoring = ColoringBehaviour.Disabled, Toolbox = ToolboxBehaviour.Disabled, AddressableColoring = ColoringBehaviour.Disabled)]
[SerializeField] private SceneReference scene;

For all arguments, passing Enabled or Disabled will force that behaviour to be enabled or disabled respectively, disregarding the project settings. DoNotOverride makes the argument respect the project settings. DoNotOverride is the default value.

You don't have to supply both fields at once. Missing fields will have the default value, which is DoNotOverride. For example, the following code disables the toolbox, but makes coloring respect project settings:

[SceneReferenceOptions(Toolbox = ToolboxBehaviour.Disabled)]
[SerializeField] private SceneReference scene;

Note

AddressableColoring argument is only relevant if addressables support is enabled.

Custom Serialization

Serializers listed under this section are tested and supported.

If you come across any problems while using these serializers, or if you want another serializer to be supported, please open an issue.

JSON serialization via Newtonsoft.Json

Example SceneReference serialization to Json and back via Newtonsoft.Json:

using Eflatun.SceneReference;
using Newtonsoft.Json;

// Serialize
SceneReference sceneRef = /* ... */;
var serialized = JsonConvert.SerializeObject(sceneRef);

// Deserialize
string json = /* ... */;
SceneReference deserialized = JsonConvert.DeserializeObject<SceneReference>(json);

Binary serialization via System.Runtime.Serialization.Formatters.Binary

Caution

We strongly advise against using BinaryFormatter as it is inconsistent and has inherent security risks. Only use it if you absolutely have to.

Example SceneReference serialization to binary and back via System.Runtime.Serialization.Formatters.Binary:

using Eflatun.SceneReference;
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

// Serialize
SceneReference sceneRef = /* ... */;
var bf = new BinaryFormatter();
using var ms = new MemoryStream();
bf.Serialize(ms, sceneRef);
var serializedBytes = ms.ToArray();
var serializedBase64 = Convert.ToBase64String(serializedBytes);

// Deserialize
byte[] bytes = /* ... */;
var bf = new BinaryFormatter();
using var ms = new MemoryStream(bytes);
SceneReference deserialized = bf.Deserialize(ms) as SceneReference;

XML serialization via System.Xml

Example SceneReference serialization to XML and back via System.Xml:

using Eflatun.SceneReference;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

// Serialize
SceneReference sceneRef = /* ... */;
var xmlSerializer = new XmlSerializer(typeof(SceneReference));
var sb = new StringBuilder();
using var xmlWriter = XmlWriter.Create(sb);
xmlSerializer.Serialize(xmlWriter, sceneRef);
var serialized = sb.ToString();

// Deserialize
string xml = /* ... */;
var xmlSerializer = new XmlSerializer(typeof(SceneReference));
using var stringReader = new StringReader(xml);
using var xmlReader = XmlReader.Create(stringReader);
SceneReference deserialized = xmlSerializer.Deserialize(xmlReader) as SceneReference;

Creating Instances in Code

You can create instances of SceneReference in code. To facilitate this, it exposes constructors and factory methods.

// Empty (and subsequently invalid)
var empty = new SceneReference();

// From Scene GUID
string sceneGuid = /* ... */;
var fromSceneGuid = new SceneReference(sceneGuid);

// From Scene Path
string scenePath = /* ... */;
var fromScenePath = SceneReference.FromScenePath(scenePath);

// Fom Scene Address
// Will throw AddressablesSupportDisabledException if addressables support is disabled.
string sceneAddress = /* ... */;
var fromSceneAddress = SceneReference.FromAddress(sceneAddress);

// From Scene Asset 
// You can only do this in Editor code.
UnityEngine.Object sceneAsset = /* ... */;
var fromSceneAsset = new SceneReference(sceneAsset);

Important

  • Constructors and factory methods validate their arguments and throw exceptions of type SceneReferenceCreationException if they are invalid.
  • The default constructor always creates an empty instance, but it never throws.
  • FromAddress factory method throws AddressablesSupportDisabledException if addressables support is disabled.

Caution

The constructor that accepts a scene asset of type UnityEngine.Object is for Editor use only. Do NOT use it in runtime code.

Exceptions

EmptySceneReferenceException

Thrown if a SceneReference is empty (not assigned anything).

To fix it, make sure the SceneReference is assigned a valid scene asset.

You can avoid it by making sure the State property is not Unsafe.

InvalidSceneReferenceException

Thrown if a SceneReference is invalid. This can happen for these reasons:

  1. The SceneReference is assigned an invalid scene, or the assigned asset is not a scene. To fix this, make sure the SceneReference is assigned a valid scene asset.

  2. The Scene GUID to Path Map is outdated. To fix this, you can either manually run the map generator, or enable all generation triggers. It is highly recommended to keep all the generation triggers enabled.

You can avoid it by making sure the State property is not Unsafe.

SceneReferenceCreationException

Thrown when something goes wrong during the creation of a SceneReference.

It can happen for many different reasons.

The exception message contains the particular reason and suggestions on how to fix it.

AddressNotFoundException

Thrown if a given address is not found in the Scene GUID to Address Map. This can happen for these reasons:

  1. The asset with the given address either doesn't exist or is not a scene. To fix this, make sure you provide the address of a valid scene.

  2. The Scene GUID to Address Map is outdated. To fix this, you can either manually run the generator, or enable generation triggers. It is highly recommended to keep all the generation triggers enabled.

Note

This exception will never be thrown if addressables support is disabled.

AddressNotUniqueException

Thrown if a given address matches multiple entries in the Scene GUID to Address Map. This can happen for these reasons:

  1. There are multiple addressable scenes with the same given address. To fix this, make sure there is only one addressable scene with the given address.

  2. The Scene GUID to Address Map is outdated. To fix this, you can either manually run the generator, or enable generation triggers. It is highly recommended to keep all the generation triggers enabled.

Note

This exception will never be thrown if addressables support is disabled.

SceneNotAddressableException

Thrown if addressables-specific operations are attempted on a SceneReference that is assigned a non-addressable scene.

You can avoid this exception by making sure the State property is Addressable.

Note

This exception will never be thrown if addressables support is disabled.

AddressablesSupportDisabledException

Thrown if an operation that requires addressables support is attempted while addressables support is disabled.

To fix it, make sure addressables support is enabled.

SceneReferenceInternalException

This exception is not part of the public API. It indicates that something has gone wrong internally. It is not meant to be catched, fixed, or avoided by user code.

If you come across this exception, make sure to create a bug report by opening an issue and including the relevant information in the exception message.

Acknowledgements

  • This project is inspired by JohannesMP's SceneReference. For many years I have used his original implementation of a runtime Scene Reference. Many thanks to @JohannesMP for saving me countless hours of debugging, and inspiring me to come up with a more robust way to tackle this problem that Unity refuses to solve.

  • README header inspired by Angular's README.

Similar Projects

If this project doesn't suit your needs, you can always let me know by opening an issue or creating a discussion and I will see what we can do about it. If you think you absolutely need another approach, here are some similar projects to check out:

License

MIT License. Refer to the LICENSE.md file.

Copyright (c) 2022 S. Tarık Çetin

eflatun.scenereference's People

Contributors

ale1 avatar gableroux avatar starikcetin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

eflatun.scenereference's Issues

Add support for dragging and dropping multiple scene files on lists (& other collections)

The issue:

The package doesn't allow populating a List of SceneReferences with multiple scene files in the inspector (via box selecting multiple files and dragging and dropping in the component's inspector).

Expected behavior:

Dragging and dropping multiple scene files into an list of SceneReferences should allow populating that list with the dropped files.

Steps to reproduce:

  1. Open Unity with any project containing the package
  2. Create an empty object and add a script to it
  3. Inside that script, add a variable of type List<SceneReference>;
  4. Back in the Unity inspector, select multiple scene files and try dragging them into the newly-created List variable; This should not be possible, even though it "would" be expected (as it is a pretty common QoL improvement)

Other

sceneRef_issue.mp4

There's no way to check if SceneReference is assigned or not

In my code I want to do this:
if (sceneReference != null) { //do something }

However, sceneReference will never be null, and there is no property or method to check if anything has been assigned in the inspector, and HasValue or IsSafeToUse does not work for this use case. Is this intentional or am I missing something?
In my case, I'm using scene reference to set up a map transition script. If the scene reference variable is empty, I want to just teleport the player to a spawn location of the same scene.

Doing any of the following will produce a SceneReferenceInternalException error if the inspector value is empty:
if (sceneReference != null) { //do something }
if (sceneReference.HasValue) { //do something }
if (sceneReference.IsSafeToUse) { //do something }

Documentation/API improvement: SceneReference is serialized so we must check AssetGuidHex not empty, else need IsValid method

I wanted to check if SceneReference was null before using it, but due to serialization, Unity creates a default instance with invalid fields (sceneAsset is null, strings are empty, other properties cause exception on access).

So, basically, my null check if (mySceneReference != null) is always verified, and my code tries to use it even when not set.

Trying to access BuildIndex then causes an obscure error:

KeyNotFoundException: The given key '' was not present in the dictionary.
System.Collections.Generic.Dictionary`2[TKey,TValue].get_Item (TKey key) (at <7560840559c84ffbb83a08c4696f01f7>:0)
Eflatun.SceneReference.SceneReference.get_Path () (at Library/PackageCache/[email protected]/Runtime/SceneReference.cs:26)
Eflatun.SceneReference.SceneReference.get_BuildIndex () (at Library/PackageCache/[email protected]/Runtime/SceneReference.cs:31)

There's not much to do about it if we want to serialize the whole class, but at least the README documentation should indicate in usage that before using the field, it may be good to check for if (!string.IsNullOrEmpty(mySceneReference.AssetGuidHex) or the likes.

I also tried to check mySceneReference.sceneAsset != null, but the field is internal so I could not access it. I suppose we could add a bool IsValid() method that checks sceneAsset to avoid the more complicated AssetGuidHex check.

Entity SubScene Support

Entity scenes work differently from regular scenes.

Opening this issue even though entities is still in preview (though not for long if I heard right). I don't know if they will be modifying this, so perhaps it is too early, but I'll describe the current state.

  • If you load a scene from the build settings, which contains a SubScene, everything works as expected. The SubScene does not need to be in the list directly (in fact, I suspect it is best to make sure it isn't).
  • If you load a SubScene programmatically (using the guid given by this repository's SceneReference for example), the SubScene must be referenced by a scene (can be any) in the build settings, or it will not be able to be loaded.

Personally I've created a scene that contains all my SubScenes and I've added it to the build settings scene list. This works fine.

image
image

Adding this repo as a submodule is not possible because it's a whole Unity project

Hello there,

the title says it all: We prefer to add utility tools like SceneReference as submodules to our Core-repository. That's only possible if the repo is not a full blown Unity project with assets, meta files and stuff. Is there a reason why this repo is not just the SceneReference code? This would make it much easier for us to add and maintain this repo.

Visually improve inline utility

Currently, when the inline utility line shows up for consecutive fields, it is not clear which field the utility line belongs to, especially if they are colored the same way. We need to improve the visual representation to make it visually clear which utility belongs to which field.

Add CI

Add semantic release CI using GitHub actions.

Need HasValue at editor time, why is it private?

The title says it all. I need to check if a scene reference has assigned a scene or not, to throw a warning if it's missing. Is there any way to achieve this?
Using State.Unsafe doesn't work because it will mark a scene that's referenced but not in the build settings as Unsafe. I specifically need to know if the designers referenced a scene.

Feature Request: Add "Open Build Settings..." opion

The Problem

I think I'd rather go to Build Settings and add the scene there manually if it's missing, so I can control it's exact placement, rather than just press the Add to Build button and leave it at that.

Potential Solutions

  1. The dialog that opens when you press the Add to Build button could contain an Open Build Settings... option. That would be more useful for me than the Add to Build as Disabled option it currently has.
  2. A context menu item for opening Build Settings (EditorApplication.ExecuteMenuItem("File/Build Settings...")). The good thing about this would be that it could be used even after the Add to Build button has already gone away. The downside is that it would be easy to miss this feature, as it's completely hidden.

Move RunSceneGUIDToPathMapGenerator MenuItem to Tools tab

Right now MenuItem RunSceneGUIDToPathMapGenerator locates at "Eflatun/Scene Reference".
But Unity projects often have a lot of packages and the toolbar becomes too big.

Would be nice to move the location of the MenuItem under the Tools tab.
For example, "Tools/Eflatun Scene Reference/RunSceneGUIDToPathMapGenerator".

Continuous NullReferenceException when Addressables Settings not initialised

Initially thought it was an incompatability with Odin Inspector.

Uninstalling Addressables package worked to stop the continuous logging.

But found out it was because I hadn't initialised Addressable Settings yet - ie the package was installed but I haven't got round to using it yet in the Project.

Maybe a check needed somewhere.

`[Exception] NullReferenceException: Object reference not set to an instance of an object
Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
Rethrow as OdinPropertyException: This error occurred while being drawn by Odin.
Current IMGUI event: repaint
Odin Property Path: worldScene
Odin Drawer Chain:

PropertyContextMenuDrawer
ReferenceDrawer
FixUnityNullDrawer
NullableReferenceDrawer
UnityPropertyDrawer<SceneReferencePropertyDrawer, SceneReference>
CompositeDrawer.
SceneReferencePropertyDrawer.Init() at Library/PackageCache/com.eflatun.scenereference@c94f1c9902/Editor/SceneReferencePropertyDrawer.cs:84

SceneReferencePropertyDrawer.OnGUI() at Library/PackageCache/com.eflatun.scenereference@c94f1c9902/Editor/SceneReferencePropertyDrawer.cs:129

PropertyDrawer.OnGUISafe() at /Users/bokken/build/output/unity/unity/Editor/Mono/ScriptAttributeGUI/PropertyDrawer.cs:23

PropertyHandler.OnGUI() at /Users/bokken/build/output/unity/unity/Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs:170

PropertyHandler.OnGUI() at /Users/bokken/build/output/unity/unity/Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs:131

RuntimeMethodInfo.Invoke() at :0

UnityPropertyHandlerUtility.PropertyHandlerOnGUI() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/Value Drawers/UnityPropertyHandlerUtility.cs:216

Sirenix.OdinInspector.Editor.UnityPropertyDrawer`2[TDrawer,TDrawnType].DrawPropertyLayout() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/Value Drawers/UnityPropertyDrawer.cs:127

OdinDrawer.CallNextDrawer() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/OdinDrawer.cs:155

Sirenix.OdinInspector.Editor.Drawers.NullableReferenceDrawer`1[T].DrawPropertyLayout() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/Misc Drawers/NullableReferenceDrawer.cs:113

OdinDrawer.CallNextDrawer() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/OdinDrawer.cs:155

Sirenix.OdinInspector.Editor.Drawers.FixUnityNullDrawer`1[T].DrawPropertyLayout() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/Misc Drawers/FixUnityNullDrawer.cs:87

OdinDrawer.CallNextDrawer() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/OdinDrawer.cs:155

Sirenix.OdinInspector.Editor.Drawers.ReferenceDrawer`1[T].DrawPropertyLayout() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/Misc Drawers/ReferenceDrawer.cs:118

OdinDrawer.CallNextDrawer() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/OdinDrawer.cs:155

Sirenix.OdinInspector.Editor.Drawers.PropertyContextMenuDrawer`1[T].DrawPropertyLayout() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/Misc Drawers/PropertyContextMenuDrawer.cs:659

OdinDrawer.DrawProperty() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/OdinDrawer.cs:109

InspectorProperty.Draw() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/InspectorProperty.cs:849

Debug.LogException()

InspectorProperty.Draw() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/InspectorProperty.cs:926

InspectorProperty.Draw() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/InspectorProperty.cs:737

UnityObjectRootDrawer`1.DrawPropertyLayout() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/Value Drawers/UnityObjectRootDrawer.cs:60

OdinDrawer.CallNextDrawer() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/OdinDrawer.cs:155

FixBrokenUnityObjectWrapperDrawer`1.DrawPropertyLayout() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/Attribute Drawers/FixBrokenUnityObjectWrapperDrawer.cs:41

OdinDrawer.DrawProperty() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/OdinDrawer.cs:109

InspectorProperty.Draw() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/InspectorProperty.cs:849

PropertyTree.DrawProperties() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/PropertyTree.cs:552

PropertyTree.Draw() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Core/PropertyTree.cs:444

OdinEditor.DrawTree() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/OdinEditor.cs:97

OdinEditor.DrawOdinInspector() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/OdinEditor.cs:254

OdinEditor.OnInspectorGUI() at C:/Sirenix/Sirenix Solution/Sirenix.OdinInspector.Editor/Drawers/OdinEditor.cs:79

GUIUtility.ProcessEvent() at /Users/bokken/build/output/unity/unity/Modules/IMGUI/GUIUtility.cs:189
`

Investigate compatibility issues with `BinaryFormatter`

Discussed in #26

Originally posted by Rava4U November 28, 2022
Hi!
In a game I'm trying to develop (as a total beginner, by the way, so please be patient with me:-) ) I'm using the JohannesMP's version of this Scene Reference tool, which I'm finding extremely helpful. However, I came across a small personal issue: it looks like SceneReference is not serializable, or at least trying to create a save file containing Scene Reference through the binary formatter causes a Serialization Exception error.
My questions are:

  • is JohannesMP's SceneReference serializable? I couldn't find the answer by myself and, if I understood correctly, that version of the project is no longer supported, that's why I came here!
  • is THIS Scene Reference tool serializable, alternatively? It would be a great help if it was (otherwise, I have a suitable, even if less practical, plan B for what I need to do).
    Any help is greatly welcome!

Andrea

PS: I'm also new to GitHub, so forgive me if I'm asking things the wrong way or in the wrong place

Add support for SceneReference type properties in Unity Events in inspector

While this is minor and can be easily worked around, I did notice that when you create a method like this one

public void LoadSceneAdditive(SceneReference sceneReference)
{
      if (sceneReference.State == SceneReferenceState.Unsafe)
      {
            Debug.LogError($"scene reference is unsafe!: {sceneReference.UnsafeReason}");
            return;
      }
           
      SceneManager.LoadSceneAsync(sceneReference.BuildIndex, LoadSceneMode.Additive);
}

then in the inspector for something like a button, it doesn't show up when registering it for a unity event

image

again, this is a very minor issue as it's straightforward to work around with a separate script that can sit on each button to hold the ScreenReference but it would be a nice QOL thing to have added

GitIgnored scenes being added to SceneGuidToPathMap json

(1) Add one of your scenes to .gitignore
(2) run SceneGuitToPathMap. the .gitignored scene will be partof the json.
(3) howeber, other users of the repo wont have that scene in their proj (since gitignored) but it wil be listed in the map.

there could be potential issues where users create a new asset, and it gets randomly assigned the same guid that according to the scene map is pointing to a scene, but accoriding to unity its pointing to a completely unrelated asset.

Addressable Scene Support

if scene is marked as addressable, the scenemap json generator should refresh, and save to the json the addressable key. This will allow in runtime to then run Addressables.LoadResourceLocationsAsync(MySceneReference.addressableKey), which will find you the scene in the addressable catalog and from there you can load the asset through the addressables system.

`[SceneReferenceOptions]` attribute does not work for nested fields

This is an example of when it doesn't work:

public class NestedOptionsTest : MonoBehaviour
{
    [SerializeField] private Container container;
}

[Serializable]
public class Container
{
    [SceneReferenceOptions(UtilityLine = UtilityLineBehaviour.Disabled, Coloring = ColoringBehaviour.Enabled)] 
    [SerializeField] private SceneReference sceneReferenceField;
}

If you are seeing this, something has gone wrong internally

Hello!

I'm using your excellent SceneReference in a project and I'm getting this error. I have a scene field that is optional and I get this error when I try to access the scene field when no scene is selected.

SceneReferenceInternalException: [Eflatun.SceneReference] If you are seeing this, something has gone wrong internally. Please open an issue on Github (https://github.com/starikcetin/Eflatun.SceneReference/issues) and include the following information: Location: 54783205 Info: AssetGuidHex is invalid. AssetGuidHex: "" Eflatun.SceneReference.SceneReference.get_HasValue () (at ./Library/PackageCache/com.eflatun.scenereference@928ac7f606/Runtime/SceneReference.cs:115)

Regardless of what I try to access on the class, I get the same error. HasValue, IsSafeToUse etc.

Unsupported type SceneReference

I use Unity 2022.3.6f1

I assign a value to SceneName in a script that contains OnValidate()

[SerializeField] private SceneReference nextScene;
public string SceneName = "";

#if UNITY_EDITOR
void OnValidate()
{
    SetMissionValue();
}
#endif

void Awake()
{
    SetMissionValue();
}

void SetMissionValue()
{
    if (nextScene.State == SceneReferenceState.Regular)
        SceneName = nextScene.Name;
}

The editor throws an error:

Unsupported type SceneReference
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)

FEATURE REQUEST: mapping via static call in-Editor

I'm a big fan of SceneReference but I never liked how it created json files for serialization inside a folder you need to source control. It keeps me from referencing this package inside of other packages, since I would have to communicate users they have to put these extra lines in their source control, and users may find my packages from multiple different sources.

What if you serialized guids inside a json file only once you build the game? And then, in the editor, it uses (something like) this?

public class SceneReference
{
    public SceneAsset sceneAsset;

    public string path => AssetDatabase.GetAssetPath(sceneAsset);
}

Obviously wrapped in #if UNITY_EDITOR where appropriate.

auto trigger script reload after entering play mode

Thanks for your hard work! My problem is, the package would trigger script reload when entering play mode, which breaks my hot reload workflow. Remove the package would fix the problem, do you have any idea about it?

Suggestion: Add attribute to ignore build check for scenes

Hi, I'd like to suggest an attribute to add to scene reference fields to not draw the build index check for certain scenes only. Maybe even draw such scenes in a different color (blue as default?).

Something like:

[UncheckedSceneReference]
public SceneReference scene;

Some scenes are used only by editor tools and don't need to be in the build index. This would be really useful. Especially because your library is currently the best for handling scene references.

I can code this change if you'd like.

Add Tests

  • Add tests for runtime assembly.
  • Add tests for editor assembly.
  • Add a test that tries to build the project.
  • Configure tests to run on PRs and commits.

Fine-grain scene asset modification generation trigger

Hey, another recommendation here!
Currently, the regeneration of the map is defaulted to a setup that occurs whenever I save a scene. This causes it to add info to the console (default setting for the asset is debug logging level) every time I save a scene.
I believe two changes would be great, one is defaulting to warning, not debug.
Another is to listen to scene files being created/deleted instead of each change/save, to generate.
You can add hooks for OnWillDeleteAsset and OnWillCreateAsset.

Sorry if you considered this already. It's just that I work with a very pedant team and the console 'spam' got to them more than the value your plugin generates, which is crazy for me.
Still, amazing work! I hope I'm helping giving suggestions.

Missing map files cause error during initial editor launch

Steps to reproduce:

  1. Close Unity.
  2. Remove the map files.
  3. Launch project.

Error message:

[Eflatun.SceneReference] Scene GUID to path map file not found!
UnityEngine.Debug:LogError (object)
Eflatun.SceneReference.Logger:Error (string) (at ./Packages/com.eflatun.scenereference/Runtime/Logger.cs:7)
Eflatun.SceneReference.SceneGuidToPathMapProvider:Load () (at ./Packages/com.eflatun.scenereference/Runtime/SceneGuidToPathMapProvider.cs:66)
Eflatun.SceneReference.SceneGuidToPathMapProvider:LoadIfNotAlready () (at ./Packages/com.eflatun.scenereference/Runtime/SceneGuidToPathMapProvider.cs:55)
Eflatun.SceneReference.SceneGuidToPathMapProvider:get_SceneGuidToPathMap () (at ./Packages/com.eflatun.scenereference/Runtime/SceneGuidToPathMapProvider.cs:27)
Eflatun.SceneReference.Editor.MapGeneratorTriggers.SceneAssetPostprocessor:OnPostprocessAllAssets (string[],string[],string[],string[]) (at ./Packages/com.eflatun.scenereference/Editor/MapGeneratorTriggers/SceneAssetPostprocessor.cs:11)
UnityEditor.AssetPostprocessingInternal:PostprocessAllAssets (string[],string[],string[],string[],string[],bool)

The map files are expected to be missing during the initial launch, so we should not print any errors at that point. Though the map generation still turns out fine, I am still marking this issue as a bug since it looks like one.

GenerationTriggers not rendering in Project Settings inspector (2022.3)

Something about the SceneDataMapsGeneratorTriggers enum isn't sitting well with the Editor settings window: while the GenerationTriggers user setting field is set to be rendered (i.e. its attribute is not commented out), an IndexOutOfRangeException and InvalidCastException occur, and the entire settings menu fails to render. This occurs both on Windows and Mac, in 2022.3.

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.