WIP base of AIEntity
This commit is contained in:
parent
41e7ddfd48
commit
95e4388610
@ -97,13 +97,13 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
<Health>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
|
||||
|
||||
@ -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
|
||||
|
||||
15
Assets/Scripts/AI Stats.asset
Normal file
15
Assets/Scripts/AI Stats.asset
Normal file
@ -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
|
||||
8
Assets/Scripts/AI Stats.asset.meta
Normal file
8
Assets/Scripts/AI Stats.asset.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9d8a9a664d932d0498d5eca7607eeb53
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
103
Assets/Scripts/AIEntity.cs
Normal file
103
Assets/Scripts/AIEntity.cs
Normal file
@ -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<Entity>();
|
||||
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<Entity>();
|
||||
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<Entity>();
|
||||
if(targetEntity != null){
|
||||
targetEntity.TakeDamage(entity.attackDmg);
|
||||
bool isTargetAlive = targetEntity.IsAlive();
|
||||
if(!isTargetAlive){
|
||||
return new FindTargetState(entity);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/AIEntity.cs.meta
Normal file
11
Assets/Scripts/AIEntity.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9081d4ec2499ba4ab3e13006869bfaf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
6
Assets/Scripts/AIStats.cs
Normal file
6
Assets/Scripts/AIStats.cs
Normal file
@ -0,0 +1,6 @@
|
||||
using UnityEngine;
|
||||
|
||||
[CreateAssetMenu]
|
||||
public class AIStats : ScriptableObject {
|
||||
public float closeEnough = 1f;
|
||||
}
|
||||
11
Assets/Scripts/AIStats.cs.meta
Normal file
11
Assets/Scripts/AIStats.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4cd7eb51def0c7747bd646073babaf4f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -6,18 +6,19 @@ using UnityEngine;
|
||||
public class Entity : MonoBehaviour
|
||||
{
|
||||
[field: SerializeField]protected float Health {get; private set; }
|
||||
[SerializeField]private float movementSpeed;
|
||||
[SerializeField]private float rotSpeed;
|
||||
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<Rigidbody2D>();
|
||||
|
||||
@ -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<Entity>() is null
|
||||
Entity targetEntity = target.GetComponent<Entity>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -8,7 +8,7 @@ public class VampireEntity : Entity {
|
||||
|
||||
protected override void Start() {
|
||||
base.Start();
|
||||
SetName("Vampire");
|
||||
base.entityName = "Vampire";
|
||||
|
||||
initialHealth = Health;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user