started adding enemy factory

This commit is contained in:
Mausham
2025-12-31 17:14:20 -08:00
parent 3aabc42bf8
commit 8eafd8bb60
130 changed files with 49524 additions and 46086 deletions

View File

@@ -14,13 +14,15 @@ namespace Darkmatter.App
[SerializeField] private PlayerMotor playerMotor;
[SerializeField] private PlayerAnimController playerAnim;
[SerializeField] private PlayerConfigSO playerConfig;
[SerializeField] private EnemyConfigSO enemyConfig;
[SerializeField] private CameraConfigSO cameraConfig;
[SerializeField] private CameraService camService;
[SerializeField] private GunWeapon gunWeapon;
[SerializeField] private TargetProvider TargetProvider;
[SerializeField] private PlayerAimTargetProvider TargetProvider;
protected override void Configure(IContainerBuilder builder)
{
builder.RegisterEntryPoint<PlayerController>(Lifetime.Scoped);
builder.RegisterEntryPoint<EnemyController>(Lifetime.Scoped);
builder.RegisterComponent<IPlayerAnim>(playerAnim);
builder.RegisterComponent<IInputReader>(inputReader);
@@ -28,9 +30,17 @@ namespace Darkmatter.App
builder.RegisterComponent<ITargetProvider>(TargetProvider);
builder.RegisterComponent(playerConfig);
builder.RegisterComponent(cameraConfig);
builder.RegisterComponent(enemyConfig);
builder.RegisterComponent<ICameraService>(camService);
builder.RegisterComponent<IReloadableWeapon>(gunWeapon);
builder.RegisterComponentInHierarchy<IEnemyAnimController>();
builder.RegisterComponentInHierarchy<IEnemyPawn>();
builder.Register<PlayerStateMachine>(Lifetime.Scoped);
builder.RegisterComponentInHierarchy<CameraService>().As<ICameraService>();
builder.Register<EnemyStateMachine>(Lifetime.Scoped);
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1095c90869cd18542ac49ca3066a5183
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,12 @@
using UnityEngine;
namespace Darkmatter.Core
{
public interface IEnemyAnimController
{
public void PlayWalkAnim(bool value);
public void PlayAttackAnim(bool value);
public void PlayeChaseAnim(bool value);
public void PlayDeadAnim();
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 068407f730880e34e9512e0a7b6aa189

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
namespace Darkmatter.Core
{
public interface IEnemyPawn : IDamageable
{
void InitializeFromFactory();
bool isDead { get; }
NavMeshAgent EnemyAI { get; }
List<Transform> PatrolPoints { get; }
void SetDestination(Vector3 destination);
Vector3 ReturnMyPos();
Transform PlayerTarget { get; }
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 8c4304330c3f4494b80013796f6dcf30

View File

@@ -1,9 +1,12 @@
using UnityEngine;
using System;
namespace Darkmatter.Core
{
public interface IDamageable
{
event Action<float> OnHealthDecreased;
float Health { get; set; }
void TakeDamage(float damage);
void Die();
}

View File

@@ -5,6 +5,5 @@ namespace Darkmatter.Core
public interface IHumonoidAnim
{
void PlayJumpAnim();
void PlayMovementAnim(Vector2 velocity);
}
}

View File

@@ -5,6 +5,7 @@ namespace Darkmatter.Core
{
public interface IPlayerAnim : IHumonoidAnim
{
public void PlayMovementAnim(Vector2 velocity);
public void PlayReloadAnim(IReloadableWeapon reloadableWeapon);
void PlayShootAnim();
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 53dde7197a1c44e4281d4edeac45e2d3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
%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: 8b8a5c204ef7f8e4f9079e6e8e28d1a8, type: 3}
m_Name: EnemyConfigSO
m_EditorClassIdentifier: CoreAssembly::Darkmatter.Core.EnemyConfigSO
walkSpeed: 1
chaseSpeed: 2
visionRange: 15
attackRange: 2

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1e02b1a664706154ead0ba098a00c234
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,14 @@
using UnityEngine;
namespace Darkmatter.Core
{
[CreateAssetMenu(fileName = "EnemyConfigSO", menuName = "Scriptable Objects/EnemyConfigSO")]
public class EnemyConfigSO : ScriptableObject
{
[Header("Enemy Data")]
public float walkSpeed = 3f;
public float chaseSpeed = 5f;
public float visionRange = 15f;
public float attackRange = 2f;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 8b8a5c204ef7f8e4f9079e6e8e28d1a8

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: eb71c28b0ae2ddd4f97052a36e8aa420
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
using UnityEngine;
namespace Darkmatter.Core
{
public interface IEnemyFactory
{
IEnemyPawn GetEnemy(ZombieType type);
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3089e498135722943b5e535be3721398

View File

@@ -0,0 +1,10 @@
using UnityEngine;
namespace Darkmatter.Core
{
public enum ZombieType
{
Fat,
slim
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 03bd7b15fdefdfb4abf373fa10450700

View File

@@ -0,0 +1,60 @@
using Darkmatter.Core;
using System;
using UnityEngine;
namespace Darkmatter.Domain
{
public class AttackState : State<EnemyStateMachine>
{
public AttackState(EnemyStateMachine runner) : base(runner) { }
private IEnemyAnimController enemyAnimController => runner.enemyAnimController;
private IEnemyPawn enemyPawn => runner.enemyPawn;
public override void Enter()
{
base.Enter();
Debug.Log("Entered Attack State");
Debug.Log("Attacking Player");
enemyAnimController.PlayAttackAnim(true);
enemyPawn.OnHealthDecreased += HandleHealth;
}
private void HandleHealth(float health)
{
if (health <= 0)
{
runner.Die();
}
}
public override void Update()
{
if (enemyPawn.isDead) return;
base.Update();
HandleAttack();
CheckForStateBreak();
}
private void CheckForStateBreak()
{
if(!runner.PlayerInAttackRange())
{
runner.ChangeState(new ChaseState(runner));
}
}
private void HandleAttack()
{
Vector3 dir = (enemyPawn.PlayerTarget.position - enemyPawn.ReturnMyPos()).normalized;
//rotate towards player and handle Attack here
}
public override void Exit()
{
base.Exit();
Debug.Log("Exiting Attack State");
enemyAnimController.PlayAttackAnim(false);
enemyPawn.OnHealthDecreased -= HandleHealth;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ee568c0b6df08d34d9c9fb008040066e

View File

@@ -0,0 +1,66 @@
using Darkmatter.Core;
using System;
using UnityEngine;
namespace Darkmatter.Domain
{
public class ChaseState : State<EnemyStateMachine>
{
public ChaseState(EnemyStateMachine runner) : base(runner) { }
private EnemyConfigSO enemyConfig => runner.enemyConfig;
private IEnemyAnimController enemyAnimController => runner.enemyAnimController;
private IEnemyPawn enemyPawn => runner.enemyPawn;
public override void Enter()
{
base.Enter();
Debug.Log("Entered Chase State");
runner.SetSpeed(enemyConfig.chaseSpeed);
enemyAnimController.PlayeChaseAnim(true);
enemyPawn.OnHealthDecreased += HandleHealth;
}
private void HandleHealth(float health)
{
if (health <= 0)
{
runner.Die();
}
}
public override void Update()
{
if (enemyPawn.isDead) return;
base.Update();
HandleChase();
CheckForStateBreak();
Debug.Log("Updated Chase State");
}
private void CheckForStateBreak()
{
if (!runner.PlayerInChasingRange())
{
runner.ChangeState(new PatrolState(runner));
}
else if(runner.PlayerInAttackRange())
{
runner.ChangeState(new AttackState(runner));
}
}
private void HandleChase()
{
enemyPawn.SetDestination(enemyPawn.PlayerTarget.position);
}
public override void Exit()
{
base.Exit();
Debug.Log("Exiting Chase State");
enemyAnimController.PlayeChaseAnim(false);
enemyPawn.OnHealthDecreased -= HandleHealth;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3a599db206b4b2a4b91b0af8749183e7

View File

@@ -10,7 +10,7 @@ namespace Darkmatter.Domain
public void Start()
{
esm.ChangeState(new PatrolState(esm));
}
public void Tick()

View File

@@ -1,9 +1,44 @@
using Darkmatter.Core;
using System.Threading.Tasks;
using UnityEngine;
using VContainer;
namespace Darkmatter.Domain
{
public class EnemyStateMachine:StateMachine
{
[Inject] public readonly IEnemyPawn enemyPawn;
[Inject] public readonly IEnemyAnimController enemyAnimController;
[Inject] public readonly EnemyConfigSO enemyConfig;
public void SetSpeed(float speed)
{
enemyPawn.EnemyAI.speed = speed;
}
public bool PlayerInChasingRange()
{
if(Vector3.Distance(enemyPawn.PlayerTarget.position,enemyPawn.ReturnMyPos()) < enemyConfig.visionRange)
{
return true;
}
return false;
}
public bool PlayerInAttackRange()
{
if(Vector3.Distance(enemyPawn.PlayerTarget.position,enemyPawn.ReturnMyPos())<enemyConfig.attackRange)
{
return true;
}
return false;
}
public void Die()
{
enemyAnimController.PlayDeadAnim();
enemyPawn.Die();
}
}
}

View File

@@ -0,0 +1,75 @@
using Codice.Client.Common;
using Darkmatter.Core;
using System;
using UnityEngine;
namespace Darkmatter.Domain
{
public class PatrolState : State<EnemyStateMachine>
{
public PatrolState(EnemyStateMachine runner) : base(runner) { }
private EnemyConfigSO enemyConfig => runner.enemyConfig;
private IEnemyAnimController enemyAnimController => runner.enemyAnimController;
private IEnemyPawn enemyPawn => runner.enemyPawn;
private int currentPatrolPointIndex = 0;
public override void Enter()
{
base.Enter();
Debug.Log("Entered Patrol State");
enemyPawn.OnHealthDecreased += HandleHealth;
runner.SetSpeed(enemyConfig.walkSpeed);
enemyAnimController.PlayWalkAnim(true);
}
private void HandleHealth(float health)
{
if(health<=0)
{
runner.Die();
}
}
public override void Update()
{
if (enemyPawn.isDead) return;
base.Update();
Debug.Log("Update in Patrol State");
HandlePatrol();
CheckForStateBreak();
}
private void CheckForStateBreak()
{
if(runner.PlayerInChasingRange())
{
runner.ChangeState(new ChaseState(runner));
}
}
private void HandlePatrol()
{
if (enemyPawn.PatrolPoints.Count == 0) return;
Transform target = enemyPawn.PatrolPoints[currentPatrolPointIndex];
enemyPawn.SetDestination(target.position);
if(Vector3.Distance(target.position,enemyPawn.ReturnMyPos()) < 0.5f) //close enought to targetPatrolPoint
{
Debug.Log("Reached Point");
currentPatrolPointIndex = (currentPatrolPointIndex+1)%enemyPawn.PatrolPoints.Count;
}
}
public override void Exit()
{
base.Exit();
enemyAnimController.PlayWalkAnim(false);
Debug.Log("Exiting Patrol State");
enemyPawn.OnHealthDecreased -= HandleHealth;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7c5d8a8739037414ea98cca25c34a1c9

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 24cf231bd8f41e043ab82eb2407bc8d5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,50 @@
using Darkmatter.Core;
using System.Collections.Generic;
using UnityEngine;
using VContainer;
namespace Darkmatter.Domain
{
public class EnemyFactory : IEnemyFactory
{
private readonly List<Transform> patrolPoints;
private readonly Transform playerTransform;
private readonly GameObject fatZombiePrefab;
private readonly GameObject slimZombiePrefab;
private readonly IObjectResolver objectResolver;
public EnemyFactory(Transform playerTransform, List<Transform> patrolPoints, GameObject fatZombiePrefab, GameObject slimZombiePrefab)
{
this.playerTransform = playerTransform;
this.patrolPoints = patrolPoints;
this.fatZombiePrefab = fatZombiePrefab;
this.slimZombiePrefab = slimZombiePrefab;
}
public IEnemyPawn GetEnemy(ZombieType type)
{
GameObject enemyObj = null;
switch (type)
{
case ZombieType.Fat:
enemyObj = GameObject.Instantiate(fatZombiePrefab, GetSpawnPos(), Quaternion.identity);
break;
case ZombieType.slim:
enemyObj = GameObject.Instantiate(slimZombiePrefab, GetSpawnPos(), Quaternion.identity);
break;
default:
break;
}
objectResolver.Inject(enemyObj);
IEnemyPawn enemyPawn = enemyObj.GetComponent<IEnemyPawn>();
return enemyPawn;
}
private Vector3 GetSpawnPos()
{
return patrolPoints[Random.Range(0, patrolPoints.Count)].position;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7cc7bf9641449434c9b547177a310227

View File

@@ -12,7 +12,7 @@ namespace Darkmatter.Domain
[Inject] public readonly IInputReader inputReader;
[Inject] public readonly IPlayerAnim playerAnim;
[Inject] public readonly ITargetProvider targetProvider;
[Inject] public readonly ICameraService cameraService;
[Inject] public readonly ICameraService cameraService;
[Inject] public readonly IReloadableWeapon currentWeapon;
[Inject] public readonly PlayerConfigSO playerConfig;
[Inject] public readonly CameraConfigSO cameraConfig;

View File

@@ -0,0 +1,33 @@
using Darkmatter.Core;
using UnityEngine;
namespace Darkmatter.Presentation
{
public class EnemyAnimController : HumonoidAnim, IEnemyAnimController
{
private readonly int walkHash = Animator.StringToHash("walk");
private readonly int chaseHash = Animator.StringToHash("chase");
private readonly int attackHash = Animator.StringToHash("attack");
private readonly int deadHash = Animator.StringToHash("dead");
public void PlayWalkAnim(bool value)
{
animator.SetBool(walkHash, value);
}
public void PlayAttackAnim(bool value)
{
animator.SetBool(attackHash, value);
}
public void PlayeChaseAnim(bool value)
{
animator.SetBool(chaseHash, value);
}
public void PlayDeadAnim()
{
animator.SetTrigger(deadHash);
}
}
}

View File

@@ -1,19 +0,0 @@
using UnityEngine;
namespace Darkmatter.Presentation
{
public class EnemyAnimationController : MonoBehaviour
{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
}

View File

@@ -7,16 +7,8 @@ namespace Darkmatter.Presentation
{
public Animator animator;
protected readonly int moveXhash = Animator.StringToHash("MoveX");
protected readonly int moveYhash = Animator.StringToHash("MoveY");
protected readonly int jumpHash = Animator.StringToHash("Jump");
public void PlayMovementAnim(Vector2 velocity)
{
animator.SetFloat(moveXhash, velocity.x,0.4f,Time.deltaTime);
animator.SetFloat(moveYhash, velocity.y,0.4f, Time.deltaTime);
}
public void PlayJumpAnim()
{
animator.SetTrigger(jumpHash);

View File

@@ -12,6 +12,8 @@ namespace Darkmatter.Presentation
public class PlayerAnimController : HumonoidAnim, IPlayerAnim
{
private readonly int shootHash = Animator.StringToHash("IsShooting");
protected readonly int moveXhash = Animator.StringToHash("MoveX");
protected readonly int moveYhash = Animator.StringToHash("MoveY");
private readonly int reloadHash = Animator.StringToHash("Reload");
public TwoBoneIKConstraint HandOnGunIK; //for gunHand Ik
private Coroutine reloadCoroutine;
@@ -59,6 +61,12 @@ namespace Darkmatter.Presentation
}
public void PlayMovementAnim(Vector2 velocity)
{
animator.SetFloat(moveXhash, velocity.x, 0.4f, Time.deltaTime);
animator.SetFloat(moveYhash, velocity.y, 0.4f, Time.deltaTime);
}
public void PlayShootAnim()
{
Debug.Log("player Shoot");

View File

@@ -1,30 +0,0 @@
using Darkmatter.Core;
using UnityEngine;
namespace Darkmatter.Presentation
{
public class Enemy : MonoBehaviour, IDamageable
{
public float health = 100f;
public Animator enemyAnimator;
public bool isDead = false;
public void Die()
{
isDead = true;
Debug.Log("Dead");
enemyAnimator.SetLayerWeight(0, 1);
enemyAnimator.SetTrigger("Death");
Destroy(this.gameObject, 5f);
}
public void TakeDamage(float damage)
{ if(isDead) return;
health -= damage;
if (health <= 0) Die();
Debug.Log("Damage Taken");
enemyAnimator.SetLayerWeight(1, 1);
enemyAnimator.SetTrigger("Hit");
}
}
}

View File

@@ -1,2 +0,0 @@
fileFormatVersion: 2
guid: 7cc0904e9eef2eb42860484c3c0d2675

View File

@@ -1,22 +1,64 @@
using Darkmatter.Core;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using VContainer;
namespace Darkmatter.Presentation
{
public class EnemyMotor : MonoBehaviour
public class EnemyMotor : MonoBehaviour, IEnemyPawn
{
[SerializeField] NavMeshAgent enemyAI;
public Transform playerTransform;
[SerializeField] private NavMeshAgent enemyAI;
[SerializeField] private Transform playerTransform;
[SerializeField] private List<Transform> patrolPoints = new List<Transform>();
[Inject] private EnemyConfigSO enemyConfig;
[Header("Enemy Data")]
public float walkSpeed = 3f;
public float chaseSpeed = 5f;
public float visionRange = 15f;
public float attackRange = 2f;
public Transform PlayerTarget => playerTransform;
public NavMeshAgent EnemyAI => enemyAI;
public List<Transform> PatrolPoints => patrolPoints;
private void Start()
public float Health { get; set; } = 100;
public bool isDead { get; set; } = false;
public event Action<float> OnHealthDecreased;
public void Die()
{
enemyAI.SetDestination(playerTransform.position);
isDead = true;
enemyAI.enabled = false;
Invoke(nameof(Hide), 8f);
}
private void Hide()
{
this.gameObject.SetActive(false);
}
public Vector3 ReturnMyPos()
{
return this.transform.position;
}
public void SetDestination(Vector3 destination)
{
enemyAI.SetDestination(destination);
}
public void TakeDamage(float damage)
{
Health -= damage;
OnHealthDecreased?.Invoke(Health);
}
private void OnDrawGizmos()
{
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(transform.position, enemyConfig.visionRange);
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, enemyConfig.attackRange);
}
}

View File

@@ -3,7 +3,7 @@ using UnityEngine;
namespace Darkmatter.Presentation
{
public class TargetProvider : MonoBehaviour, ITargetProvider
public class PlayerAimTargetProvider : MonoBehaviour, ITargetProvider
{
private Camera mainCamera;
[SerializeField] private LayerMask aimLayer;

View File

@@ -43,6 +43,7 @@ namespace Darkmatter.Presentation
private void PlayBulletHitEffectParticle()
{
var damageable = hitPoint.transform.GetComponent<IDamageable>();
Debug.Log(hitPoint.transform);
if (damageable != null)
{
damageable.TakeDamage(10f);