355 lines
8.6 KiB
Markdown
355 lines
8.6 KiB
Markdown
# BladeSmith Agent Development Guide
|
|
|
|
## Project Overview
|
|
|
|
BladeSmith is a UE5.6 C++ blacksmith simulation game featuring physics-based metal forging with GPU-accelerated compute shaders and dynamic mesh deformation.
|
|
|
|
**Core Technologies:**
|
|
- Unreal Engine 5.6
|
|
- Geometry Scripting API
|
|
- Custom Compute Shaders (MiceShaders plugin)
|
|
- Dynamic Mesh System
|
|
- Enhanced Input
|
|
- Voxel-based physics simulation
|
|
|
|
---
|
|
|
|
## Build Commands
|
|
|
|
### Building the Project
|
|
```bash
|
|
# Build game target (run from UE5 engine directory)
|
|
"C:\Program Files\Epic Games\UE_5.6\Engine\Build\BatchFiles\Build.bat" BladeSmith Win64 Development "E:\MiceCola\work\BladeSmith\BladeSmith.uproject"
|
|
|
|
# Build editor target
|
|
"C:\Program Files\Epic Games\UE_5.6\Engine\Build\BatchFiles\Build.bat" BladeSmithEditor Win64 Development "E:\MiceCola\work\BladeSmith\BladeSmith.uproject"
|
|
|
|
# Alternative: Open BladeSmith.sln in Visual Studio
|
|
```
|
|
|
|
### Running Tests
|
|
UE5 uses the Automation System, not traditional test runners:
|
|
- **Editor**: Window → Developer Tools → Automation Sessions
|
|
- **Command line**: `UE5Editor.exe BladeSmith.uproject -ExecCmds="Automation RunTests"`
|
|
- **Single test**: Run specific test class from Automation Sessions panel
|
|
|
|
### Development Workflow
|
|
1. Open `BladeSmith.uproject` in UE5.6 editor
|
|
2. Use hot reload for C++ changes (Ctrl+F11 in editor)
|
|
3. Test via "Play In Editor" (Alt+P)
|
|
4. Use Visual Studio for compilation
|
|
|
|
---
|
|
|
|
## Code Style Guidelines
|
|
|
|
### File Structure
|
|
- **Header files (.h)**: Class declarations, forward declarations, USTRUCT/UCLASS definitions
|
|
- **Source files (.cpp)**: Implementations, includes in dependency order
|
|
- **Shader files (.usf)**: HLSL compute shaders in `Plugins/MiceShaders/Shaders/Private/`
|
|
|
|
### Import Ordering
|
|
|
|
**Header Files:**
|
|
```cpp
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "GameFramework/Actor.h"
|
|
#include "ProjectModule.generated.h"
|
|
|
|
class UForwardDeclaredClass; // Forward declarations
|
|
```
|
|
|
|
**Source Files:**
|
|
```cpp
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "ClassName.h"
|
|
#include "SystemHeader1.h"
|
|
#include "SystemHeader2.h"
|
|
```
|
|
|
|
**Pattern:**
|
|
1. Epic copyright header (required)
|
|
2. `#pragma once` guard
|
|
3. Core UE5 headers (`CoreMinimal.h` first)
|
|
4. Engine framework headers
|
|
5. Project headers
|
|
6. Forward declarations (headers only)
|
|
|
|
### Naming Conventions
|
|
|
|
**Classes:** PascalCase with UE5 prefixes
|
|
- `ABladeSmithCharacter` - Actor classes (A prefix)
|
|
- `UBladeSmithWeaponComponent` - Component classes (U prefix)
|
|
- `FDeformationVoxel` - Structs (F prefix)
|
|
- `EGameStateEnum` - Enums (E prefix)
|
|
|
|
**Functions:** PascalCase
|
|
```cpp
|
|
public:
|
|
void SwingHammer();
|
|
FVector GetHammerHeadLocation() const;
|
|
|
|
private:
|
|
void PerformHammerHit(); // Private helpers use PascalCase
|
|
```
|
|
|
|
**Variables:** camelCase
|
|
```cpp
|
|
float HammerForce = 1000.0f;
|
|
FVector HammerHeadOffset;
|
|
UMaterialInstanceDynamic* DynamicMaterialInstance;
|
|
TArray<FTemperatureVoxel> TemperatureGrid;
|
|
```
|
|
|
|
**Constants:** PascalCase
|
|
```cpp
|
|
const int32 MaxResolutionPerAxis = 200;
|
|
const float DefaultTemperature = 20.0f;
|
|
```
|
|
|
|
### Formatting
|
|
|
|
**Indentation:** 4 spaces (no tabs)
|
|
**Braces:** Allman style - opening brace on new line
|
|
```cpp
|
|
void ABladeSmithCharacter::Move(const FInputActionValue& Value)
|
|
{
|
|
FVector2D MovementVector = Value.Get<FVector2D>();
|
|
// implementation
|
|
}
|
|
```
|
|
|
|
**Line Length:** Under 120 characters, wrap parameters as needed
|
|
**Spacing:** Spaces around operators, after commas
|
|
|
|
### UE5 Macros and Attributes
|
|
|
|
**UPROPERTY Specifiers:**
|
|
```cpp
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Category")
|
|
UPropertyType* VariableName;
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Category|Subcategory", meta = (ClampMin = "0.0", ClampMax = "1.0"))
|
|
float PropertyWithConstraints;
|
|
|
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Category", meta = (AllowPrivateAccess = "true"))
|
|
UComponentType* PrivateComponent;
|
|
```
|
|
|
|
**UFUNCTION Specifiers:**
|
|
```cpp
|
|
UFUNCTION(BlueprintCallable, Category = "Category Name")
|
|
ReturnType FunctionName(Parameters);
|
|
|
|
UFUNCTION(BlueprintImplementableEvent)
|
|
void BlueprintEventName();
|
|
```
|
|
|
|
**USTRUCT:**
|
|
```cpp
|
|
USTRUCT(BlueprintType)
|
|
struct FStructName
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
UPROPERTY()
|
|
Type VariableName;
|
|
};
|
|
```
|
|
|
|
### Type Annotations
|
|
|
|
**UE5 Types (preferred):**
|
|
- `TArray<T>` instead of std::vector
|
|
- `TMap<TKey, TValue>` instead of std::map
|
|
- `TSet<T>` instead of std::unordered_set
|
|
- `FVector`, `FVector2D`, `FRotator`, `FQuat` for math
|
|
- `FString` for strings (TEXT() macro for string literals)
|
|
- `FName` for names, `FText` for localized text
|
|
- `float` not double (unless precision critical)
|
|
- `int32` not int, `uint8` for bytes
|
|
- `bool` for booleans
|
|
|
|
**Smart Pointers:**
|
|
- Use UE5's garbage collection for UObject-derived classes
|
|
- `TSharedPtr<T>` for non-UObject smart pointers
|
|
- `TWeakObjectPtr<T>` for weak references to UObjects
|
|
|
|
### Error Handling
|
|
|
|
**Null Checks:**
|
|
```cpp
|
|
if (DynamicMeshComp == nullptr)
|
|
{
|
|
UE_LOG(LogTemp, Error, TEXT("DynamicMeshComponent not found"));
|
|
return;
|
|
}
|
|
```
|
|
|
|
**Logging:**
|
|
```cpp
|
|
UE_LOG(LogTemp, Log, TEXT("Temperature: %.1f°C"), Temperature); // Info
|
|
UE_LOG(LogTemp, Warning, TEXT("Temperature system disabled")); // Warning
|
|
UE_LOG(LogTemp, Error, TEXT("Failed to initialize GPU buffers")); // Error
|
|
```
|
|
|
|
**Validation:**
|
|
```cpp
|
|
if (!IsValid(InputParam))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Early return pattern
|
|
if (Condition)
|
|
{
|
|
return;
|
|
}
|
|
```
|
|
|
|
### Documentation
|
|
|
|
**Chinese Comments:** Domain-specific logic uses Chinese comments
|
|
```cpp
|
|
/** 锤子组件 */
|
|
/** 温度体素结构 - 存储单个体素的温度和塑性数据 */
|
|
```
|
|
|
|
**Function Documentation:**
|
|
```cpp
|
|
/**
|
|
* 函数简述
|
|
* @param ParameterName 参数说明
|
|
* @return 返回值说明
|
|
*/
|
|
```
|
|
|
|
### Threading and GPU Operations
|
|
|
|
**Atomic Flags:**
|
|
```cpp
|
|
std::atomic<bool> bGPUBuffersReady{false};
|
|
```
|
|
|
|
**Render Thread Operations:**
|
|
```cpp
|
|
ENQUEUE_RENDER_COMMAND(CommandName)(
|
|
[Params](FRHICommandListImmediate& RHICmdList)
|
|
{
|
|
// GPU operations here
|
|
}
|
|
);
|
|
```
|
|
|
|
### Component Structure Pattern
|
|
|
|
**Actor Template:**
|
|
```cpp
|
|
UCLASS()
|
|
class BLADESMITH_API AClassName : public AParentClass
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
AClassName();
|
|
|
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Category")
|
|
UComponentType* Component;
|
|
|
|
UFUNCTION(BlueprintCallable, Category="Category")
|
|
ReturnType PublicFunction();
|
|
|
|
protected:
|
|
virtual void BeginPlay() override;
|
|
virtual void Tick(float DeltaTime) override;
|
|
|
|
private:
|
|
void PrivateHelper();
|
|
};
|
|
```
|
|
|
|
---
|
|
|
|
## Module Dependencies
|
|
|
|
**BladeSmith.Build.cs:**
|
|
- GeometryScriptingCore, GeometryFramework, DynamicMesh
|
|
- GeometryCore, GeometryAlgorithms, ModelingComponents
|
|
- RenderCore, RHI, Renderer, PhysicsCore
|
|
- EnhancedInput, AudioExtensions, AudioMixer
|
|
- Custom: MiceShaders (plugin)
|
|
|
|
---
|
|
|
|
## Performance Guidelines
|
|
|
|
- **Deformation calculations:** <7ms per frame target
|
|
- **60 FPS:** Maintain during hammer operations
|
|
- **High-poly meshes:** ~100k vertices with GPU acceleration
|
|
- **Voxel resolution:** 50x50x50 typical (balance performance/quality)
|
|
- **Use RDG (Render Dependency Graph)** for GPU compute operations
|
|
|
|
---
|
|
|
|
## Common Patterns
|
|
|
|
**Material Parameters:**
|
|
```cpp
|
|
UMaterialInstanceDynamic* DynMaterial = UMaterialInstanceDynamic::Create(BaseMaterial, this);
|
|
DynMaterial->SetScalarParameterValue(TEXT("ParameterName"), Value);
|
|
DynMaterial->SetVectorParameterValue(TEXT("VectorParam"), FLinearColor(R,G,B,A));
|
|
DynMaterial->SetTextureParameterValue(TEXT("TextureParam"), Texture);
|
|
```
|
|
|
|
**Dynamic Mesh Editing:**
|
|
```cpp
|
|
UDynamicMesh* DynMesh = DynMeshComp->GetDynamicMesh();
|
|
DynMesh->EditMesh([&](FDynamicMesh3& EditMesh)
|
|
{
|
|
for (FVertexID VertexID : EditMesh.VertexIndicesItr())
|
|
{
|
|
EditMesh.SetVertex(VertexID, NewPosition);
|
|
}
|
|
}, EDynamicMeshChangeType::GeneralEdit);
|
|
```
|
|
|
|
**Input Binding (Enhanced Input):**
|
|
```cpp
|
|
if (UEnhancedInputComponent* EnhancedInput = Cast<UEnhancedInputComponent>(InputComponent))
|
|
{
|
|
EnhancedInput->BindAction(Action, ETriggerEvent::Triggered, this, &ClassName::Handler);
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Plugin System
|
|
|
|
**MiceShaders Plugin:**
|
|
- Custom compute shaders for temperature simulation and deformation
|
|
- Located in `Plugins/MiceShaders/`
|
|
- Add new shaders: Create `.h` and `.cpp` in Source/MiceShaders, HLSL in Shaders/Private/
|
|
- Use RDG for shader dispatch
|
|
|
|
---
|
|
|
|
## Git Workflow
|
|
|
|
- **Ignore:** `Binaries/`, `Intermediate/`, `DerivedDataCache/`, `Saved/`, `.vs/`, `.idea/`
|
|
- **Commit:** Source/, Content/, Plugins/, Config/, docs/
|
|
- **No binary assets** in Git (use version control for assets)
|
|
|
|
---
|
|
|
|
## Documentation
|
|
|
|
**Technical docs:** Located in `docs/plans/`
|
|
- Reference existing design docs before implementing new features
|
|
- Update plans when architecture changes
|
|
- Use markdown for design documents
|