basic aim assist system
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 19s
Create tag and build when new code gets to main / Test (push) Successful in 7m42s
Create tag and build when new code gets to main / Export (push) Successful in 10m3s

This commit is contained in:
2026-02-08 20:34:54 +01:00
parent c4be97e0de
commit 3148d3b69b
8 changed files with 91 additions and 0 deletions

View File

@@ -109,6 +109,9 @@ blend_mode = 1
[node name="Player" type="CharacterBody3D" unique_id=709076448]
collision_mask = 272
script = ExtResource("1_poq2x")
AimAssistStrength = 0.3
AimAssistReductionWhenCloseToTarget = 0.1
AimAssistReductionStartDistance = 8.0
RDamage = SubResource("Resource_cb2lu")
RKnockback = SubResource("Resource_abfq8")
RHealth = SubResource("Resource_ue7xq")
@@ -345,6 +348,12 @@ shape = SubResource("SphereShape3D_cmijs")
target_position = Vector3(0, 0, -5)
collision_mask = 48
[node name="AimAssistRayCast" type="RayCast3D" parent="." unique_id=995133571]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.6, 0)
target_position = Vector3(0, 0, -6)
collision_mask = 112
collide_with_areas = true
[node name="GroundDetector" type="ShapeCast3D" parent="." unique_id=1681055424]
shape = SubResource("CapsuleShape3D_6lejt")
collision_mask = 256

View File

@@ -361,6 +361,11 @@ public partial class HeadSystem : Node3D
return GetGlobalTransform().Basis.Z;
}
public Vector3 GetGlobalForwardVector()
{
return _camera.GlobalBasis.Z;
}
public Vector3 GetGlobalLookRotation()
{
return new Vector3(

View File

@@ -59,6 +59,7 @@ transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0,
mesh = ExtResource("3_svc06")
[node name="WeaponLocationIndicator" type="MeshInstance3D" parent="." unique_id=406396593]
visible = false
mesh = SubResource("SphereMesh_jpdh0")
[node name="StateChart" type="Node" parent="." unique_id=1135887603]

View File

@@ -81,6 +81,14 @@ public partial class PlayerController : CharacterBody3D,
// Combat stuff
[ExportCategory("Combat")]
[ExportGroup("General")]
[Export(PropertyHint.Range, "0,1f,0.01,or_greater")]
public float AimAssistStrength { get; set; } = 0.1f;
[Export(PropertyHint.Range, "0,1f,0.1,or_greater")]
public float AimAssistReductionWhenCloseToTarget { get; set; } = 0.3f;
[Export(PropertyHint.Range, "0,10f,0.1,or_greater")]
public float AimAssistReductionStartDistance { get; set; } = 10f;
[ExportGroup("Damage")]
[Export] public RDamage RDamage { get; set; }
[Export] public RKnockback RKnockback { get; set; }
@@ -372,6 +380,7 @@ public partial class PlayerController : CharacterBody3D,
private readonly List<IDamageable> _hitEnemies = new List<IDamageable>();
private ShapeCast3D _closeEnemyDetector;
private RayCast3D _aimAssisRayCast;
private Camera3D _camera;
public override void _Ready()
@@ -386,6 +395,8 @@ public partial class PlayerController : CharacterBody3D,
PlayerUi = GetNode<PlayerUi>("UI");
_closeEnemyDetector = GetNode<ShapeCast3D>("%CloseEnemyDetector");
_closeEnemyDetector.TargetPosition = _closeEnemyDetector.TargetPosition.Normalized() * TargetingDistance;
_aimAssisRayCast = GetNode<RayCast3D>("AimAssistRayCast");
_aimAssisRayCast.TargetPosition = _aimAssisRayCast.TargetPosition.Normalized() * (TargetingDistance*1.5f);
// DashIndicator = GetNode<TextureRect>("%DashIndicator");
PowerCooldownIndicator = GetNode<ColorRect>("%DashCooldownIndicator");
@@ -939,6 +950,31 @@ public partial class PlayerController : CharacterBody3D,
public float CalculateGravityForce() => _gravity * Weight;
// Camera stuff
private Vector2 ComputeAimAssist()
{
_aimAssisRayCast.SetRotation(HeadSystem.GetGlobalLookRotation());
if (!_aimAssisRayCast.IsColliding()) return Vector2.Zero;
// Hard dependency on the aim assist to be an Area3D and having a parent
var collidedObject = _aimAssisRayCast.GetCollider() as Area3D;
if (collidedObject is null) return Vector2.Zero;
if (collidedObject.GetParent() is not ITargetable targetable) return Vector2.Zero;
var targetPosition = targetable.GetTargetGlobalPosition();
var targetPositionOnCamera = _camera.UnprojectPosition(targetPosition);
var centerOfScreen = _camera.GetViewport().GetVisibleRect().Size / 2f;
var aimAssistDirection = centerOfScreen - targetPositionOnCamera;
var aimAssist = aimAssistDirection * AimAssistStrength / 1000f;
var distanceToTarget = (targetPosition - HeadSystem.GlobalPosition).Length();
if (distanceToTarget > AimAssistReductionStartDistance) return aimAssist; // useless but clearer
// Reduce aim assist when closing in on target because it can mess with the camera when dashing through
var distanceFactor = Mathf.Clamp(distanceToTarget / AimAssistReductionStartDistance, 0f, 1f);
var aimAssistReductionFactor = Mathf.Lerp(AimAssistReductionWhenCloseToTarget, 1f, distanceFactor);
return aimAssist * aimAssistReductionFactor;
}
private void LookAround(double delta)
{
Vector2 inputLookDir = new Vector2(_inputRotateY, _inputRotateFloorplane);
@@ -947,6 +983,9 @@ public partial class PlayerController : CharacterBody3D,
var wallHugContactPoint = _onWallRunning.Active ? _currentWallContactPoint : Vector3.Zero;
var moveInput = GetGlobalMoveInput();
if (_isUsingGamepad)
inputLookDir += ComputeAimAssist();
var lookAroundInputs = new HeadSystem.CameraParameters(
Delta: delta,
LookDir: inputLookDir,
@@ -1772,6 +1811,9 @@ public partial class PlayerController : CharacterBody3D,
// DashIndicatorMesh.Visible = true;
if (!isOnFloorCustom())
ReduceTimeScaleWhileAiming();
_aimAssisRayCast.TargetPosition = _aimAssisRayCast.TargetPosition.Normalized() *
(DashSystem.DashCast3D.TargetPosition.Length() + DashSystem.DashCastRadius);
}
public void HandleAiming(float delta)
{
@@ -1785,6 +1827,8 @@ public partial class PlayerController : CharacterBody3D,
{
DashSystem.StopPreparingDash();
_aimAssisRayCast.TargetPosition = _aimAssisRayCast.TargetPosition.Normalized() * (TargetingDistance*1.5f);
// DashIndicatorMesh.Visible = false;
}