I just got hit with a compile error I do not understand, and is not directed at any line of code.
First of all, I have structured my game with a fair amount of inheritance to make it work easier.
I have a pawn class that handles things that every character in the game will use, like having health.
I made playerpawn class that extends from that class and handles all the basic player motion and controls (as opposed to an enemy pawn or an npc.)
And on top of that I have classes for specific player classes, like PP_Mage and PP_Ranger that handle the unique particulars of those classes, like how they attack.
So today I was working on some enemies, and I decided that I want to use some of the same movement code that I have been using for the players. So I went into my PlayerPawn class, copied and removed a couple variables, and placed them in the Pawn class, so I could have them in my enemy’s classes.
Then I got this error:
“myXVelocity” is one of the variables I moved from the PlayerPawn class. It is declared as a protected variable so it can be used in the children classes. It it is never referenced or called in any manner from the scripts for the particular player classes.
So, I’m confused. What is this error?
That’s odd, suddenly the error has disappeared. I didn’t even change anything.
I just had this happen today. I had two classes, DetonatorBullet and HomingBullet, which both inherited from the base class Bullet. Both classes declared a member field m_directional. I decided DetonatorBullets should be HomingBullets, so I changed DetonatorBullets to inherit from HomingBullet and removed the DetonatorBullet.m_directional declaration in favor of the inherited HomingBullet.m_directional. As soon as I recompiled scripts, Unity threw this error.
It seems it still had the DetonatorBullet.m_directional value serialized in existing DetonatorBullet prefabs, and now with the new inheritance is also had HomingBullet.m_directional serialized into those same prefabs, which would obviously be screwy. However, I think the error itself is superfluous; I restarted Unity and reimported scripts once more (with no other changes) and the error went away. I think it’s just holding onto some stale serialization data longer than it should.
1 Like
I had the same error today while refactoring some classes and creating interfaces to be used as variables in some places. I got a lot of errors like Serialized Multiple Times and, to be honest, at some time there probably was a duplication of variables in an inheriting class. The errors did not go away though.
Then I realized, it was not a compile error! It is an error thrown by unity at serilization/deserialization. So all you have to do is fix the offending class structure and clear the console. If the error has not been solved, Unity will let you know next time it serializes…
When Unity saves the data shown in the inspector, it can only save the tip. so when a base class has a field that says
public Collider2D targetCollider;
then an inheriting class has something like
new public BoxCollider targetCollider;
unity sees both types and doesn’t know which to serialize to (even though BoxCollider should take precidence)
EDIT: To clarify, its not specifically Unity, its the fact of how Reflection works that Unity uses during serialization/deserialization
regardless whether unity should or shouldn’t handle this more intelligently, the real problem is with the code. It violates Liskov’s Substitution principal. The cleaner way to handling this is that the base class refers to the most abstract version needed and then the inheriting classes attempt to cast at run-time. this should avoid most of your “serialized multiple times” issue
public abstract class BaseClass:MonoBehaviour
{
public Collider target; //all inheriting classes will use SOME type of collider
}
public class BoxClass:BaseClass
{
private void OnTriggerEnter(Collider other)
{
//cast to the actual type we need
BoxCollider box = target as BoxCollider;
if(box == null)
{
Debug.LogError("Collider is not a BoxCollider!");
return;
}
Debug.Log("Using BoxCollider!");
}
}
public class CapsuleClass:BaseClass
{
private void OnTriggerEnter(Collider other)
{
//cast to the actual type we need
CapsuleCollider capsule = target as CapsuleCollider;
if(capsule == null)
{
Debug.LogError("Collider is not a CapsuleCollider!");
return;
}
Debug.Log("Using CapsuleCollider!");
}
}
6 Likes