using System.Linq.Expressions;
using System.Reflection;
using UnityEngine;
using Object = UnityEngine.Object;
public class EnemyStateMachine : MonoBehaviour {
Func<Enemy, Hero, Action<Enemy, Hero>> stateEvaluator;
Action<Enemy, Hero> behavior;
Enemy enemy;
Hero hero;
void Start() {
enemy = FindObjectOfType<Enemy>();
hero = FindObjectOfType<Hero>();
stateEvaluator = CreateDynamicStateMachine();
}
void Update() {
behavior = stateEvaluator(enemy, hero);
behavior(enemy, hero);
Debug.Log("Enemy Aggression Level:", enemy.AggressionLevel);
}
public Func<Enemy, Hero, Action<Enemy, Hero>> CreateDynamicStateMachine() {
ParameterExpression enemyParam = Expression.Parameter(typeof(Enemy), "enemy");
ParameterExpression heroParam = Expression.Parameter(typeof(Hero), "hero");
BinaryExpression heroLowHealth = Expression.LessThan(
Expression.Property(heroParam, "Health"),
Expression.Constant(30)
);
BinaryExpression heroNear = Expression.LessThan(
Expression.Property(heroParam, "Distance"),
Expression.Constant(10f)
);
Debug.Log($"HeroLowHealth{heroLowHealth}");
Debug.Log($"HeroNear{heroNear}");
var attack = CreateActionExpression("Attack").Compile();
var taunt = CreateActionExpression("Taunt").Compile();
var patrol = CreateActionExpression("Patrol").Compile();
ConditionalExpression tauntOrPatrol = Expression.Condition(heroNear, Expression.Constant(taunt), Expression.Constant(patrol));
ConditionalExpression finalCondition = Expression.Condition(heroLowHealth, Expression.Constant(attack), tauntOrPatrol);
var lambda = Expression.Lambda<Func<Enemy, Hero, Action<Enemy, Hero>>>(finalCondition, enemyParam, heroParam);
return lambda.Compile();
}
Expression<Action<Enemy, Hero>> CreateActionExpression(string methodName) {
ParameterExpression enemyParam = Expression.Parameter(typeof(Enemy), "enemy");
ParameterExpression heroParam = Expression.Parameter(typeof(Hero), "hero");
MethodInfo method = typeof(Enemy).GetMethod(methodName, new[] { typeof(Hero) });
MethodCallExpression call = Expression.Call(enemyParam, method, heroParam);
return Expression.Lambda<Action<Enemy, Hero>>(call, enemyParam, heroParam);
}
}