[FreedomAI]第二周——FuSM

只使用FSM及其变种是很难应用在复杂的AI中的,因为其复杂度的扩展性很差,就比如,如果怪物有20种状态,你就需要考虑20*20种可能性的连接。

所以这时我们必须建立分层次的状态机设计,试想一下,把AI的所有行为再分个类,每一类都认为是一种策略(事实上我们人的大脑也很类似这样,比如我们去攻击一个人,我们选择什么方式攻击、什么方式假动作是大脑思考好的,但之下的出拳这些动作确是自然而然做出来,虽然攻击策略不同,但是下面的行为确实一样的——这就是把策略看作了行为的组合),这样首先第一个好处就是,用很少的行为就可以表示很复杂的策略,因为同是出拳,在不同的策略中有不同的用法。这样,原本是增加状态节点->复杂度线性增加->难度指数增加,现在是增加状态节点和策略节点->复杂度平方增加->难度平方增加。

然后再来看看在框架中我们要如何做,很明显,一个策略要和一个状态机绑定。这里有一个问题出现了,策略还用FSM来做么?显然是不好的,FSM强调状态的转化,但是对于策略来说,策略的转化没有什么衔接和前后关系,所以我们使用了FuSM。FuSM的整体思想也很简单,他为每个策略确定了一个激活水平,选取最高激活水平的策略进入。

来看看代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityECS;
using FreedomAI;

namespace FreedomAI
{
	public delegate float StrategyActioner(AIEntity pEntity);

	public delegate float StrategyFeedbacker(AIEntity pEntity);

	public delegate void StrategyExit(AIEntity pEntity);

	public delegate void StrategyEnter(AIEntity pEntity);

	public class ObstacleComponent:UComponent
	{
		public GameObject hitObject;
		public float hitDistance;
		public Vector3 target;
	}

	public class ObstacleAvoidance
	{
		public static float ActionFunc(AIEntity pEntity)
		{
			GameObject tAIObject = pEntity.GetComponent<BaseAIComponent> ().mAIRT;
			Vector3 tDir = pEntity.GetComponent<AIMove> ().mDirection;
			float maxDis = 2.0f;
			RaycastHit hit = new RaycastHit();
			int layoutmask = 1 << LayerMask.NameToLayer ("Collision");
			if (Physics.Raycast (tAIObject.transform.position, tDir,out hit,maxDis,layoutmask))
			{
				Vector3 hitPos = hit.transform.position;
				float tDis = Vector3.Distance (hitPos,tAIObject.transform.position);
				pEntity.GetComponent<ObstacleComponent> ().hitObject = hit.transform.gameObject;
				pEntity.GetComponent<ObstacleComponent> ().hitDistance = tDis;
				if (tDis < 1.0f)
				{
					return 1.0f;
				}
				return 2.0f-tDis;
			}
			else
			{
				return 0.0f;
			}
		}

		public static void Strategy_Enter(AIEntity pEntity)
		{
			pEntity.GetComponent<ObstacleComponent> ().target = Vector3.zero;
		}

		public static void FSM_Avoid(AIEntity pEntity)
		{
			if (pEntity.GetComponent<ObstacleComponent> ().target == Vector3.zero)
			{
				Vector3 v1 = pEntity.GetComponent<ObstacleComponent> ().hitObject.transform.position - pEntity.AIPos;
				v1.y = 0.0f;
				Vector3 v2 = new Vector3 (1.0f,0.0f,-v1.x/v1.z);
				v2.Normalize ();
				Vector3 v3 = -v2;
				for (int i = 0; i <=10; i++) 
				{
					float tempRate = (float)i / 10.0f;
					Vector3 vdir1 = Vector3.Lerp (v1, v2, tempRate);
					vdir1.Normalize ();
					Vector3 vdir2 = Vector3.Lerp (v1,v3,tempRate);
					vdir2.Normalize ();
					float maxDis = 2
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值