Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ScriptableObjects as Blueprints #373

Closed
VladislavKostin opened this issue Apr 8, 2017 · 15 comments
Closed

ScriptableObjects as Blueprints #373

VladislavKostin opened this issue Apr 8, 2017 · 15 comments

Comments

@VladislavKostin
Copy link

VladislavKostin commented Apr 8, 2017

Why not just generate scriptable objects and use them as blueprints? I slapped together some example of a code that could be generated:

// Everything should be generated.
using UnityEngine;
using Entitas;

// Level is the name of the context.
[CreateAssetMenu(fileName = "LevelBlueprint", menuName = "Entitas/LevelBlueprints", order = 1)]
public class LevelBlueprint : ScriptableObject
{
    [SerializeField] [SomeDrawer] private bool isTile;
    [SerializeField] [SomeDrawer] private bool isPath;
    [SerializeField] [AnotherDrawer] private TilePosition tilePosition;
    [SerializeField] [ThirdDrawer] private Prefab prefab;

    public void Apply(LevelEntity entity)
    {
        entity.isTile = isTile;
        entity.isPath = isPath;
        if (tilePosition.exists)
        {
            entity.AddTilePosition(tilePosition.x, tilePosition.z);
        }
        else if (entity.hasPosition)
        {
            entity.RemovePosition();
        }
        if (prefab.exists)
        {
            entity.AddPrefab(prefab.value);
        }
        else if (entity.hasPrefab)
        {
            entity.RemovePrefab();
        }
    }

    public Entity CreateEntity()
    {
        LevelEntity entity = Contexts.sharedInstance.level.CreateEntity();
        Apply(entity);
        return entity;
    }

    // Generated from components.
    [System.SerializableAttribute]
    private struct TilePosition
    {
        public int x;
        public int z;
        public bool exists; // Added to indicate if it is "null" since it can't actually be null.
    }

    [System.SerializableAttribute]
    private struct Prefab
    {
        public GameObject value;
        public bool exists; // Added to indicate if it is "null" since it can't actually be null.
    }
}

// Original component.
// public sealed class TilePositionComponent : IComponent
// {
//     private int x;
//     private int z;
// }

This one actually works, just put property drawers on top and it seems to be a fully-functioning blueprint with Unity serialization. No problems. Right?..

34t3

@ghost
Copy link

ghost commented Apr 8, 2017

That's a good idea actually, If Blueprints are supposed to be a unity only thing but currently a blueprint is wrapped within a scriptableobject and draw using inspector code. This way you could load a blueprint from file and apply it that way as well.

@VladislavKostin
Copy link
Author

VladislavKostin commented Apr 9, 2017

You mean someone wants to use blueprints in non-Unity apps? If that is the case then current blueprints probably already work for them. In Unity, it is far better to have things serialized by Unity itself.

This approach can work with runtime serialization, this class is perfectly serializable. And if you want non-Unity, this can be wrapped. I need help making this. I have no experience with reflection, so I think code generation will be hard for me. (At least so I thought, now I'm looking into code generator.)

Unless current blueprints can be as reliable and are easier to make work, and unless they also can serialize everything this example can, I think this is a good way to go. This one potentially supports even refactoring with [FormerlySerializedAs] which Entitas could utilize.

@VladislavKostin
Copy link
Author

VladislavKostin commented Apr 9, 2017

Actually, game state saving and blueprint integrated system seem pretty simple.

  • Generate serializable versions of all components.
  • Generate a class like a blueprint in the initial post but not Unity-specific, use it as C# blueprint.
  • Wrap it into or generate ScriptableObject version just like in the example above, for Unity blueprint.
  • Blueprints should be able to be serialized into files.
  • Have a method that will serialize given list or a group of entities into files using those blueprints.

This would make a very easy to use runtime serializer out of the blueprint system.

  • Optionally, have a [SerializeComponent] or [DoNotSerializeComponent] attributes to mark components that you want to be serialized during runtime. But serialize all for the blueprints. In generated serializable components have a bool _serializeAtRuntime.

@IsaiahKelly
Copy link

IsaiahKelly commented Apr 9, 2017

I'm sure it has something to do with "portability" here, but I've been studying Blueprints lately and thought about doing something like this myself since I noticed Blueprints don't currently support Unity undo operations and switching context erases all blueprint components!

This is really ridiculous and annoying, but I believe replacing the binary formatter should fix all that and I hope to help in this area eventually, but I still don't know enough about the system yet to contribute anything. I have however at least been able to fix some aspects of the blueprint inspector already.

@VladislavKostin
Copy link
Author

I think it can be portable by breaking down in 2-3 files and just using a ScriptableObject as a wrapper, but it might be easier to just generate Unity version separately. Internally they both would implement the same interface, so it is just a matter of one code generator addon for Unity. Blueprints are already pretty unity-specific at least partially.

@sschmid
Copy link
Owner

sschmid commented Apr 27, 2017

Fyi, due to #390 I cannot work on blueprint related issues. Blueprints can become a community supported feature.

@VladislavKostin
Copy link
Author

I think I have read in the chat that someone was implementing something like this. Whoever it was, please respond here if you have some progress or have it working already 😄

@pixeption
Copy link

@VladislavKostin Not sure but is it me or someone else?

@VladislavKostin
Copy link
Author

VladislavKostin commented May 6, 2017

@pixeption Idk, possibly. Were you working on this? How is it going?

@VladislavKostin
Copy link
Author

This would make a good Entitas Plus feature :)

@VladislavKostin
Copy link
Author

It's not going anywhere for now. Should I close it? 😄

@Arpple
Copy link

Arpple commented May 15, 2017

I still want this to happen because I now use scriptableobject as blueprint by manually create it.
so it will be awesome if I can generate it instead.
I really want to help on this if I can :D

@pixeption
Copy link

@VladislavKostin sorry for late response

Actually I worked on something different, I don't want blueprint as scriptable object, I want to attach entitas components into GameObject (For example many game level require design on Editor for productivity).

At the end I gave up (although it can run) since it is contained many cheat code & limited when using Unity serialization.

Writing code to generate scriptable object as blueprint is not hard, you can check how blueprint generate in source code and do the same thing. (actually I learn a lot of reflection and code generation via entitas)

@VladislavKostin
Copy link
Author

VladislavKostin commented May 17, 2017

@pixeption Isn't it almost the same code though? Mine and what you tried to achieve? Just change : ScriptableObject to : MonoBehaviour and you can use it on game objects. And it is easy to implement yes. Problem is that for me it won't save any time doing so, but when someone will do this it will save time to a lot of people and improve workflow in the editor. Wink-wink nod-nod to @sschmid again :) It would be a great Plus/Pro/Delux feature.

@pixeption
Copy link

pixeption commented May 17, 2017

@VladislavKostin It's actually difference.
Blueprint is like a template and can't change (if we change, we change all object), prefab does. I want to add entitas component just like monobehaviour did and with each different object, the number of components and values are difference.

I succeed at serialize entitas component using Unity Serialization via many tricks.
I save all component info into a scriptable object with object instance ID, component lookup id (i failed here, component lookup id can change and no other ways to add component to entity without lookup id)

Here is a demo but i don't think this is a good approach, maybe I'll think about another approach
screen shot 2017-05-18 at 12 09 51 am

@sschmid sschmid closed this as completed Nov 7, 2017
@ghost ghost removed the help wanted label Nov 7, 2017
@sschmid sschmid added this to Entitas Jul 2, 2023
@github-project-automation github-project-automation bot moved this to Todo in Entitas Jul 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

No branches or pull requests

5 participants