Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections.Generic;
- using UnityEngine;
- public class Bullet : MonoBehaviour
- {
- private const int RAYCAST_MAX_DISTANCE = int.MaxValue;
- private const float SPEED = 20f;
- [SerializeField] private int amountOfBounces;
- [HideInInspector] public float aliveTime;
- private float aliveTempTime;
- private bool canDestroy;
- public GameObject impactEffect;
- private GameObject previousCollisionObject;
- private int maxBounces;
- private Vector3 currentDirection;
- private bool useTimer;
- private void Start()
- {
- maxBounces = amountOfBounces;
- aliveTempTime = aliveTime;
- if (aliveTempTime!=0)
- {
- useTimer = true;
- }
- currentDirection = transform.up.normalized;
- }
- private void Update()
- {
- HandleTimer();
- }
- private void HandleTimer()
- {
- if (!useTimer)
- {
- return;
- }
- if (aliveTempTime < 0)
- {
- return;
- }
- aliveTempTime -= Time.deltaTime;
- if (aliveTempTime <= 0)
- {
- canDestroy = true;
- }
- }
- private void FixedUpdate()
- {
- MoveTowardsPathPoint();
- }
- private void MoveTowardsPathPoint()
- {
- BulletPath _target = GetNextTarget(previousCollisionObject);
- if (_target == default)
- {
- Destroy(gameObject);
- return;
- }
- MoveTowardsTarget(_target);
- if (!DidReachTarget(_target))
- {
- return;
- }
- HandleCollisionAndReflection(_target);
- InstantiateImpactEffect();
- CheckDestroyConditions();
- }
- private void MoveTowardsTarget(BulletPath _target)
- {
- Transform _bulletTransform = transform;
- _bulletTransform.position = Vector3.MoveTowards(_bulletTransform.position, _target.ImpactPoint, SPEED * Time.deltaTime);
- }
- private bool DidReachTarget(BulletPath _target)
- {
- return Vector3.Distance(transform.position, _target.ImpactPoint) < 0.01f;
- }
- private void HandleCollisionAndReflection(BulletPath _target)
- {
- Transform _bulletTransform = transform;
- currentDirection = HandleRaycastHit(currentDirection, _target.RaycastHit2D);
- _bulletTransform.up = currentDirection;
- previousCollisionObject = _target.Collider;
- amountOfBounces--;
- }
- private void InstantiateImpactEffect()
- {
- if (impactEffect == null)
- {
- return;
- }
- GameObject _impact = Instantiate(impactEffect);
- _impact.transform.position = transform.position;
- Destroy(_impact, 1f);
- }
- private void CheckDestroyConditions()
- {
- if (canDestroy || (amountOfBounces == 0&& !useTimer))
- {
- Destroy(gameObject);
- }
- }
- private BulletPath GetNextTarget(GameObject _ignoreObject)
- {
- var _bulletTransform = transform;
- Vector2 _startingPosition = _bulletTransform.position;
- Vector2 _direction = _bulletTransform.up.normalized;
- List<BulletPath> _path = GetPath(_startingPosition, _direction, maxBounces, _ignoreObject);
- return _path != default && _path.Count > 0 ? _path[0] : default;
- }
- public static List<BulletPath> GetPath(Vector2 _startingPosition, Vector2 _direction, int _bouncesLeft, GameObject _currentObject)
- {
- List<BulletPath> _path = new List<BulletPath>();
- AddPoint(_startingPosition, _direction, _bouncesLeft, _currentObject, _path);
- return _path;
- }
- private static void AddPoint(Vector2 _startingPosition, Vector2 _direction, int _bouncesLeft, GameObject _currentObject, List<BulletPath> _path)
- {
- while (true)
- {
- RaycastHit2D _validHit = GetValidHit(_startingPosition, _direction, _currentObject);
- if (_validHit == default)
- {
- return;
- }
- Vector2 _newStartingPosition = _validHit.point;
- Vector2 _newDirection = HandleRaycastHit(_direction, _validHit);
- _bouncesLeft--;
- _path.Add(new BulletPath { ImpactPoint = _newStartingPosition, Collider = _validHit.transform.gameObject, RaycastHit2D = _validHit });
- if (_bouncesLeft <= 0)
- {
- return;
- }
- _startingPosition = _newStartingPosition;
- _direction = _newDirection;
- _currentObject = _validHit.transform.gameObject;
- }
- }
- private static RaycastHit2D GetValidHit(Vector2 _startingPosition, Vector2 _direction, GameObject _currentObject)
- {
- RaycastHit2D[] _hits = Physics2D.RaycastAll(_startingPosition, _direction, RAYCAST_MAX_DISTANCE);
- foreach (RaycastHit2D _hit in _hits)
- {
- GameObject _hitObject = _hit.transform.gameObject;
- if (!_hitObject.CompareTag("Wall") && !_hitObject.CompareTag("Ground"))
- {
- continue;
- }
- if (_hitObject == _currentObject)
- {
- continue;
- }
- return _hit;
- }
- return default;
- }
- private static Vector3 HandleRaycastHit(Vector3 _currentDirection, RaycastHit2D _hit)
- {
- Vector2 _wallNormal = _hit.normal;
- return Vector2.Reflect(_currentDirection, _wallNormal).normalized;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement