While it may seem like you DMHeaderList.h has the right ordering, the error seems to be that at the time Spell.h is compiled it doesn’t understand what ADMagicCharacter is.
It is probably because of the circular dependency in your headers. DMHeaderList.h includes Spell.h which includes DMHeaderList.h.
In this case you can forward declare your used of the ADMagicCharacter. Simple add the word “class” in front of your member variable, or better yet put “class ADMagicCharacter” right below your include files and above the class declaration.
Additionally, something to remember, is ALWAYS use UPROPERTY above UObject member variables or you will have garbage collection issues. Your Caster variable will be set to null on the first opportunity to garbage collect and you’ll crash if you access it. Or at least you will get bad behavior.
Spell.h
#pragma once
#include "GameFramework/Actor.h"
#include "Spell.generated.h"
...
// Forward declarations here (as long as its pointer type or const& and you don't need the internal details this will be fine)
// any time you use the implementation of the class, put it in the cpp and include DMagicCharacter.h there
class ADMagicCharacter;
class AProjectile;
UCLASS()
class DMAGIC_API ASpell : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ASpell(const FObjectInitializer& ObjectInitializer);
...
UPROPERTY()
ADMagicCharacter* Caster;
...
UPROPERTY(VisibleAnywhere, Category=Spells)
AProjectile* SpellProjectile;
...
};
DMagicCharacter.h
#pragma once
#include "GameFramework/Character.h"
#include "DMagicCharacter.generated.h"
//try to only include what you use
//DMHeaderList.h is going to get too big and cause you future headache
...
UCLASS(config=Game)
class ADMagicCharacter : public ACharacter
{
GENERATED_BODY()
...
public:
ADMagicCharacter(const FObjectInitializer& ObjectInitializer);
...
};
Thank you, adding class in front of the ADMagicCharacter declaration solved the issue.
Will circular dependency mess with the project? (aside from syntax errors like this. I mean at run time)
Circular dependencies will always result in a compile error of some kind. The issue is that the compiler is looking for the complete definition of something before it can consider it compilable. If it has to go figure out the definition of something else to understand part of the first thing and that second thing is defined in terms of the first, you can’t resolve that.
Here is a link on the concept if you would like more information
It may not be that obvious as that, and in fact just using includes can run the compiler in circles, as was your case.
A.h
#include "B.h"
class A
{
public:
B* MyB;
};
B.h
#include "A.h"
class B
{
public:
A* MyA;
};
As defined, and pardon the bad pseudocode, the compiler could never resolve this because it would just bounce back and forth. One of them has to be resolveable before it can move on.
That kind makes a mess of my variable declarations…
Or are you just saying to add a UPROPERTY to just class declarations like ADMagicCharacter and AProjectile?
It would seem rather messy and disorganized to have to tack that onto every float and int…
I wasn’t commenting on your formatting, either of your statements above are fine. What is important is that any UObject member variables of a class must be marked as UPROPERTY otherwise your memory will be freed up by the engine. UObject memory management is done by garbage collection and it only knows the object is in use if it can follow UPROPERTY variables. There are internal lists of objects and if other objects don’t tell that main list they are using something via UPROPERTY the object will be removed out from under you.
There are lots of powerful things that require UPROPERTY. You don’t have to mark every variable as one, but if you want to replicate over the network, save to disk, edit the value in the editor, debug print variable state, etc you must have them marked.