[C++] Implementing a class for the Weapons [CRASH]

Hello guys.

I’m going to implement a Base Class for the Weapons in my game in order to define all the shared characteristics between them (Damage, WeaponName, FireRate…)

I made this one:

And in the FirstPersonCharacter.h I declare a CurrentWeapon (which indicates the active weapon, the one the player is currently holding) amd a TArray of Weapons in order to make an **Inventory of Weapons **that the Player picks up

As you saw in the Weapon.h, the Constructor takes some arguments and then assigns them to the “internal” variables.

So I want the FirstPersonCharacter to have, when he spawns the first time, kind of “Default Weapon”.

So in his constructor i write:

When I compile, the Unreal Engine crashes

I think it has problems when I call the Constructor of the AWeapon class.

In “pure” C++ that’s absolutely lawful, but I don’t understand which is Unreal Engine’s problem…

You should not create unreal classes with “new”. Use SpawnActor/NewObject/etc.

You also cannot transfer any parameters through constructor.
See this discussion: 4.7 How do I actually pass parameter's in the new constructor format? - C++ - Epic Developer Community Forums
That’s because Constructor expects FObjectInitializer.

Also, you should really use UPROPERTY in your classes, otherwise people won’t be able to edit them through editor.

Unreal engine is not pure C++. The engine has garbage collection, for example, and there’s the whole UPROPERTY mechanism.
Check first person tutorial C++: A new, community-hosted Unreal Engine Wiki - Announcements - Epic Developer Community Forums
Forget about passing stuff through constructor. Create an “init” method or something.

Frankly, I’d consider splitting weapon into two parts - UDataAsset-derived weapon information - that stores its characteristics, and probably something derived from USceneComponent that handles actual weapon model and shooting. Making weapon an AActor-derived class smells like Unity’s approach, I’m not sure if doing that in UE4 is a good idea (you could make it work though. See: Attach Actor to another Actor based on Socket points - Blueprint - Epic Developer Community Forums) .


I advise to walk through first person shooter C++ tutorial. That should clear some things up.

Thanks for the answer.

I just need a mechnanism like this:

Weapon Class (describes characteristics for any derived-weapon: Fire Rate, DamagePerShot…) <- it’s NOT something that can be phisically placed into the World, it’s just a pattern

Then we have derived classes from it, like:

-Pistol (FireRate = 0.7seconds, DamagePerShot = 15)
-Minigun (FireRate = 0.1 seconds, DamagePerShot = 30)

And so on…

For now I’m leaving away all the stuff regarding animations, models… I’m just building the logic of the game, the weapons, when a player is hit, when he’s dead and thing like this.

So?

There’s a few things running through my mind that aren’t fully answered by what you’re posting. For starters though I would:

  1. Set the Visual Studio project solution to “DebugGame Editor”
  2. Consider instantiating the weapon during BeginPlay() in the FirstPersonCharacter code.
  3. Use CurrentWeapon = GetWorld()->SpawnActor<AWeapon>(WeaponClass, SpawnLoc, SpawnRot, SpawnParams);

Given that Weapon is derived from AActor I don’t thinks is appropriate to use NewObject<>(), well, at least I don’t think I’ve done so. I use new objects for a lot of UUserWidget derived classes, and some other classes that I’ve created and based off of UObject.

There’s a possibility that the FirstPersonCharacter constructor is called more than once. I don’t know that to be true in your case, but I’ve seen some of my constructors called more than once. Is the FirstPersonCharacter in your active scene?

  1. I’d put a break point at the BeginPlay() CurrentWeapon is performed at to see what happens.

Typically I close the UE4 Editor, set up for a debug build, set my break point(s), then press F5. What’s nice is that if the error is occurring due to something else the debugger will help you find it.

Actor is pretty much a base class for something that physically exists in the world.
You could try to derive from component, which are used to describe some “portion” of the actor (not necessarily physical), or you could describe you weapons as data.

From your explanation it really sounds like you just want some structs to hold weapon configuration (fire rate, fire power, etc). UDataAsset is a good class for that.

Yeah but if I make my Weapon class derive from UDataAsset, then all my weapn will derive from that, right?

I want the weapons derived classes to be actors though

UDataAsset is a data that can be edited in content browser. Data block, literally. You can make a class that stores weapon settings, and reference it via “UPROPERTY() UMyWeaponDataAsset *weaponConfig = nullptr;” member. Then make actual actor/component that will reference that datablock.

Do you have a reason to do it this way? Inheritance is not the only way, there’s also composition.

You should look at ShooterGame. That’s an example of how to set up a good, flexible weapon system. Unreal Tournaments is similar also, but there’s more code per-weapon since it’s weapons are so diverse in what they do.

The idea is to create an overarching weapon class in code which handles all the behavior of any weapon - such as it’s model, animations, it’s ammo/damage values, spawning projectiles / doing line traces, replication and networking, inventory, spawning muzzle FX etc. You then create Blueprints of that class and change the default values so it behaves differently. That’s the ideal workflow, and inheritance is what UE and Blueprint is designed around. There’s no point fighting the tools for no good reason.

If you’re going to have models and animations, then why wouldn’t you want it to be an actor spawned into the world? That’s exactly what you’ll need. It’s all very well putting together a framework but if you can’t use that framework later than it’s a waste of time, and you may as well be prototyping in Blueprint since you’ll also learn the API while doing so as well.

If all you’re doing is changing a few properties like ‘Fire Rate’ or ‘Particle Template’ or ‘Mesh’, then a Blueprint of it is just a data asset anyway.

I don’t want to spawn a Weapon because Weapon is just a generic class that holds informations for the future weapons i’ll implement in the game!

It’s like saying… why don’t you spawn an Animal to the world? HOW?

Animal is GENERIC, I’ll use Animal class to be the base class and hold information of other derived classes** AND THOSE DERIVED CLASSES** will be spawned!

But also, If i’m building a game where a man has to collect as many animals as possible, then I wouldn’t create an ARRAY OF PIGS! I’d create an array of… ANIMALS!

That’s [COLOR=“#FF0000”]POLYMORPHISM![/COLOR]

I don’t know which Animal will be put into the array, so I just say I’m sure that there’ll be put a derived class from Animal.

So do you understand my problem now?

You’re overthinking it.

In the game engine it often works differently.

A pig can be of the same type as a “town guard”.

The differences between those is that pig has different mesh, different set of animations and different set of sound effects.
Depending on the game engine, they can even use the same class. In that case “behavior”, “animation set”, “mesh” and “set of sound effects” are properties of instance of that class. (Also google “inheritance vs composition”)

Don’t use polymorphism for the sake of using polymorphism.

In case of programming, in general, when you’re about to do something (“I want to implement X!”) it is a good idea to stop and ask yourself what you would GAIN from doing that? (“What benefit would I gain from implementing X?”). If you can’t answer that question, then that thing you were planning to do might not be a good idea.

Ok so I thing you understood what I’m looking for.

With that said, I need Weapon class that just holds informations (will not spawn) and all derived (minigun,pistol,laser,sniper) that will spawn (and so are actors, right?)

How to achieve this?

Data class:
Derive from UDataAsset, like you would derive any other UClass.



UCLASS()
class MYPROJECT_API UWeaponConfig : public UDataAsset{
	GENERATED_BODY()
public:
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	FText displayName;

	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	float fireRate = 0.25f;

	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	float damage = 10.0f;

....
};


Create data asset through content browser (rightclick->misc->new data asset), select your base class, then you’ll be able to fill in values.

Object class: There’s more than one way to do it. Either create a “combatant” class that represent a single person-with-weapon, references data class with weapon stats OR create actor for weapon (makes sense if it, say, can turn into stationary turret), OR a custom component that represents the weapon. Whichever you prefer. You can handle actual shooting in either of those.

I can’t find the UDataAsset base class

You need to Type “DataAsset”. When selecting classes in calss editor, you omit first letter (U or A). So when you derive from AActor, you type “Actor”, and when you derive from UDataAsset, you type DataAsset, etc.

Also, you could manually create files without class wizard, if you wanted.

I created the UWeapon C++ class and the DataAsset from Miscellaneous:

It’s empty… now what do I do? And also, why should I create a DataAsset from Miscellaneous?

You need to populate class with UPROPERTIES. Any variable that must be visible in editor, must have UPROPERTY macro before it, like this:



UPROPERTY(EditAnywhere, BlueprintReadOnly)
	FText displayName;

	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	float fireRate = 0.25f;


If you don’t specify UPROPERTY or if you don’t specify EditAnywhere (and BlueprintReadOnly IIRC), it won’t be visible in editor.

I think there is tutorial on uproperties somewhere, but I forgot where I learned that stuff. Check the wiki, rama’s tutorials, and C++ first person shooter tutorial. It was explained somewhere.

Also, make sure that you created your data asset using your DataAsset-derived class.
So, you first create C++ class based on DataAsset (say, it is called UMyWeaponData), then you create data asset using that menu, and in that menu you have to select the calss you created.

Well, because menu exists there for some historical reason?
DataAsset (and data asset based classes) act like configuration file or data block.

Doing things this way would allow you to have weapon configuration that can be referenced from actual actor/object/etc. If you’d got this route you’ll have one DataAsset-based class (for example UMyWeaponConfig) sitting in your content browser, and weapons in level would reference it.

See this article for more info on UDataAssets:

Ok thanks, I created the DataAsset. Now it wants the values I defined in the UWeapon C++ base class.

This leads me to think that I should now create as many DataAssets as the number of weapons. One for each. Right?

Yes, but I recommend that you reread what TheJamsh wrote. I’d suggest that you work out the details of one weapon with mesh, texture, sound, animation, etc. and see how that all works together in UE4. See how it is put together, then spawn it, and control it, then go back and add a second one. You may find yourself fine tuning what information you’re keeping. Of course design with generality in mind, not hardcoding things if you can keep away from it. You may want an enum though for weapon type, or some other mechanism to tell them apart when needed. Obviously derived classes will add needed functionality but you can start with a base weapon, work out what you need, then move parts out that may not fit the class of weapons you’re developing for to an appropriate derived class.

Frankly no, I don’t.

The sensible approach is: You create an overarching actor class of type ‘Animal’ - and then all of you’re pigs, sheep and cows would derive from that. You don’t spawn ‘Animal’ (hell, you can even force that specific class to NOT be spawnable) - you spawn ‘BP_Cow’ or ‘BP_Pig’. Cows might have extra functions like producing milk, so you add that functionality to the derived ‘Cow’ class. Hell, let’s say you want your goats to produce milk too. Then you create a ‘Makes Milk’ interface and both the Goat and the Cow implement that Interface (or better yet - use an actor component instead of an interface).

This is absolutely no different to creating a ‘Weapon’ class, then having your pistol, rifle and shotgun inherit from it. Now whose to say you can’t have your ‘Rifle’ class support a Data Table, and the Rifle reads it’s ‘Fire Rate’ and ‘Damage’ from a data table based on it’s name, such as M4A1 or MP5 for example. I don’t see the point in doing that however, since you’ll have to create Blueprints of each one with different visual elements anyway, so you may as well set the weapon properties there (although, the data table method is good for quick adjustments to properties).

Don’t even know why I’m explaining this… ShooterGame is setup the way it is for a reason and you may as well use it for reference since half the works done for you - there’s no point reinventing the wheel. The Engine is not designed around Polymorphism, it’s built around inheritance. If you’re just going to fight the tools without first learning that, then:

youre-going-to-have-a-bad-time.png

Hello. I’m following your golden tip. I didn’t even know of its existence.

Anyway, I started studying that project but there are things that I don’t understand.

For example, look at this:

There’s a function declaration on the left (ServerStartFire), but in the .cpp file I see ServerStartFire_Validate and ServerStartFire_Implementation.

Since we just delcared one function, I wonder why are we implementing two “new” functions called in a different way?
What’s the relationship between them?

Thanks!