Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

Get data from Config

Discussion in 'Project Tiny' started by Ferran_SP, Jun 6, 2019.

  1. Ferran_SP

    Ferran_SP

    Joined:
    Jul 9, 2018
    Posts:
    27
    Hi,

    following the example of the SpawnAndDestroy sample, I'm trying spawn Scenes (much as in Typescript I'd have tried to spawn EntityGroups).

    I'm trying to define scene references in the config data.
    To do that, I've created a struct that inherits from IBufferElementData.

    public struct TestSceneRefs : IBufferElementData
    {
    public SceneReference MySceneRefs;
    }


    Then, back in the Editor: tap Configurations at the bottom of the Hierarchy panel -> Add Component -> add the newly created TestSceneRefs -> Set a ref to a scene:
    upload_2019-6-6_16-2-50.png


    In code, I'm trying to retrieve this by doing:

    env.GetConfigBufferData<TestSceneRefs>().Reinterpret<SceneReference>().ToNativeArray(Unity.Collections.Allocator.Temp)


    Unfortunately, for some reason, this array is empty, and I can't figure out why.
    It's as if the ConfigData is empty, or isn't aware of the changes.
    Does anybody have a clue what I am missing?
     
  2. AlexMasse

    AlexMasse

    Joined:
    Jun 29, 2014
    Posts:
    19
    Not sure why it's empty but in your case, maybe an IComponentData would work best?

    Code (CSharp):
    1. public struct TestSceneRefs : IComponentData
    2. {
    3.        public SceneReference MenuScene;
    4.        public SceneReference GameScene;
    5. }
    6.  
    7. var gameScene = env.GetConfigData<TestSceneRefs>().GameScene;
     
  3. robertg_unity

    robertg_unity

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    32
    There seems to be an issue with the Configuration entity. Apparently we are not resolving the entity references for that particular entity.
     
  4. Ferran_SP

    Ferran_SP

    Joined:
    Jul 9, 2018
    Posts:
    27
    You're right, an IComponentData is better.
    I had copied the AllyShips example in the SpawnAndDestroy sample, and they use a buffer there I guess to showcase how to have dynamic data there.
    Still, if I try to get the gameScene in the way you suggested, I get a GUID that's all 0s, as if it had not been initialized.
    I guess it's what robertg is saying:

    Do you know why does it work in the SpanwAndDestroy sample, then?

    I'm thinking a workaround for this could be to store the SceneRefs in an a different entity in each Scene, so that I can effectively load Scenes.
    Or is there any other way to load Scenes?
     
  5. furroy

    furroy

    Joined:
    Feb 24, 2017
    Posts:
    93
    Are you calling it an OnCreate() I think this is called before the Configuration stuff is ready to be used.
     
  6. Ferran_SP

    Ferran_SP

    Joined:
    Jul 9, 2018
    Posts:
    27
    Hi,
    I was calling this on OnCreate, and I think you're right that Config data is not available at OnCreate. But there was a prior and major issue before this: like robertg_unity says, the Configuration entity is not saved.

    At first I couldn't understand what was going on: I edited the config, closed the editor, and started it again. The data I had just added to the config was right there, but it couldn't retrieve it through code.

    Then I closed the project, and when I opened it again the data I had added to the config was gone.

    So, to sum it up, config data is not saved. Closing the editor will somehow cache the currently open project, so that even if config data is not properly saved, it will indeed be temporarily cached.

    @robertg_unity should I file a bug for this, or you already did?
    Also, could you confirm if it's expected that the Config is not available at OnCreate time?
     
  7. furroy

    furroy

    Joined:
    Feb 24, 2017
    Posts:
    93
    yea we need a different OnXXXX() method to override by the looks of it. OnCreate() is called before the engine is up to speed, which i guess is useful for something, but we need a method that's called after the engine is up and running but before the main loop starts.
     
  8. robertg_unity

    robertg_unity

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    32
    I investigated the issue, and what happens is that the configuration entity is stored in its own scene, while the entity reference that is trying to get resolved comes from a different scene, such as the MainScene for example. We currently do not support having entity references across scenes, and I presume that it will not be any time soon.

    This means, having entity references on the configuration entity is unfortunately a workflow that we do not support. The fact that you can set it up in the inspector is a bug; we need to prevent this pitfall in the first place.
     
  9. Ferran_SP

    Ferran_SP

    Joined:
    Jul 9, 2018
    Posts:
    27
    Thanks for checking this.
    The explanation makes sense, but I don't know how to get around this.

    Does this mean that we shouldn't take as a reference the SpawnAndDestroy sample? (since it uses this workflow)
    What's the recommended way to change scenes, then? How would we implement a game flow that goes from a MainMenu Scene to a GameScen, for instance?
    Before, in Typescript, I would load scenes passing the name of the scenes as a string. I understand that now we can only load scenes passing a scene reference (is this correct?). Where do I get a scene reference from, if cross scene references are not allowed?

    I think there's either something I'm missing, or the change to C# brought some heavy restrictions to scene loading.
     
  10. Rocco_B

    Rocco_B

    Joined:
    Oct 28, 2016
    Posts:
    34
    Here is what I did for scene loading based on feedback from some other users in the main C# thread. I have a component called GameStates that extends IBufferElementData.
    Code (CSharp):
    1. public struct GameStates : IBufferElementData {
    2.     public SceneReference States;
    3. }
    I add this component to the Configuration entity and added my scenes in as Scene References.

    Screen Shot 2019-06-12 at 9.27.00 AM.png


    Then in code I am able to access the them from my GameStateLoadingService class. This is not a system and it does not inherit anything. It's just a static class with a static LoadState(World, GameState) method. I additionally cache the Entity returned from LoadSceneAsync in my GameConfig in case I need a reference to it else where during the game.
    Code (CSharp):
    1. // GameStateTypes is an enum that matches the order of my states in the screenshot above.
    2. private static void LoadState(World pWorld, GameStateTypes pGameStateType) {
    3.     TinyEnvironment env = pWorld.TinyEnvironment();
    4.  
    5.     // Cache SceneReference to the desired scene.
    6.     SceneReference state = env.GetConfigBufferData<GameStates>()
    7.         .Reinterpret<SceneReference>()
    8.         .ToNativeArray(Unity.Collections.Allocator.Temp)[(int)pGameStateType];
    9.  
    10.     // Update the game config data with the current entity for removal for other places if required.
    11.     GameConfig gameConfig = env.GetConfigData<GameConfig>();
    12.     gameConfig.CurrentStateEntity = SceneService.LoadSceneAsync(state);
    13.     env.SetConfigData(gameConfig);
    14. }
    Hope this helps!
     
  11. Ferran_SP

    Ferran_SP

    Joined:
    Jul 9, 2018
    Posts:
    27
    Yeah, this was the approach I was trying to follow, but I can't get it to work because the changes I make to the Configuration entity in the Editor are not saved.
    robertg_unity said the bug is not in that the Configuration entity is not saved, but in that we shouldn't be able to assign Scene References in the Configuration.

    So, while I wait until robertg_unity can hopefully address the questions I made before, could you confirm that you can modify the Configuration, close the DOTS project, open it again, and that you still see in the Configuration the changes you had previously made?
    This is not working for me.

    Side-question: I noticed sometime in the Console Log I get this message, saying that the project file can't be accessed:

    UnauthorizedAccessException: Access to the path "C:\Repos\TinyTest2019CSharp2\Assets\Samples\Project Tiny\0.15.3-preview\Spawn and Destroy\SpawnAndDestroy.project" is denied.
    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) (at <23c160f925be47d7a4fd083a3a62c920>:0)
    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, System.String msgPath, System.Boolean bFromProxy, System.Boolean useLongPath, System.Boolean checkHost) (at <23c160f925be47d7a4fd083a3a62c920>:0)
    (wrapper remoting-invoke-with-check) System.IO.FileStream..ctor(string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,int,System.IO.FileOptions,string,bool,bool,bool)
    System.IO.StreamWriter.CreateFile (System.String path, System.Boolean append, System.Boolean checkHost) (at <23c160f925be47d7a4fd083a3a62c920>:0)
    System.IO.StreamWriter..ctor (System.String path, System.Boolean append, System.Text.Encoding encoding, System.Int32 bufferSize, System.Boolean checkHost) (at <23c160f925be47d7a4fd083a3a62c920>:0)
    System.IO.StreamWriter..ctor (System.String path, System.Boolean append, System.Text.Encoding encoding, System.Int32 bufferSize) (at <23c160f925be47d7a4fd083a3a62c920>:0)
    System.IO.StreamWriter..ctor (System.String path, System.Boolean append, System.Text.Encoding encoding) (at <23c160f925be47d7a4fd083a3a62c920>:0)
    (wrapper remoting-invoke-with-check) System.IO.StreamWriter..ctor(string,bool,System.Text.Encoding)
    System.IO.File.WriteAllText (System.String path, System.String contents, System.Text.Encoding encoding) (at <23c160f925be47d7a4fd083a3a62c920>:0)
    System.IO.File.WriteAllText (System.String path, System.String contents) (at <23c160f925be47d7a4fd083a3a62c920>:0)
    Unity.Editor.Extensions.FileInfoExtensions.WriteAllText (System.IO.FileInfo fileInfo, System.String content) (at Library/PackageCache/com.unity.tiny@0.15.3-preview/Unity.Editor/Unity.Editor.Extensions/FileInfoExtensions.cs:91)
    Unity.Editor.Project.Persist (System.IO.FileInfo file, Unity.Editor.Project project) (at Library/PackageCache/com.unity.tiny@0.15.3-preview/Unity.Editor/Unity.Editor/Project.cs:381)
    Unity.Editor.Project.SaveAs (System.IO.FileInfo projectFile) (at Library/PackageCache/com.unity.tiny@0.15.3-preview/Unity.Editor/Unity.Editor/Project.cs:349)
    Unity.Editor.Project.Save () (at Library/PackageCache/com.unity.tiny@0.15.3-preview/Unity.Editor/Unity.Editor/Project.cs:332)
    Unity.Editor.MenuItems.FileMenuItems.SaveProject () (at Library/PackageCache/com.unity.tiny@0.15.3-preview/Unity.Editor/Unity.Editor.Modes/MenuItems/FileMenuItems.cs:91)
    Unity.Editor.MenuItems.FileMenuItems.SaveProject (UnityEditor.CommandExecuteContext context) (at Library/PackageCache/com.unity.tiny@0.15.3-preview/Unity.Editor/Unity.Editor.Modes/MenuItems/FileMenuItems.cs:26)
    UnityEditor.CommandService.ExecuteCommand (System.String id, UnityEditor.CommandHint hint, System.Object[] args) (at C:/buildslave/unity/build/Editor/Mono/Commands/CommandService.cs:180)
    UnityEditor.CommandService.Execute (System.String id, UnityEditor.CommandHint hint) (at C:/buildslave/unity/build/Editor/Mono/Commands/CommandService.cs:136)
    UnityEditor.ModeService+<LoadMenu>c__AnonStorey1.<>m__1 () (at C:/buildslave/unity/build/Editor/Mono/EditorMode/ModeService.cs:383)
    UnityEditor.EditorApplication:Internal_CallGlobalEventHandler



    Maybe this is the reason why my Configuration is not being saved?
    I've tried setting up a new project from scratch, and I still get the same. And a colleague of mine also has the same issue.
     
  12. robertg_unity

    robertg_unity

    Unity Technologies

    Joined:
    May 4, 2018
    Posts:
    32
    Clarification: using a
    SceneReference
    field in the configuration is allowed, since this is not pointing to an entity. The unsupported case is having a field of type
    Entity
    in a component and assign it to an entity that belongs in a different scene than the entity with that component. In other words, scene references and entity references are two different concepts that does not have the same constraints. Hope this make sense.
     
    Ferran_SP likes this.
  13. Ferran_SP

    Ferran_SP

    Joined:
    Jul 9, 2018
    Posts:
    27
    Ok, so I finally figured everything out.

    The biggest issue I was having is that the folder that contains the samples and my test examples only had (for some reason) read-only access.
    This has happened on fresh installs in both my setups: Windows + Unity 2019.2.0b4, and Mac + Unity 2019.2.0b5 (so I'm thinking maybe there's something weird going on in the install process of the samples?).

    As soon as I fixed this, I was able to properly recreate the pattern that the SpawnAndDestroy sample showcases of having SceneReferences stored in some Component in the Configuration entity.

    Hope this is useful to somebody!

    Cheers!
     
    Rocco_B and Zionisias like this.
  14. Rocco_B

    Rocco_B

    Joined:
    Oct 28, 2016
    Posts:
    34
    Thanks for that clarification. I think it should be much clearer for anyone that comes to this post now. I had a feeling that was the case as I had no issues saving Scene References but did find issues saving Entities before I assumed that cross scene would not be allowed.

    Great to see that you sorted it out and glad I could help!
     
    Ferran_SP likes this.