beyond-all-reason / beyond-all-reason/RecoilEngine
GroundMoveType unit skid enhancement proposal
- Dominant language
- C++
- Stars
- 679
- Forks
- 290
- Avg merge
- 3d 2h
- Merged PRs (30d)
- 40
Description
A proposal to update our current UpdateSkid() logic with key features.
1/ Separate "skidSpeed" from "selfSpeed" during the skid process:
```cpp
const float3& pos = owner->pos;
const float4& inputSpeed = owner->speed;
const float3 dir = owner ->frontdir;
const float3 inputSelfSpeed = inputSpeed.dot(dir)*dir; // speed in the direction of owner->frontdir
const float3 inputSkidSpeed = inputSpeed - inputSelfSpeed; // speed orthogonal to owner->frontdir
```
StopSkidding() function can then become a simple inputSkidSpeed.Length() < threshold check (= no orthogonal speed accumulation)
We can apply different drag values to orthogonal and colinear speeds
2/ Add a "skidRecoveryFactor" or "skidDragFactor" = float
When applying owner->GetDragAccelerationVec() on a grounded unit (not flying) we can then apply this factor to the orthogonal drag.
This would make sense mostly for hovers vs tanks: hovers sideways drag mostly relies on air friction and is no different from linear drag; while tanks' wheels/tracks will tend to fight sideways skid more.
The "passive" result is vehicules will tend to keep more forward speed relative to their skid speed than hovers, and will have an easier time recovering from it.
ie:
```cpp
float3 totalDragVec = owner->GetDragAccelerationVec(
mapInfo->atmosphere.fluidDensity,
mapInfo->water.fluidDensity,
owner->unitDef->atmosphericDragCoefficient,
owner->unitDef->groundFrictionCoefficient
);
float3 selfDragVec = dir * totalDragVec.dot(dir);
float3 skidDragVec = totalDragVec - selfDragVec;
outputSkidSpeed += skidRecoveryFactor*skidDragVec;
```
3/ Add an "manoeuverDuringSkid" bool
When performing UpdateSkid(), this tag will allow the unit to turn, accelerate in order to manoeuver out of skidding.
That part is still under construction.
The way i imagine it is:
> float controlRatio = skidSpeed/(speed); clamped between minValue (0.3f?) and 1.0.
> turnRate, accRate, decRate *= controlRatio
> currWaypointDist > turnRadius, or waypointDir.dot(speed) > 0: wantedDir becomes (speed/speed.Length())
> currWaypointDist < turnRadius AND waypointDir.dot(speed) < 0: wantedDir becomes (-skidSpeed/skidSpeed.Length())
We steer towards wantedDir at modTurnRate speed, which will alter next frame's skidSpeed and selfSpeed
> We accelerate towards currWaypoint if it's front
> We decelerate if currWaypoint is behind.
> We apply longitudinal drag if selfSpeed > maxSpeed
here is a WIP clip showing current state of progress.
https://www.youtube.com/watch?v=bIMTxD9WIUE
Contributor guide
Research direction
Start by locating UpdateSkid(), StopSkidding(), and GetDragAccelerationVec() in the ground-movement code and review how current skid and drag speeds are calculated. The proposal still leaves manoeuvring behavior under construction; done would require an agreed design and implementation of the separate speed components, recovery factor, and optional manoeuvring behavior, with validation of the resulting vehicle motion.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- game-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100