From 95e4388610ac07724bcf9e78afc1c5fa74041870 Mon Sep 17 00:00:00 2001 From: Soulaha Balde Date: Sat, 2 Apr 2022 12:31:24 -0400 Subject: [PATCH] WIP base of AIEntity --- Assets/Prefabs/Gladiator.prefab | 4 +- Assets/Prefabs/Monster.prefab | 1 + Assets/Scripts/AI Stats.asset | 15 +++++ Assets/Scripts/AI Stats.asset.meta | 8 +++ Assets/Scripts/AIEntity.cs | 103 +++++++++++++++++++++++++++++ Assets/Scripts/AIEntity.cs.meta | 11 +++ Assets/Scripts/AIStats.cs | 6 ++ Assets/Scripts/AIStats.cs.meta | 11 +++ Assets/Scripts/Entity.cs | 33 ++++----- Assets/Scripts/Gladiator.cs | 5 +- Assets/Scripts/Monster.cs | 5 +- Assets/Scripts/VampireEntity.cs | 2 +- 12 files changed, 177 insertions(+), 27 deletions(-) create mode 100644 Assets/Scripts/AI Stats.asset create mode 100644 Assets/Scripts/AI Stats.asset.meta create mode 100644 Assets/Scripts/AIEntity.cs create mode 100644 Assets/Scripts/AIEntity.cs.meta create mode 100644 Assets/Scripts/AIStats.cs create mode 100644 Assets/Scripts/AIStats.cs.meta diff --git a/Assets/Prefabs/Gladiator.prefab b/Assets/Prefabs/Gladiator.prefab index 5fd83e0..6c83e05 100644 --- a/Assets/Prefabs/Gladiator.prefab +++ b/Assets/Prefabs/Gladiator.prefab @@ -97,13 +97,13 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: k__BackingField: 0 - movementSpeed: 5 - rotSpeed: 3 fov: 0 attackRange: 1.5 attackDmg: 10 attackCooldown: 1 target: {fileID: 0} + stats: {fileID: 11400000, guid: 9d8a9a664d932d0498d5eca7607eeb53, type: 2} + ennemyName: Monster --- !u!58 &3988163462708087662 CircleCollider2D: m_ObjectHideFlags: 0 diff --git a/Assets/Prefabs/Monster.prefab b/Assets/Prefabs/Monster.prefab index e63490d..c04df97 100644 --- a/Assets/Prefabs/Monster.prefab +++ b/Assets/Prefabs/Monster.prefab @@ -104,6 +104,7 @@ MonoBehaviour: attackDmg: 10 attackCooldown: 1 target: {fileID: 0} + stats: {fileID: 11400000, guid: 9d8a9a664d932d0498d5eca7607eeb53, type: 2} --- !u!50 &1427479462206541758 Rigidbody2D: serializedVersion: 4 diff --git a/Assets/Scripts/AI Stats.asset b/Assets/Scripts/AI Stats.asset new file mode 100644 index 0000000..fc57117 --- /dev/null +++ b/Assets/Scripts/AI Stats.asset @@ -0,0 +1,15 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4cd7eb51def0c7747bd646073babaf4f, type: 3} + m_Name: AI Stats + m_EditorClassIdentifier: + closeEnough: 2 diff --git a/Assets/Scripts/AI Stats.asset.meta b/Assets/Scripts/AI Stats.asset.meta new file mode 100644 index 0000000..c420059 --- /dev/null +++ b/Assets/Scripts/AI Stats.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9d8a9a664d932d0498d5eca7607eeb53 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/AIEntity.cs b/Assets/Scripts/AIEntity.cs new file mode 100644 index 0000000..81e0ab6 --- /dev/null +++ b/Assets/Scripts/AIEntity.cs @@ -0,0 +1,103 @@ +#nullable enable +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class AIEntity : Entity +{ + [SerializeField] AIStats stats = null!; + public string ennemyName {get; protected set; } + + abstract class BaseStateAI : BaseState{ + protected AIEntity entity; + public BaseStateAI(AIEntity entity){ + this.entity = entity; + } + } + + class SeekState : BaseStateAI{ + public SeekState(AIEntity entity) : base(entity){ + + } + + public override BaseState? UpdateState(){ + Entity targetEntity = entity.GetTarget().GetComponent(); + if(targetEntity != null){ + if(targetEntity.IsAlive()){//target is alive, keep chasing it + return null; + }else{//target is dead, go to findTargetState + return new FindTargetState(entity);; + } + } + return null; + } + + public override BaseState? FixedUpdateState(){ + Transform target = entity.GetTarget(); + entity.direction = Vector3.RotateTowards(entity.direction, (target.position - entity.transform.position), entity.rotSpeed*Time.fixedDeltaTime, 0.0f); + if(!entity.IsInAttackRange()){ + entity.rb.MovePosition(entity.transform.position + entity.direction * entity.movementSpeed * Time.fixedDeltaTime); + }else{ + return new AttackState(entity); + } + return null; + } + } + + class FindTargetState : BaseStateAI{ + float closeEnough; + public FindTargetState(AIEntity entity) : base(entity){ + } + + public override BaseState? UpdateState(){ + Entity[] entities = FindObjectsOfType(); + float lastDist = -1; + Entity chosenEntity = null!; + foreach (Entity other in entities){// Find the closest entity + if(other.name == entity.ennemyName){ + float distance = Vector2.Distance(other.transform.position, entity.transform.position); + if(distance < lastDist){ + lastDist = distance; + chosenEntity = other; + if(lastDist <= entity.stats.closeEnough)break; + } + } + } + if(chosenEntity != null){ + entity.SetTarget(chosenEntity.transform); + } + return new SeekState(entity); + } + + } + + class AttackState : BaseStateAI{ + public AttackState(AIEntity entity) : base(entity){ + } + + public override BaseState? UpdateState(){ + if(entity.IsInAttackRange()){ + if(entity.attackTimer >= entity.attackCooldown){ + entity.attackTimer = 0; + return Attack(); + }else{ + entity.attackTimer += Time.deltaTime; + } + + } + return null; + } + + private BaseState? Attack(){ + Entity targetEntity = entity.GetTarget().GetComponent(); + if(targetEntity != null){ + targetEntity.TakeDamage(entity.attackDmg); + bool isTargetAlive = targetEntity.IsAlive(); + if(!isTargetAlive){ + return new FindTargetState(entity); + } + } + return null; + } + } +} diff --git a/Assets/Scripts/AIEntity.cs.meta b/Assets/Scripts/AIEntity.cs.meta new file mode 100644 index 0000000..75d2700 --- /dev/null +++ b/Assets/Scripts/AIEntity.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a9081d4ec2499ba4ab3e13006869bfaf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/AIStats.cs b/Assets/Scripts/AIStats.cs new file mode 100644 index 0000000..e1d503a --- /dev/null +++ b/Assets/Scripts/AIStats.cs @@ -0,0 +1,6 @@ +using UnityEngine; + +[CreateAssetMenu] +public class AIStats : ScriptableObject { + public float closeEnough = 1f; +} \ No newline at end of file diff --git a/Assets/Scripts/AIStats.cs.meta b/Assets/Scripts/AIStats.cs.meta new file mode 100644 index 0000000..6fe625f --- /dev/null +++ b/Assets/Scripts/AIStats.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4cd7eb51def0c7747bd646073babaf4f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Entity.cs b/Assets/Scripts/Entity.cs index cbeff89..60e79b0 100644 --- a/Assets/Scripts/Entity.cs +++ b/Assets/Scripts/Entity.cs @@ -5,19 +5,20 @@ using UnityEngine; [RequireComponent(typeof(Rigidbody2D))] public class Entity : MonoBehaviour { - [field: SerializeField]protected float Health { get; private set; } - [SerializeField]private float movementSpeed; - [SerializeField]private float rotSpeed; + [field: SerializeField]protected float Health {get; private set; } + bool isAlive = true; + [SerializeField]public float movementSpeed{get; private set; } + [SerializeField]public float rotSpeed {get; private set; } [SerializeField]private float fov; [SerializeField]private float attackRange; - [SerializeField]private float attackDmg; + [SerializeField]public float attackDmg {get; private set; } [SerializeField]protected float attackCooldown; protected float attackTimer; [SerializeField]private Transform target; - private new string name; + public string entityName {get; protected set; } private Collider atkCollider; - private Vector3 direction; - Rigidbody2D rb; + public Vector3 direction {get; set; } + public Rigidbody2D rb {get; private set;} void Awake() => rb = GetComponent(); @@ -27,11 +28,6 @@ public class Entity : MonoBehaviour } protected virtual void Attack(){ - // jason: TODO Either have target be Entity instead of transform, or skip Attack when GetComponent() is null - Entity targetEntity = target.GetComponent(); - if(targetEntity != null){ - bool isTargetAlive = targetEntity.TakeDamage(attackDmg); - } } @@ -60,19 +56,12 @@ public class Entity : MonoBehaviour public virtual bool TakeDamage(float amount){ Health -= amount; if(Health <= 0){ + isAlive = false; return false; } return true; } - public void SetName(string name){ - this.name = name; - } - - protected string GetName(){ - return this.name; - } - protected bool IsInAttackRange(){ return Vector2.Distance(transform.position, target.position) <= attackRange; } @@ -81,4 +70,8 @@ public class Entity : MonoBehaviour float angle = Vector2.SignedAngle(direction, (target.position - transform.position)); return angle >= -fov && angle <= fov; } + + public bool IsAlive(){ + return isAlive; + } } diff --git a/Assets/Scripts/Gladiator.cs b/Assets/Scripts/Gladiator.cs index 81da14e..628a1d7 100644 --- a/Assets/Scripts/Gladiator.cs +++ b/Assets/Scripts/Gladiator.cs @@ -2,13 +2,14 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; -public class Gladiator : Entity +public class Gladiator : AIEntity { // Start is called before the first frame update override protected void Start() { base.Start(); - base.SetName("Gladiator"); + base.entityName = "Gladiator"; + base.ennemyName = "Monster"; } // Update is called once per frame diff --git a/Assets/Scripts/Monster.cs b/Assets/Scripts/Monster.cs index 77bd059..91d3042 100644 --- a/Assets/Scripts/Monster.cs +++ b/Assets/Scripts/Monster.cs @@ -2,13 +2,14 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; -public class Monster : Entity +public class Monster : AIEntity { // Start is called before the first frame update override protected void Start() { base.Start(); - base.SetName("Monster"); + base.entityName = "Monster"; + base.ennemyName = "Gladiator"; } void FixedUpdate() => MoveToTarget(Time.fixedDeltaTime); diff --git a/Assets/Scripts/VampireEntity.cs b/Assets/Scripts/VampireEntity.cs index 51561e8..a5bc04d 100644 --- a/Assets/Scripts/VampireEntity.cs +++ b/Assets/Scripts/VampireEntity.cs @@ -8,7 +8,7 @@ public class VampireEntity : Entity { protected override void Start() { base.Start(); - SetName("Vampire"); + base.entityName = "Vampire"; initialHealth = Health; }