#Interface Serialization
1 messages · Page 1 of 1 (latest)
not with unity's serialization, no. some custom stuff does though, ive heard odin inspector supports serializing interfaces i think?
is there some sort of workaround?
something that achieves the same thing I'm trying to do
okay that's on me
well, I'm trying to make a script that basically enables a selected visual object
so when the player looks at something that has the interface IInteractable, that object will light up
now, I have 2 objects in my game, an item spawner and a table to put an item on
I want to be able to do the same visual selection logic on the table as I do on the spawner
I'm hesitating to use inheritance in this case because the two objects do wildy different things
do you need to serialize that at all?
well, yes. I need to reference the actual IInteractable to check if that is the instance I'm pointing to
reference ≠ serialize
if (for example) you do a raycast and just do a GetComponent<IInteractable>, you can reference the interface just fine. no serialization in that operation
my system works like this:
player raycasts onto object
object returns script
if the script has the interface, it gets stored in a variable
player sends an event, carrying the interface
visual script checks that and checks if that instance is the same instance it's on
I need to expose it in the editor though for the last step
sends an event for what, to where?
from the player, it sends to the visual script
since I'm trying to separate visual scripts
what is this visual script exactly
using UnityEngine;
public class SelectedVisual : MonoBehaviour {
[SerializeField] private GameObject[] selectedGameObjectVisualsArray;
[SerializeReference] private IInteractable interactable;
private void Start() {
Player.Instance.OnInteractableChanged += Player_OnInteractableChanged;
}
private void Player_OnInteractableChanged(object sender, Player.OnInteractableChangedEventArgs e) {
if(e.interactable == this.interactable) {
Show();
}
else {
Hide();
}
}
private void Show() {
foreach (GameObject go in selectedGameObjectVisualsArray) {
go.SetActive(true);
}
}
private void Hide() {
foreach (GameObject go in selectedGameObjectVisualsArray) {
go.SetActive(false);
}
}
}
and what's this for exactly...?
couldn't you just have this be handled by the interactable
just call a method on the interactable
well, the interactable is doing something else, for example this one:
using UnityEngine;
using System;
[Serializable]
public class BeerKeg : MonoBehaviour, IInteractable {
[SerializeField] private GameObject beerCupObject;
private void Start() {
}
public void Interact() {
if (!Player.Instance.HasBeerCup()) {
BeerCup beerCup = GameObject.Instantiate(beerCupObject).GetComponent<BeerCup>();
beerCup.SetBeerCupParent(Player.Instance);
}
}
}
I'm trying to keep the logic there and then the visual stuff in another script
and trying to minimize duplicated code
the visuals you're referring to are like, highlights, right?
yes
if there's a 1:1 correspondance between Interactables and their visual highlights, why not just have the highlights also be handled by the interactable
not necessarily the component directly, but at least on the same gameobject
so how would I do a check though
https://github.com/mackysoft/Unity-SerializeReferenceExtensions
This would give you some interface serialization but ideally just figure a way to create some abstraction with classes*
I'm not quite sure I follow
Problem with third party serialization is being paranoid your serialization doesnt implode on the off chance
right that's why I'm trying to be vanilla as much as possible
eg
selectedInteractable = null
update:
hit = raycast()
if hit and hit.trygetcomponent(interactible):
if selectedInteractible != interactible:
interactible.Show()
selectedInteractible.Hide()
selectedInteractible = interactible
else:
if selectedInteractible != null:
selectedInteractible.Hide();
selectedInteractible = null
```in those Show/Hide steps, you could retrieve the highlights there, you could have some way to get the highlights via the interactible itself, you could have IInteractible be an abstract class, etc
oh? I don't need to check if it's the instance it's on?
not if you don't go through a detached system, no
if you keep the highlights with the interactible itself, then you know you're getting the right instance
if(e.interactable == this.interactable) {
Show();
}
else {
Hide();
}
cuz this check is to validate if it's talking about itself or it's talking about another instance of that
and you're broadcasting the event to every highlight? that's where the "detached system" aspect comes in
instead of having every highlight worry about every interactible, design around the 1:1 relation
alright so instead of having everything separate, I should make it so that it's connected?
but that would need me to make a visual script for every interactable
right
i mean, if you want each one to have its own highlight, yeah?
isn't that the same as what you had before
you could have interactibles not have highlights too (even in the case of inheritance, you could just have the visuals be an empty array)
well, I only made one visual script that I can attach to every interactible
is inheritance really the only option here? If I want to continue the design I'm doing, that is
you would have a single script that you have multiple instances of
you don't need separate scripts
definitely not, but i feel like it'd fit the task pretty well
composition is always an option
ooh okay I haven't heard of that actually, do you have any resources I can read on that topic?
in unity composition is basically just components on the same gameobject that rely/interact with each other
I seeee
I usually go with the separated systems approach though, it's a lot less messy
when can you say it's better to use composition?
when the 2 things should be coupled together in a way, like here
yeah composition sounds like an idea
instead of an interface just make it a component
what's the difference though
components are classes ;p
but aren't abstracts classes too
components are concrete classes
yeah but abstract classes still fall into the pitfalls of OOP
(though, that wasn't my suggestion)
so like
concrete = non-abstract
i don't follow the analogy
oh I mean those are the two objects that are interactable
so instead of interactable A and interactable B in can be just interactable
okay I was worried about that
so how are components and abstracts different (besides components being concrete)
oh hold on so meaning
i mean.. i don't actually know if unity can't use abstract classes. i don't think so. i should test that.
I can extend the interactable component?
ok i feel like there's some confusion here
Well, your interactable component class would be abstract, but the idea here is instead of having a base abstract class where all classes derive from Interactable it would instead just be an abstract component that your primary entity class includes
my suggestions were one of the following:
- interactible interface, interactible highlight component, some concrete interactible implements interface, composition
- interactible abstract class that includes highlights, some concrete interactible extends abstract class, inheritance
right so interactable itself will be something I can attach to an object..?
if it were abstract, probably not*
-# * gonna test it rq
oh wait so the interface would still exist?
if we're using the composition architecture
i mean, you could change that part to an abstract class too, if you want
public class Enemy: Monobehavior
{
[SerializeField] private Interactable interactable;
}
public abstract class Interactable: Monobehavior
{
public abstract void Interact();
}```
something like that. You don't actually need to include it in the enemy script and can always just do a component search on the game object
i'm just clarifying what my original suggestions were
ah yeah composition inside the component is also an option
I hardly use interfaces anymore with monos
I'm confused
why would I declare an abstract within the script
shouldn't it be separate?
alright, confirmed, abstract classes can't be used as components.
2 scripts here. Unity doesnt like two monos in a single script
well, 2 + each unique derived interactable class
alright I'm starting to understand
though, I'll look into it more
thanks so much guys
then there's the SO idea where if you can somehow make code reusable, a single SO class could work
but if you need unique logic which requires hardcoding then making a class per interactable is fine
I thought SOs were just data containers though
SOs are very customizable and you can use them as blueprints
just my 2¢, but personally the inheritance option here seems the least painful/easiest to use
Unity already serializes interface if you use [SerializeReference]. This and other packages just tell unity how to display it in the inspector.
Thought that's important to point out
Yeah, but even then that's annoying to work with
How so?
I use serializereference extensively with abstract classes, haven't used with interfaces though, but shouldn't be too different
It's just more boilerplate which unity should have already provided for us
I cannot get that to work for some reason
What part doesn't work? Serialization or showing it in the inspector with a package?
So did you add any 3rd party code that would show it?
pure vanila
Unity doesn't have native support for showing [SerializeReference] stuff in the inspector
so pure the only thing I have is cinemachine
Hence the mentioned package(s)
but wouldn't adding the package break things potentially
it's not so much the package. SerializedReferences are just iffy
so i rlly have to change my design huh
It shouldn't modify the serialization itself, it just has property drawers for how to display it
I recall having problems renaming some interfaces and it would just break everything, but it's been a while
may be some attributes to help support that
Yeah renaming types isn't that great with SR
right so I gotta find a workaround
i mean you shouldnt have had that roundabout design with events to begin with tbh
Im late to the chat but I have done this in the past by serialising mono behaviour and using on validate to restrict the value to interface implementors
Does require a cast at runtime to then use but I see no way around that
update, I refactored my code and I'm not quite sure if this is composition but I feel like it is?
because instead of having the look trigger code and the actual visual turning on code in one script,
I decoupled the trigger code, letting it send an event when it's looked at
so at that point, any script that wants to be activated when the player looks at it turns on just needs to listen to it