InvalidCastException: Specified cast is not valid when downcasting

Hi everyone

I’m trying to make a classical rhythm game with notes and long notes to tap in a lane.

for the notes i have a NormalNote and LongNote class, both inherits from an abstract BaseNote.
when i try to initialize each one with their respective timestamps using downcasting i get the error InvalidCastException ONLY for the longnotes, but it works with normalnotes. Any idea why?

function with the error (line 8):

private void LoadNotes(List<NoteData> noteDataList) {

            foreach (NoteData note in noteDataList) {
                var pulledNote = _notesPool.PullFromPool(transform.position, transform.rotation, transform);
                var baseNote = pulledNote.GetComponent<BaseNote>();

                if (note.IsLong) {
                    ((LongNote) baseNote).SetTimestamps(note.TapTime, note.EndTime);
                }
                else {
                    ((NormalNote) baseNote).SetTimestamps(note.TapTime);
                }
               
                _notesList.Add(baseNote);
            }
        }

Extra:
LongNote.cs

using UnityEngine;

namespace Project.Runtime {

    [RequireComponent(typeof(SpriteRenderer), typeof(PoolableGameObject))]
    public sealed class LongNote : BaseNote {

        private SpriteRenderer _spriteRenderer;

        public override float AssignedTapTime { get; set; }
        public float AssignedEndTime { get; set; }

        public override NoteType Type { get {
            return NoteType.LongNote;
        }}

        public override bool IsLong { get {
            return true;
        }}

        private void Awake() {
            _spriteRenderer = GetComponent<SpriteRenderer>();
        }

        public void SetTimestamps(float tapTime, float endTime) {
            AssignedTapTime = tapTime;
            AssignedEndTime = endTime;
        }

    }
}

NormalNote.cs

using UnityEngine;

namespace Project.Runtime {

    [RequireComponent(typeof(SpriteRenderer), typeof(PoolableGameObject))]
    public sealed class NormalNote : BaseNote {

        public override NoteType Type { get {
            return NoteType.NormalNote;
        }}

        public override float AssignedTapTime { get; set; }

        public override bool IsLong { get {
            return false;
        }}

        public void SetTimestamps(float tapTime) {
            AssignedTapTime = tapTime;
        }

    }
}

I don’t know the details of your notepool but it can’t be a mindreader. Nothing in PullFromPool specifies what kind of note are you expecting to get out of it. I assume NormalNote doesn’t fail because that’s what you have filled your object pool with.

If you want to work with multiple object types in object pool, you either need two object pools one for each kind or an implementation of object pool which stores each kind of object in a separate list and PullFromPool method to which you can specify what you want to retrieve.

1 Like

Oh wow, you’re absolutely right. i totally forgot about my object pool, it was filled with normalnotes lol.
Thank you so much! :slight_smile: