Search Unity

Feedback Feature Request: Allow prefabs to reference objects in scene

Discussion in 'Prefabs' started by GrayLightGames, May 24, 2020.

  1. GrayLightGames

    GrayLightGames

    Joined:
    Jan 14, 2015
    Posts:
    30
    It would really help me in all of my projects if I could reference scene objects in the prefabs I am creating. I understand that prefabs are often shared between scenes, but I only use one scene in my projects so that doesn't help me. If I could make a main prefab and then have variants that are attached to specific scenes with access to that scene's objects, that would provide best of both worlds.

    For a use case example, I have a Close Overlay Button prefab that has two OnClick() functions: one calls a PlaySound function on my AudioController and the other closes the active overlay by calling a function on an OverlayController. I would like to configure these two functions in the prefab itself.

    I understand I can work around this limitation... usually I just duplicate a button in the scene instead of instantiating a fresh one. This means that I can't modify those configurations in one place and I have to search and select the instances to modify. I could create a script with an OnClick function and not use the OnClick of the UI Button. This means an extra script for each type of button I want to make.

    This is just one example... for my situation, the main benefit of a prefab is being able to manage a large number of similar objects in my scene from one place. This limitation gets in the way of that in many cases.

    If anyone else would find this useful, please reply as well. If there is a better place to post this, I'd love to know.

    Thanks for your time!
     
  2. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,332
    It would be useful, but there are three major issues:

    - What does it mean to load a prefab with scene references outside of that scene? I assume it would mean "let the field be null", but that could end up being confusing. Should it perhaps show an error?
    - UI: How do you show it when you're looking at the prefab in prefab mode? I assume that the field would have to say "targeting scene object" and then not show the object (as you'd otherwise have to load the scene, which would be slow)
    - Serialization: This would require the serialization format to be updated. When deserializing a prefab, Unity now knows that the things it references are either a part of the prefab, or another asset. You'd have to have a different syntax for targeting scene objects, and preferably not do it in a way that increased the size of the serialized data.


    There's a lot of potential unknowns here, and it's not a very important feature, but it would be nice to have for prefabs that are only used in a single scene, but repeated a bunch in that scene.
     
  3. DigitalSalmon

    DigitalSalmon

    Joined:
    Jul 29, 2013
    Posts:
    100
    I don't think this is a great idea, for the reasons listed above.

    That being said, it can certainly be useful to have scene references on components - In which case, write yourself a property drawer that displays an object field, but have the backing type be your own reference type. You could then decide how you wanted to serialize behind the scenes. You could have some unique ID/marker component, or serialize by scene hierarchy path, or have the reference stored in some "Scene Objects" component which allows you to look up a scene component given some search criteria.
     
  4. GrayLightGames

    GrayLightGames

    Joined:
    Jan 14, 2015
    Posts:
    30
    Thanks much for your input @Baste! You bring a lot of important points, it may be a nice to have where the overhead to make it possible is heavier than the benefit. I have just seen a number of posts and questions where people have strange errors because they don't understand that a prefab can't link to a scene object. It took me some time to figure that out as well. I have worked with other development environments that don't have this limitation where reusable components function more like simple copies of existing objects. But I can definitely understand if the prefab system wasn't designed with this functionality in mind. Here's some responses anyway:

    Issue 1: Simplest solution: it doesn't allow you to load the prefab in another scene... it could prompt you to create another variant for that scene. Or it could null the fields and popup a warning message.

    Issue 2: My thinking is that the prefab view of the object should be identical to what you see in the hierarchy and the inspector in the scene. I'm not sure what you mean about showing the object... in the inspector, it just shows the name of the linked reference object. It could add the scene name in parentheses or something. If you mean clicking on the reference to navigate to the linked object, this could just do nothing in prefab view or return to the scene object just like if you clicked on it in the scene inspector. Loading up my scene in the editor doesn't take long, so if that's a limiting factor it will be up to the dev how often they switch back and forth. Maybe that's only something you would do on an instance of the prefab already in scene view.

    Issue 3: I'm not as familiar with serialization as it relates to prefabs... from a quick read of some googled info, it sounds like prefabs are serialized and processed completely differently than scene objects. Maybe there's a good reason to structure it that way (performance?) , but if prefabs have some complicated architecture behind them, maybe it's reasonably doable to give me a new reusable structure that just straight up copies an object from scene view to my asset structure, and then calls the existing Duplicate functionality when instantiating. All that's left is to maintain linkage between the reusable asset and instances, push changes and manage overrides. It just seems like I can almost achieve what I want using existing editor functionality manually, so making that part of the platform shouldn't require too much reengineering. Again, I understand if cost-benefit is a problem.

    After talking this out, I may take a crack at doing this myself if the Unity folks don't think it's worthwhile... am thinking I can have a reusable object controller in my scene with a dictionary of inactive objects and I just Instantiate things out of there. This would also mean I can key it however I want, even just by a string, and I don't need to reference prefab objects in all my other scripts if I have a reference to the controller. Pushing object changes and managing overrides will be the main challenge I suppose. Just a question of how much time do I want to spend not making games and monkeying around with Unity functionality.
     
  5. GrayLightGames

    GrayLightGames

    Joined:
    Jan 14, 2015
    Posts:
    30
    Thanks @DigitalSalmon, sounds like an intelligent approach... if I knew more about editor scripting and Unity serialization this would probably be a nice and quick solution. I'm not as interested yet in spending my game dev time learning how to enhance the editor, but I'll definitely look into how to do what you're recommending if the Unity folks don't think this is useful functionality.
     
  6. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,332
    The name of the object is stored in the scene file... somewhere. So in order to show the name of an object in a scene, you have to load that scene. Objects are not stored by name in general, but with some kind of ID - for objects in scenes that's the object's fileID.
    An alternative would be to store the name where you store the reference, but that's bad for filesize reasons.


    You can for sure take a crack at this yourself. It's for sure doable to link stuff in a scene - the Timeline system does just that as the timeline assets are assets, and the things they link are in the scene. The way they do it is that the playable direction component in the scene has a string-to-object dictionary, which is injected into the timeline asset when it's played. You can do something similar, or use something like Unity's cross scene reference tool from here.
     
  7. GrayLightGames

    GrayLightGames

    Joined:
    Jan 14, 2015
    Posts:
    30
    For better context, I'm creating relatively simple 2D games on mobile... so opening my single scene is pretty much instantaneous.

    If you dedicate a prefab to a scene like I'm trying to request, wouldn't you have that scene open anyway while modifying that prefab? Maybe I'm pigeon-holed into my type of projects, but with a single scene project like mine, I'm either working in my main scene or another scene I made for the level editor.

    If the scene is already open, would it be difficult to display the scene hierarchy while in prefab view? All you'd need available would be object names and hierarchy in the editor, and internally the object types and the ID's associated. Similar to how you can inspect a prefab while in scene view before you open prefab view.

    Thanks for the advice about the Timeline asset, and I'll check out the cross scene reference tool if I do try this myself...
     
  8. DigitalSalmon

    DigitalSalmon

    Joined:
    Jul 29, 2013
    Posts:
    100
    Nest this prefab in a "Scene" prefab, then be careful about which level you make modifications at? That way anything in your broad prefab can be referenced/assigned at that level. Or make it not a prefab at all?