0

EF inherits from E
SF inherits from S
S has attribute subE of type E
Runtime obj of type EF calls AddS(S arg) from its ancestor class (E) - passing runtime obj of type (SF)
Assignment attempt is in AddS: arg.subE = this
From attached image you can see that the runtime types match, but the assignment fails.

Key for image: E - Event; EF - EventFrameChange; S - Subscriber; SF - SubscriberFrameChange; AddS() - AddSubscriber; subE - subscribedEvent

enter image description here

Minimal, Complete, and Verifiable example

This code works in Unity. Create an empty GameObject in a scene and add a SpriteAnimatorScript as a component.

using UnityEngine;

public abstract class Event : ScriptableObject
{
    public Subscriber[] subscribers;

    public void AddSubscriber(Subscriber aSub)
    //
    {
        aSub.subscribedEvent = this;
    }
}

using UnityEngine;

public class EventFrameChange : Event
{
    private SpriteAnimatorScript animatorScript;

    public void Initialize()
    // ^ 
    {
        subscribers = new Subscriber[0];
    }

}

using UnityEngine;

public abstract class Subscriber : ScriptableObject
{
    public Event subscribedEvent;
    // ^ Event this is a subscription to.

    public virtual void SetEvent(Event aEvent)
    {
        subscribedEvent = aEvent;
    }

}

using UnityEngine;

public class SubscriberFrameChange : Subscriber
{
    public new EventFrameChange subscribedEvent;
}

using UnityEngine;

public class SpriteAnimatorScript : MonoBehaviour 
{
    public EventFrameChange eventFrameChange;

    public SubscriberFrameChange subscriberFrameChange;

    void Start () 
    {
        SetupEvents();
    }

    private void SetupEvents()
    {
        eventFrameChange = ScriptableObject.CreateInstance<EventFrameChange>();
        subscriberFrameChange = ScriptableObject.CreateInstance<SubscriberFrameChange>();
        eventFrameChange.AddSubscriber(subscriberFrameChange);
    }

}
  • 3
    Please edit your question to include a [mcve] demonstrating the problem. See [ask] and [tour]. – Phil M Feb 09 '19 at 23:39
  • I am not a frequent StackExchange user - I hope my code delivery and instructions are clear and appropriate. – corpsinhere Feb 10 '19 at 17:47
  • Looks like I am basically talking to myself here. Some added info: explicitly casting in Event.AddSubscriber like so: aSub.subscribedEvent = (EventFrameChange)this - causes the assignment to succeed. Though it also breaks the inheritance structure. – corpsinhere Feb 11 '19 at 15:03
  • If I throw the code into just a normal C# Console App (tweaking for the lack of Unity), I see `aSub` has two properties named `subscribedEvent`, because your `new` field just shadows the old one (see [answer](https://stackoverflow.com/questions/326223/overriding-fields-or-properties-in-subclasses)). Although it presents somewhat differently in that environment, might be related. If, in that image, you had expanded `aSub`'s `base`, would it have shown another field with a non-null value? – Phil M Feb 11 '19 at 17:39
  • @PhilM Yes! There is a non-null version when expanding base. Hrm - I suppose I could get rid of the `new` attribute and then do an explicit casting when using the field in a descendant - does that sound reasonable? – corpsinhere Feb 11 '19 at 19:25
  • @PhilM if you want to post that as an answer I will select it and ty. – corpsinhere Feb 12 '19 at 00:25
  • It might make this a duplicate of the answer I linked, but maybe you just need to make the base class Event a property, although the fact you want different types does vary from what that question was asking. – Phil M Feb 12 '19 at 00:34

1 Answers1

0

If I throw the code into just a normal C# Console App (tweaking for the lack of Unity), I see aSub has two properties named subscribedEvent, because your new field just shadows the old one. So the assignment from within the base class method is assigning to the base class copy of the field.

Phil M
  • 1,619
  • 1
  • 8
  • 10