9.1 KiB
9.1 KiB
Skill GFX System Deep Dive
Movement System Architecture
CGfxMoveBase Design
Purpose: Abstract base for all projectile movement patterns.
Key Responsibilities:
- Calculate position over time
- Handle area emission (random offsets)
- Support clustering (multiple projectiles)
- Provide position/direction queries
Core Methods:
public abstract void StartMove(Vector3 vHost, Vector3 vTarget);
public abstract bool TickMove(uint dwDeltaTime, Vector3 vHostPos, Vector3 vTargetPos);
Return Value Semantics:
StartMove(): Initialize movement, set initial position/directionTickMove():- Returns
true= target reached/hit - Returns
false= still in flight - Updates
m_vPosandm_vMoveDir
- Returns
Movement Mode Details
CGfxLinearMove
- Pattern: Straight line from host to target
- Speed:
_fly_speed = 20.0f / 1000.0f(units per millisecond) - Behavior:
- If max fly time allows, uses constant speed
- Otherwise, calculates speed to reach target in max time
- Updates direction each frame to track moving target
CGfxOnTargetMove
- Pattern: Instant hit (no flight)
- Behavior:
StartMove(): Sets position to target immediatelyTickMove(): Returnsfalse(stays at target)- Hit triggered by fly time timeout, NOT by
TickMove()return - Supports cluster offset (random radius around target)
CGfxParabolicMove
- Pattern: Arc trajectory with gravity
- Physics:
- Horizontal velocity constant
- Vertical velocity affected by gravity
- Calculates initial vertical velocity to reach target
CGfxMissileMove
- Pattern: Homing missile
- Behavior:
- Accelerates toward target
- Rotates to face target
- Constant acceleration until hit
CGfxMeteoricMove
- Pattern: Falls from sky
- Behavior:
- Starts above target
- Falls straight down
- Configurable radius
CGfxHelixMove
- Pattern: Spiral path
- Behavior:
- Spiral around center axis
- Radius can shrink over time
- Configurable radius parameter
CGfxCurvedMove
- Pattern: Bezier-like curve
- Behavior:
- Curves from host to target
- Can curve left or right
- Configurable lateral speed
CGfxAccMove
- Pattern: Accelerated flight
- Behavior:
- Constant acceleration
- Configurable acceleration value
CGfxLinkMove
- Pattern: Lightning chain
- Behavior:
- Links between host and target
- Updates GFX parameters dynamically
- No movement (stays linked)
CGfxRandMove
- Pattern: Random walk
- Behavior:
- Random direction changes
- Configurable step size and speed
- Uses control points for smoothness
Area Emission System
Purpose
Emit multiple projectiles in a random area around the start position.
Configuration
- m_bArea: Enable area emission
- m_Shape: Emission shape (Box, Sphere, Cylinder)
- m_vSize: Size of emission area
Implementation
CalcRange(): Calculates X/Y/Z range vectors based on movement direction.
protected void CalcRange(Vector3 vDir)
{
m_vYRange = Vector3.up;
m_vZRange = new Vector3(vDir.x, 0, vDir.z); // Project to horizontal
if (Normalize(ref m_vZRange) < 0.01f) m_vZRange = Vector3.forward;
m_vXRange = Vector3.Cross(m_vYRange, m_vZRange); // Perpendicular
// Scale by m_vSize
}
GetRandOff(): Generates random offset based on shape.
- Box: Uniform distribution in box
- Sphere: Uniform distribution in sphere (rejection sampling)
- Cylinder: Uniform in horizontal circle, uniform in Y
Usage
if (m_bArea)
{
CalcRange((vTarget - vHost).normalized);
m_vPos = vHost + GetRandOff();
}
Clustering System
Purpose
Emit multiple projectiles with time intervals (e.g., machine gun effect).
Configuration
- m_bOneOfCluser: This projectile is part of a cluster
- Cluster params: Count and interval (handled by manager)
OnTarget Clustering
For CGfxOnTargetMove, clustering adds random offset:
if (m_bOneOfCluser)
{
float fRandAng = Random.value * 2π;
float fRadius = Random.value * m_fRadius;
m_vOffset = new Vector3(cos(ang) * radius, 0, sin(ang) * radius);
m_vPos += m_vOffset;
}
State Machine Details
enumWait State
- Entry: Event created
- Behavior:
- Increment
m_dwCurSpan - Wait for
m_dwDelayTime
- Increment
- Exit: When
m_dwCurSpan >= m_dwDelayTime - Transition: →
enumFlying
enumFlying State
- Entry: Delay expired
- Behavior:
- Call
m_pMoveMethod.SetMaxFlyTime(m_dwFlyTimeSpan) - Call
m_pMoveMethod.StartMove(m_vHostPos, m_vTargetPos) - Each frame:
- Update host/target positions if
m_bTraceTarget - Call
m_pMoveMethod.TickMove(dwDeltaTime, ...) - Update GFX position
- Check timeout:
m_dwCurSpan > m_dwFlyTimeSpan
- Update host/target positions if
- Call
- Exit Conditions:
TickMove()returnstrue(target hit)m_dwCurSpan > m_dwFlyTimeSpan(timeout)
- Transition: →
enumHit
enumHit State
- Entry: Target hit or timeout
- Behavior:
- Release fly GFX (fade out or immediate)
- Spawn hit GFX at target position
- Update hit GFX position if
m_bTraceTarget - Check if hit GFX is infinite (
m_bHitGfxInfinite)
- Exit Conditions:
- Hit GFX completes (not infinite)
- Hit GFX timeout (5 seconds for infinite)
- Target disappears
- Transition: →
enumFinished
enumFinished State
- Entry: Hit effect complete
- Behavior:
- Release all GFX
- Mark event for cleanup/pooling
- Exit: Event removed from active list
Position Tracking
Host Position
- Source: Character position from
m_nHostID - Update: Each frame if
m_bHostExist - Usage:
- Initial position for
StartMove() - Dynamic updates for
TickMove()(if target moves)
- Initial position for
Target Position
- Source: Character position from
m_nTargetID - Update: Each frame if
m_bTargetExistandm_bTraceTarget - Usage:
- Target position for
StartMove() - Dynamic updates for
TickMove()(tracking)
- Target position for
GetTargetCenter()
- Abstract method: Must be implemented by derived class
- Purpose: Get current target center position
- Implementation:
CECSkillGfxEvent: Gets character position from ID- Can use hooks/bones in future
GFX Loading & Instantiation
C++ Pattern
A3DGFXEx* LoadFlyGfx(A3DDevice* pDev, const char* szPath);
void SetFlyGfx(A3DGFXEx* pFlyGfx);
C# Pattern (Unity)
// Async loading with Addressables
async Task<GameObject> LoadFlyGfxAsync(string path)
{
var handle = Addressables.LoadAssetAsync<GameObject>(path);
await handle.Task;
return handle.Result;
}
// Instantiation
GameObject instance = Instantiate(prefab, position, rotation);
Lifecycle
- Load: Async load prefab (Addressables)
- Instantiate: Create instance at position
- Update: Update position each frame
- Release: Destroy instance, release prefab
Parameter System
GFX_SKILL_PARAM Structure
public struct GFX_SKILL_PARAM
{
public ValueUnion value; // Union: bVal, nVal, or fVal
public bool m_bArea;
public EmitShape m_Shape;
public A3DVECTOR3 m_vSize;
}
Usage by Movement Mode
- CGfxLinearMove: Uses
m_bArea,m_Shape,m_vSize(default) - CGfxOnTargetMove: Also uses
value.fValfor radius - CGfxMeteoricMove: Uses
value.fValfor fall radius - CGfxHelixMove: Uses
value.fValfor spiral radius - CGfxCurvedMove: Uses
value.bValfor curve direction - CGfxAccMove: Uses
value.fValfor acceleration - CGfxRandMove: Uses
value.fValfor speed
Setting Parameters
GFX_SKILL_PARAM param = new GFX_SKILL_PARAM();
param.value.fVal = 5.0f; // Radius for OnTarget
param.m_bArea = true;
param.m_Shape = EmitShape.enumSphere;
param.m_vSize = new A3DVECTOR3(2, 2, 2);
m_pMoveMethod.SetParam(param);
Performance Optimizations
Object Pooling
- Purpose: Reuse event instances
- Implementation:
m_FreeLstinCECSkillGfxMan - Usage:
- Get from pool when creating event
- Return to pool when finished
GFX Caching
- Purpose: Avoid reloading same prefabs
- Implementation: Cache loaded Addressable handles
- Key: Use path as key
Batch Updates
- Purpose: Update all events efficiently
- Implementation: Single loop through active events
- Optimization: Early exit for finished events
LOD System
- Purpose: Reduce quality for distant effects
- Field:
m_bGfxUseLod - Usage: Disable expensive effects when far away
Debugging Tips
Common Issues
- Projectile doesn't move: Check
StartMove()called,m_fSpeedset - Projectile goes wrong direction: Check
m_vMoveDircalculation - Hit doesn't trigger: Check
TickMove()return value, timeout - GFX doesn't appear: Check loading, instantiation, position
- Performance issues: Check pooling, caching, LOD
Debug Fields
m_vPos: Current positionm_vMoveDir: Current directionm_enumState: Current statem_dwCurSpan: Current time spanm_dwFlyTimeSpan: Max fly time
Visualization
- Draw gizmos for projectile position
- Draw line from host to target
- Show state in inspector
- Log state transitions