Overview
Purpose: This example demonstrates how to extend VR-Forces' projectile system by creating custom projectile types with additional runtime state. It shows the pattern for inheriting from DtProjectile, adding custom per-projectile properties, and integrating with the projectile factory.
Observable Behavior: When running this example, you will see:
- Custom projectile type available in VR-Forces simulation
- Projectiles created with additional time-in-flight state that accumulates while in flight
- Projectiles function identically to standard projectiles with added time-in-flight tracking
Prerequisites:
- Understanding of VR-Forces simulation architecture
- Familiarity with C++ inheritance and virtual functions
- Basic understanding of projectile ballistics
Related Examples:
- VR-Forces projectile documentation
Key Concepts Demonstrated
This example demonstrates:
- VR-Forces Projectile Extension - Inheriting from
DtProjectile to add custom behavior
- Adds additional per-projectile runtime state
- Unique aspect: Shows complete pattern for extending simulation objects
- Factory Pattern Integration - Registering custom types with VR-Forces factory system
- Type identifier enables deserialization of custom projectiles
- Factory creates correct subclass when loading from file
- Simulation Object Lifecycle - Proper update logic and state management
- Override
update() to maintain custom state during simulation
- Base class methods handle standard ballistics and physics
Code Walkthrough
Custom Projectile Class Definition
The custom projectile adds a time-in-flight parameter to track how long the projectile has been airborne:
{
public:
DtCustomProjectile(
const DtString& name, DtReaderWriterRegistry*
const parentRegistry =
nullptr);
virtual DtString
type()
const;
protected:
};
Custom projectile class with additional time-in-flight tracking.
Definition customProjectile.h:54
double myTimeInFlight
Custom time-in-flight parameter.
Definition customProjectile.h:191
virtual DtString type() const override
Return the class type identifier string.
virtual makVre::DtProjectile * clone() const override
Create a deep copy of this projectile.
DtCustomProjectile()
Default constructor - not implemented (projectiles require names)
virtual makVre::DtProjectileDetonationResult update(double deltaTime) override
Update projectile state for one simulation frame.
static makVre::DtProjectile * creator(const DtString &name, DtReaderWriterRegistry *const parentRegistry=nullptr)
Static factory creator method.
Class representing the result of a projectile detonation.
Definition projectileDetonationResult.h:33
Class representing ballistic projectiles in simulations.
Definition projectile.h:42
Key Points:
- Inherits from
DtProjectile to use existing ballistics
DtRwReal wrapper provides automatic serialization
- Static
creator() method required for factory instantiation
type() returns unique identifier for this projectile class
Constructor and Registry Integration
The constructor initializes the base class and sets the initial time-in-flight state:
: DtProjectile(name, parentRegistry)
, myTimeInFlight(0.0)
{
}
: DtProjectile(orig, parentRegistry)
, myTimeInFlight(orig.myTimeInFlight)
{
}
- Time-in-flight starts at zero for new projectiles
- Time-in-flight is internal runtime state, not configurable from data files
- Copy constructor preserves accumulated time-in-flight when cloning projectiles
- Initialization happens before simulation starts
Update Logic for Custom Behavior
The update method is called each simulation frame to maintain custom state:
{
return DtProjectile::update(deltaTime);
}
- Called once per simulation frame with time delta
- Custom logic executes before base class ballistics
- Base class handles trajectory, collision, detonation logic
- Return value indicates if projectile should be destroyed
Factory Registration
The plugin registers the custom projectile type during VR-Forces initialization:
DT_VRF_DLL_PLUGIN bool DtPostInitializeVrfPlugin(DtCgf* cgf)
{
return true;
}
virtual void addCreatorFcn(const std::string &type, DtProjectileCreatorFcn fcn)
Registers a projectile creation function with the factory.
static DtProjectileFactory * factory()
The factory for creating objects of type DtProjectile. The factory is used to generate projectiles on...
constexpr char DtCustomProjectileType[]
Type identifier string for custom projectile class Used by factory system to create instances and for...
Definition customProjectile.h:25
- Factory uses type string to instantiate correct subclass
- Required for loading custom projectiles from saved scenarios
- Called during VR-Forces post-initialization phase
- Type string must match value returned by
type() method
Static Creator Method
The factory calls this method to instantiate custom projectiles:
Key Points:
- Static method enables factory to create instances without existing object
- Signature matches factory's creator function pointer type
- Returns base class pointer for polymorphic use
Deployment and Testing
Installation
Build the example (see Environment Setup & Build Guide):
cd examples\build
cmake --build . --config RelWithDebInfo --target customProjectile
Install the plugin to the VR-Engage installation:
cmake --install . --config RelWithDebInfo
This copies the plugin to <VR-Engage-Install-Dir>\plugins64\vrForces\release\exampleCustomProjectile.dll
Verify installation:
dir "<VR-Engage-Install-Dir>\plugins64\vrForces\release\exampleCustomProjectile.dll"
Configuration
Backend plugin loads automatically: The VR-Engage toolkit installer automatically installs the backend plugin configuration file appData/plugins/exampleCustomProjectile.xml which tells VR-Forces to load the DLL. No manual plugin configuration is required.
Use custom projectile in weapon definitions (in .mtl files):
munition "CustomRound"
{
projectile "DtCustomProjectile"
{
// Standard projectile parameters
mass 10.0
caliber 0.155
velocity 800.0
}
}
For details on munition configuration, see VR-Forces documentation.
Testing Procedure
- Launch VR-Forces with the custom projectile plugin loaded
- Create entity with weapon using the custom munition type
- Fire weapon during simulation
- Expected Behavior:
- Projectile created using
DtCustomProjectile class
- Time-in-flight parameter increments each frame
- Projectile ballistics and detonation function normally
- Custom parameter persists if scenario saved/loaded
Verification:
- Check VR-Forces log (
logs\*.log) for plugin initialization: [Plugin] Loaded exampleCustomProjectile
[Projectile Factory] Registered DtCustomProjectile
- Enable debug logging to see projectile creation:
[Projectile] Created DtCustomProjectile instance
- Use VR-Forces debugger to inspect projectile properties during flight
Troubleshooting
Plugin not loading:
- Verify DLL is in
<VR-Engage-Install-Dir>\plugins64\vrForces\release\
- Check plugin package configuration includes correct path
- Review VR-Forces log for load errors or missing dependencies
Custom projectile not created:
- Symptom: Standard
DtProjectile created instead of DtCustomProjectile
- Cause: Type string mismatch or factory not registered
- Solution: Verify
DtCustomProjectileType matches type used in .mtl file
Simulation crash during projectile flight:
- Symptom: Crash when custom projectile updates or detonates
- Cause: Missing base class method call or invalid state
- Solution: Verify
update() calls DtProjectile::update() and returns result
Technical Reference
File Structure
examples/customProjectile/
├── CMakeLists.txt # Build configuration
├── README.md # This documentation
├── plugin.cxx # VR-Forces plugin entry point
├── customProjectile.h # Custom projectile class declaration
└── customProjectile.cxx # Custom projectile implementation
Key Classes
API Methods Used
DtProjectile::DtProjectile() - Base class constructor
DtProjectile::update() - Frame update with ballistics and collision
DtProjectile::factory() - Access to projectile factory singleton
DtProjectileFactory::addCreatorFcn() - Register custom projectile type
Reader-Writer Registry Types
VR-Forces provides several parameter wrapper types:
| Type | Purpose | Example |
DtRwReal | Single floating-point value | myMass |
DtRwInt | Integer value | myFragmentCount |
DtRwString | Text string | myMunitionName |
DtRwBool | Boolean flag | myHasGuidance |
DtRwVector3 | 3D vector | myVelocity, myAcceleration |
DtRwEnum | Enumerated value | myFuseType |
Projectile Update Return Values
| Value | Meaning |
DT_PROJECTILE_CONTINUE | Projectile continues flight |
DT_PROJECTILE_DETONATE | Projectile detonates (impact, fuse) |
DT_PROJECTILE_DUD | Projectile becomes inactive (fuse failure) |
DT_PROJECTILE_DESTROY | Projectile should be removed (left simulation area) |
Build Targets
- Plugin:
exampleCustomProjectile.dll (Windows)
- Install Location:
plugins64/vrForces/release/
Related Documentation: