Edit: its working well now
Hi !
I have made a predictive aiming system for my game, I took an iterative approach to solve the predicted position.
it works nicely most of the time, but there seems to be a problem with calculating the offset angle of the spaceship weapon.
I’m assuming the problem is with the calculation of the projectile travel velocity and direction, but i can’t pinpoint the problem.
In the video you can see how it miss the target when the spaceship is moving fast, or orbiting a stationary object.
could any one help me out here, it seems like I’m missing something
The way the system works:
- calculating the predicted position of the target
- getting the direction from weapon to prediction
- getting the projectile travel direction, including inherited velocity from spaceship
- getting the angles of the weapon relative to the ship
- getting the angles of the projectile relative to the weapon
- rotating the weapon to a new angle equals to: projectile angle + weapon angle
Yellow line - direction from weapon to prediction
Red line - projectile direction of travel
Green line - the final weapon direction
0:00 to 0:15 - working nicely in low speed when target is relatively in front and spaceship travels straight
0:15 to 0:45 - orbiting the target and missing it
0:45 to end - shooting on a moving target
Calculate Target Predicted Position
public static class PredictiveAiming
{
public static Vector3 CalculateTargetPredictedPosition
(Transform target, Rigidbody targetRb, Transform shooter, Rigidbody shooterRb, float projectileStartSpeed, int iterations)
{
Vector3 targetVelocity = targetRb.velocity;
Vector3 targetPosition = target.transform.position;
Vector3 shooterPosition = shooter.transform.position;
float projectileSpeed = GetProjectileSpeedInDirection(shooterRb, projectileStartSpeed, targetPosition, shooterPosition);
float timeToTarget;
Vector3 targetFuturePosition = targetPosition;
for (int i = 0; i < iterations; i++)
{
timeToTarget = Vector3.Distance(targetFuturePosition, shooterPosition) / projectileSpeed;
targetFuturePosition = (timeToTarget * targetVelocity) + targetPosition;
projectileSpeed = GetProjectileSpeedInDirection(shooterRb, projectileStartSpeed, targetFuturePosition, shooterPosition);
}
return targetFuturePosition;
}
private static float GetProjectileSpeedInDirection(Rigidbody shooterRb, float projectileStartSpeed, Vector3 targetPosition, Vector3 shooterPosition)
{
float shooterSpeedInDirection = Vector3.Project(shooterRb.velocity, (targetPosition - shooterPosition).normalized).magnitude;
float projectileSpeed = projectileStartSpeed + shooterSpeedInDirection;
return projectileSpeed;
}
}
the part that sets the new weapon angle
public class Class1
{
Vector3 futurePos = PredictiveAiming.CalculateTargetPredictedPosition
(AimAssistTarget.transform, AimAssistTarget.Rigidbody, weapon.transform, ShipConfig.Rigidbody, weapon.StartingSpeed, 64);
Vector3 dirFromWeaponToPrediction = (futurePos - weapon.transform.position).normalized;
Vector3 shipVelocity = ShipConfig.Rigidbody.velocity;
_projectileTravelDirection = ((dirFromWeaponToPrediction* weapon.StartingSpeed) + shipVelocity).normalized;
Vector3 shipForwardDir = weapon.transform.parent.transform.forward;
_weaponAngleToTarget = Vector3.SignedAngle(shipForwardDir, dirFromWeaponToPrediction, weapon.transform.parent.transform.up);
_projectileAngleToTarget = Vector3.SignedAngle(_projectileTravelDirection, dirFromWeaponToPrediction, weapon.transform.parent.transform.up);
Vector3 newWeaponAngle = new Vector3(0f, _weaponAngleToTarget + _projectileAngleToTarget, 0f);
weapon.transform.localRotation = Quaternion.Euler(newWeaponAngle);
}