Projectlie Shooting Enemy Added
This commit is contained in:
45
Assets/Scripts/AI/Projectile.cs
Normal file
45
Assets/Scripts/AI/Projectile.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using Pausable;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AI
|
||||
{
|
||||
[RequireComponent(typeof(Rigidbody2D))]
|
||||
public class Projectile : MonoBehaviour, IPausable
|
||||
{
|
||||
[SerializeField] protected float damageOnContact = 50f;
|
||||
private Rigidbody2D _rigidbody = null;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_rigidbody = GetComponent<Rigidbody2D>();
|
||||
}
|
||||
|
||||
public void SetVelocity(Vector2 velocity)
|
||||
{
|
||||
_rigidbody.velocity = velocity;
|
||||
}
|
||||
|
||||
private void OnCollisionEnter2D(Collision2D other)
|
||||
{
|
||||
ProjectilePool.Instance.Return(this);
|
||||
}
|
||||
|
||||
public bool IsPaused { get; protected set; } = false;
|
||||
|
||||
public void Pause()
|
||||
{
|
||||
IsPaused = true;
|
||||
UpdateRigidbody();
|
||||
}
|
||||
public void Resume()
|
||||
{
|
||||
IsPaused = false;
|
||||
UpdateRigidbody();
|
||||
}
|
||||
|
||||
private void UpdateRigidbody()
|
||||
{
|
||||
_rigidbody.simulated = !IsPaused;
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/Scripts/AI/Projectile.cs.meta
Normal file
11
Assets/Scripts/AI/Projectile.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1451960c367cc30478631b32ba4f8356
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
56
Assets/Scripts/AI/ProjectilePool.cs
Normal file
56
Assets/Scripts/AI/ProjectilePool.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AI
|
||||
{
|
||||
public class ProjectilePool : MonoBehaviour
|
||||
{
|
||||
private static ProjectilePool _instance = null;
|
||||
public static ProjectilePool Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
GameObject go = new GameObject(typeof(ProjectilePool).Name);
|
||||
_instance = go.AddComponent<ProjectilePool>();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public Stack<Projectile> pool = null;
|
||||
private GameObject prefab;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (_instance != this && _instance != null)
|
||||
{
|
||||
Destroy(this);
|
||||
return;
|
||||
}
|
||||
|
||||
pool = new Stack<Projectile>(64);
|
||||
prefab = Resources.Load<GameObject>("Projectiles/Basic Projectile");
|
||||
}
|
||||
|
||||
public Projectile Get()
|
||||
{
|
||||
Projectile projectile = null;
|
||||
pool.TryPop(out projectile);
|
||||
|
||||
if (projectile == null)
|
||||
projectile = Instantiate(prefab).GetComponent<Projectile>();
|
||||
|
||||
projectile.gameObject.SetActive(true);
|
||||
|
||||
return projectile;
|
||||
}
|
||||
|
||||
public void Return(Projectile projectile)
|
||||
{
|
||||
projectile.gameObject.SetActive(false);
|
||||
pool.Push(projectile);
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/Scripts/AI/ProjectilePool.cs.meta
Normal file
11
Assets/Scripts/AI/ProjectilePool.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9d37792a64c70ac4eb6971ac3a062f15
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
82
Assets/Scripts/AI/ShootingEnemyAI.cs
Normal file
82
Assets/Scripts/AI/ShootingEnemyAI.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using Pausable;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace AI
|
||||
{
|
||||
public class ShootingEnemyAI : MonoBehaviour, IPausable
|
||||
{
|
||||
[SerializeField] protected float attacksPerSecond = 1f;
|
||||
[SerializeField] protected float attackRange = 5f;
|
||||
[SerializeField] protected float timeForProjectileToHit = .25f;
|
||||
|
||||
protected float cooldownPerShoot = 0f;
|
||||
protected float remainingCooldown = 0f;
|
||||
|
||||
private float attackRangeSquared = 5f;
|
||||
private Transform target = null;
|
||||
|
||||
private bool canShoot => (target.transform.position - transform.position).sqrMagnitude < attackRangeSquared && target != null;
|
||||
|
||||
public UnityEvent OnShoot { get; protected set; } = null;
|
||||
|
||||
#region IPausable
|
||||
public bool IsPaused { get; protected set; } = false;
|
||||
public virtual void Pause() => IsPaused = true;
|
||||
public virtual void Resume() => IsPaused = false;
|
||||
#endregion
|
||||
|
||||
protected void Awake()
|
||||
{
|
||||
cooldownPerShoot = 1f / attacksPerSecond;
|
||||
attackRangeSquared = attackRange * attackRange;
|
||||
OnShoot = new UnityEvent();
|
||||
UpdateTarget(FindObjectOfType<Player.PlayerController>()?.transform);
|
||||
}
|
||||
|
||||
protected void Update()
|
||||
{
|
||||
remainingCooldown -= Time.deltaTime;
|
||||
|
||||
if (remainingCooldown <= 0f && canShoot)
|
||||
Shoot();
|
||||
}
|
||||
|
||||
protected void Shoot()
|
||||
{
|
||||
|
||||
Projectile projectile = ProjectilePool.Instance.Get();
|
||||
projectile.transform.position = transform.position;
|
||||
|
||||
Vector3 velocity = GetVelocityForProjectile(timeForProjectileToHit);
|
||||
|
||||
RaycastHit2D raycastHit2D = Physics2D.Raycast(transform.position, target.position - transform.position, attackRange);
|
||||
if (raycastHit2D.transform != target)
|
||||
velocity = GetVelocityForProjectile(timeForProjectileToHit * 2);
|
||||
|
||||
projectile.SetVelocity(velocity);
|
||||
|
||||
remainingCooldown = cooldownPerShoot;
|
||||
OnShoot?.Invoke();
|
||||
}
|
||||
|
||||
private Vector3 GetVelocityForProjectile(float time)
|
||||
{
|
||||
Vector3 vector3 = target.position - transform.position;
|
||||
vector3.z = 0f;
|
||||
vector3.y -= (Physics2D.gravity.y / 2) * (time * time);
|
||||
vector3 /= time;
|
||||
return vector3;
|
||||
}
|
||||
|
||||
public void UpdateTarget(Transform transform) => target = transform;
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
Gizmos.color = Color.yellow;
|
||||
Gizmos.DrawWireSphere(transform.position, 0.125f);
|
||||
Gizmos.color = Color.red;
|
||||
Gizmos.DrawWireSphere(transform.position, attackRange);
|
||||
}
|
||||
}
|
||||
}
|
11
Assets/Scripts/AI/ShootingEnemyAI.cs.meta
Normal file
11
Assets/Scripts/AI/ShootingEnemyAI.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9308b2482216814428bfc53e4e5113c2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user