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

@@ -162,6 +162,7 @@ locale/translations=PackedStringArray("res://addons/maaacks_game_template/base/t
3d_physics/layer_4="4"
3d_physics/layer_5="enemies"
3d_physics/layer_6="InteractiveGeo"
3d_physics/layer_7="Aim Assist"
3d_physics/layer_9="terrain"
3d_physics/layer_17="weapon"

View File

@@ -47,6 +47,9 @@ albedo_color = Color(0.06469653, 0.06469653, 0.06469653, 1)
[sub_resource type="BoxShape3D" id="BoxShape3D_4yfjf"]
[sub_resource type="SphereShape3D" id="SphereShape3D_ykkxn"]
radius = 2.0
[node name="FlyingEnemy" type="CharacterBody3D" unique_id=2090203407]
collision_layer = 16
collision_mask = 273
@@ -116,3 +119,10 @@ monitorable = false
[node name="CollisionShape3D" type="CollisionShape3D" parent="DamageBox" unique_id=68664931]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.5)
shape = SubResource("BoxShape3D_4yfjf")
[node name="AimAssistTarget" type="Area3D" parent="." unique_id=178575959]
collision_layer = 64
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="AimAssistTarget" unique_id=843739364]
shape = SubResource("SphereShape3D_ykkxn")

View File

@@ -48,6 +48,9 @@ albedo_color = Color(0.06469653, 0.06469653, 0.06469653, 1)
[sub_resource type="BoxShape3D" id="BoxShape3D_4yfjf"]
size = Vector3(1, 2, 1.5)
[sub_resource type="SphereShape3D" id="SphereShape3D_k2cew"]
radius = 2.0
[node name="GroundedEnemy" type="CharacterBody3D" unique_id=1747444936]
collision_layer = 16
collision_mask = 273
@@ -120,3 +123,11 @@ monitorable = false
[node name="CollisionShape3D" type="CollisionShape3D" parent="DamageBox" unique_id=978720734]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, -0.25)
shape = SubResource("BoxShape3D_4yfjf")
[node name="AimAssistTarget" type="Area3D" parent="." unique_id=328174571]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
collision_layer = 64
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="AimAssistTarget" unique_id=1960476920]
shape = SubResource("SphereShape3D_k2cew")

View File

@@ -17,6 +17,9 @@ roughness = 0.1
emission_enabled = true
emission = Color(0, 0.68968636, 0.7473501, 1)
[sub_resource type="SphereShape3D" id="SphereShape3D_gxutf"]
radius = 2.5
[node name="FixedDashthroughTarget" type="AnimatableBody3D" unique_id=1291663508]
collision_layer = 32
collision_mask = 0
@@ -28,3 +31,10 @@ shape = SubResource("SphereShape3D_nkm8n")
[node name="MeshInstance3D" type="MeshInstance3D" parent="." unique_id=1965985422]
mesh = SubResource("SphereMesh_r0j7a")
surface_material_override/0 = SubResource("StandardMaterial3D_kgb3i")
[node name="AimAssistTarget" type="Area3D" parent="." unique_id=1141164558]
collision_layer = 64
collision_mask = 0
[node name="CollisionShape3D" type="CollisionShape3D" parent="AimAssistTarget" unique_id=784189005]
shape = SubResource("SphereShape3D_gxutf")

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;
}