lab5 dop
This commit is contained in:
1 parent
e60163307c
commit
bca661e132
5 files changed
+1189
-624
No files matched your search
@@ -0,0 +1,253 @@
|
||||
using Code.Base;
|
||||
using Code.Lab3;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Lab5
|
||||
{
|
||||
public class BetterProjectileLauncher : MonoBehaviour
|
||||
{
|
||||
[Header("Projectile Settings")]
|
||||
public GameObject projectilePrefab;
|
||||
public float launchSpeed = 20f;
|
||||
public bool useHighTrajectory;
|
||||
public float fireRate = 1f;
|
||||
|
||||
[Header("Target")]
|
||||
public Wander wanderingTarget;
|
||||
|
||||
public float predictionTime = 2f;
|
||||
public bool useDynamicPrediction = true;
|
||||
|
||||
[Header("Visualization")]
|
||||
public GameObject targetCirclePrefab;
|
||||
public bool showPredictedPosition = true;
|
||||
public float circleLifetime = 1f;
|
||||
|
||||
[Header("Accuracy")]
|
||||
[Range(0f, 1f)]
|
||||
public float accuracy = 0.9f;
|
||||
|
||||
public float inaccuracyRadius = 2f;
|
||||
|
||||
private float _nextFireTime;
|
||||
private Transform _predictedTarget;
|
||||
private GameObject _predictedTargetObject;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (wanderingTarget == null)
|
||||
{
|
||||
Debug.LogError("Wandering target not assigned!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (showPredictedPosition && targetCirclePrefab != null)
|
||||
{
|
||||
_predictedTargetObject = new GameObject("PredictedTarget");
|
||||
_predictedTarget = _predictedTargetObject.transform;
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (wanderingTarget == null) return;
|
||||
|
||||
if (Time.time >= _nextFireTime)
|
||||
{
|
||||
TryFireAtTarget();
|
||||
_nextFireTime = Time.time + 1f / fireRate;
|
||||
}
|
||||
|
||||
if (showPredictedPosition && _predictedTarget != null)
|
||||
{
|
||||
UpdatePredictedTargetVisual();
|
||||
}
|
||||
}
|
||||
|
||||
private void TryFireAtTarget()
|
||||
{
|
||||
if (!wanderingTarget || !projectilePrefab) return;
|
||||
|
||||
var targetPos = wanderingTarget.transform.position;
|
||||
var targetVelocity = GetTargetVelocity();
|
||||
|
||||
var predictedPos = PredictTargetPosition(targetPos, targetVelocity);
|
||||
|
||||
var aimPosition = ApplyInaccuracy(predictedPos);
|
||||
|
||||
if (!Projectile.IsTargetReachable(transform.position, aimPosition, launchSpeed))
|
||||
{
|
||||
useHighTrajectory = !useHighTrajectory;
|
||||
|
||||
if (!Projectile.IsTargetReachable(transform.position, aimPosition, launchSpeed))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var direction = Projectile.GetFireDirection(
|
||||
transform.position,
|
||||
aimPosition,
|
||||
launchSpeed,
|
||||
useHighTrajectory
|
||||
);
|
||||
|
||||
if (direction == Vector3.zero) return;
|
||||
|
||||
FireProjectile(direction, aimPosition);
|
||||
}
|
||||
|
||||
private Vector3 GetTargetVelocity()
|
||||
{
|
||||
if (wanderingTarget) return Vector3.zero;
|
||||
|
||||
var targetAgent = wanderingTarget.GetComponent<Agent>();
|
||||
if (targetAgent)
|
||||
{
|
||||
return targetAgent.velocity;
|
||||
}
|
||||
|
||||
return Vector3.zero;
|
||||
}
|
||||
|
||||
private Vector3 PredictTargetPosition(Vector3 currentPos, Vector3 velocity)
|
||||
{
|
||||
if (velocity.magnitude < 0.1f) return currentPos;
|
||||
|
||||
float timeToTarget;
|
||||
|
||||
if (useDynamicPrediction)
|
||||
{
|
||||
var toTarget = currentPos - transform.position;
|
||||
var distance = toTarget.magnitude;
|
||||
var closingSpeed = launchSpeed - Vector3.Dot(velocity, toTarget.normalized);
|
||||
|
||||
if (closingSpeed > 0)
|
||||
{
|
||||
timeToTarget = distance / closingSpeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeToTarget = predictionTime;
|
||||
}
|
||||
|
||||
timeToTarget = Mathf.Min(timeToTarget, predictionTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
timeToTarget = predictionTime;
|
||||
}
|
||||
|
||||
var predictedPos = currentPos + velocity * timeToTarget;
|
||||
|
||||
predictedPos.y = 0.1f;
|
||||
|
||||
return predictedPos;
|
||||
}
|
||||
|
||||
private Vector3 ApplyInaccuracy(Vector3 targetPos)
|
||||
{
|
||||
if (accuracy >= 1f) return targetPos;
|
||||
|
||||
var inaccuracy = (1f - accuracy) * inaccuracyRadius;
|
||||
|
||||
var randomOffset = Random.insideUnitCircle * inaccuracy;
|
||||
|
||||
var inaccuratePos = targetPos;
|
||||
inaccuratePos.x += randomOffset.x;
|
||||
inaccuratePos.z += randomOffset.y;
|
||||
|
||||
return inaccuratePos;
|
||||
}
|
||||
|
||||
private void FireProjectile(Vector3 direction, Vector3 targetPos)
|
||||
{
|
||||
var projObj = Instantiate(projectilePrefab, transform.position, Quaternion.identity);
|
||||
var projectile = projObj.GetComponent<Projectile>();
|
||||
projectile.Set(transform.position, direction, launchSpeed);
|
||||
|
||||
if (showPredictedPosition && targetCirclePrefab)
|
||||
{
|
||||
SpawnTargetCircle(targetPos, "ShotTarget");
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePredictedTargetVisual()
|
||||
{
|
||||
if (wanderingTarget) return;
|
||||
|
||||
var targetPos = wanderingTarget.transform.position;
|
||||
var targetVelocity = GetTargetVelocity();
|
||||
var predictedPos = PredictTargetPosition(targetPos, targetVelocity);
|
||||
|
||||
_predictedTarget.position = predictedPos;
|
||||
|
||||
Debug.DrawLine(transform.position, predictedPos, Color.cyan);
|
||||
|
||||
Debug.DrawLine(targetPos, predictedPos, Color.yellow);
|
||||
}
|
||||
|
||||
private void SpawnTargetCircle(Vector3 position, string name1 = "TargetCircle")
|
||||
{
|
||||
var circle = Instantiate(targetCirclePrefab, position, Quaternion.identity);
|
||||
circle.name = name1;
|
||||
|
||||
var circlePos = circle.transform.position;
|
||||
circlePos.y = 0.05f;
|
||||
circle.transform.position = circlePos;
|
||||
|
||||
if (circleLifetime > 0)
|
||||
{
|
||||
Destroy(circle, circleLifetime);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetAccuracy(float newAccuracy)
|
||||
{
|
||||
accuracy = Mathf.Clamp01(newAccuracy);
|
||||
}
|
||||
|
||||
public void SetFireRate(float newFireRate)
|
||||
{
|
||||
fireRate = Mathf.Max(0.1f, newFireRate);
|
||||
}
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
if (wanderingTarget == null) return;
|
||||
|
||||
Gizmos.color = Color.yellow;
|
||||
Gizmos.DrawWireSphere(wanderingTarget.transform.position, 0.5f);
|
||||
|
||||
var targetAgent = wanderingTarget.GetComponent<Agent>();
|
||||
if (targetAgent != null && targetAgent.velocity.magnitude > 0.1f)
|
||||
{
|
||||
Gizmos.color = Color.blue;
|
||||
var velocityVector = targetAgent.velocity.normalized * 2f;
|
||||
Gizmos.DrawRay(wanderingTarget.transform.position, velocityVector);
|
||||
}
|
||||
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
var targetPos = wanderingTarget.transform.position;
|
||||
var velocity = targetAgent != null ? targetAgent.velocity : Vector3.zero;
|
||||
var predictedPos = PredictTargetPosition(targetPos, velocity);
|
||||
|
||||
Gizmos.color = Color.cyan;
|
||||
Gizmos.DrawWireSphere(predictedPos, 0.5f);
|
||||
Gizmos.DrawLine(transform.position, predictedPos);
|
||||
}
|
||||
|
||||
Gizmos.color = new Color(1f, 0f, 0f, 0.2f);
|
||||
Gizmos.DrawWireSphere(transform.position, inaccuracyRadius);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (_predictedTargetObject != null)
|
||||
{
|
||||
Destroy(_predictedTargetObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user