一个基础的的AI-状态机-脚手架

一方说,现在的AI不是真正的AI的

另一方说,现在的AI就是重大突破

我水平只是地球的水平,到不了火星,所以我是支持后者的,你不能说小鹏的走路姿势不是重大突破,不是真正的走路,在宏观世界

非常奇怪循环

模拟电子--- 数字电子 --- 再回到*模拟电子 --- 已是终点 --- 我们可能不到 *纯数字电子 --- 突破到四,五,六维度;

分享一个很简单的Unity,即可构建框架、

第一次接触AI的概念,可能来自1997这个电影
《星河战队》

STARSHIP TROOPERS

道理,很简单,就是一个大脑,控制很多个小脑

韩国人,c# 委托Delegate

public abstract class UOgreAI : MonoBehaviour 
{
    public enum EOgreAIState
    {
        OgreAI_None,
        OgreAI_Idle,
        OgreAI_PortalFollow,
        OgreAI_LeaderFollow,
    }
    protected void EnterState(EOgreAIState inEnterState)
    {
        switch(inEnterState)
        {
            case EOgreAIState.OgreAI_Idle:                  { Enter_Idle(currentAIState); DelegateAIUpdate = new FDelegateAIUpdate(Update_Idle); } break;
            case EOgreAIState.OgreAI_PortalFollow:          { Enter_PortalFollow(currentAIState); DelegateAIUpdate = new FDelegateAIUpdate(Update_PortalFollow); } break;
            case EOgreAIState.OgreAI_LeaderFollow:          { Enter_LeaderFollow(currentAIState); DelegateAIUpdate = new FDelegateAIUpdate(Update_LeaderFollow); } break;
            case EOgreAIState.OgreAI_EnemyFollow:           { Enter_EnemyFollow(currentAIState); DelegateAIUpdate = new FDelegateAIUpdate(Update_EnemyFollow); } break;
        }
    }
   // 상태 진입.
    protected void EnterState(EOgreAIState inEnterState)
    {
        switch(inEnterState)
        {
            case EOgreAIState.OgreAI_Idle:                  { Enter_Idle(currentAIState); DelegateAIUpdate = new FDelegateAIUpdate(Update_Idle); } break;
            case EOgreAIState.OgreAI_PortalFollow:          { Enter_PortalFollow(currentAIState); DelegateAIUpdate = new FDelegateAIUpdate(Update_PortalFollow); } break;
            case EOgreAIState.OgreAI_LeaderFollow:          { Enter_LeaderFollow(currentAIState); DelegateAIUpdate = new FDelegateAIUpdate(Update_LeaderFollow); } break;
            case EOgreAIState.OgreAI_EnemyFollow:           { Enter_EnemyFollow(currentAIState); DelegateAIUpdate = new FDelegateAIUpdate(Update_EnemyFollow); } break;
            case EOgreAIState.OgreAI_DashApproach:          { Enter_DashApproach(currentAIState); DelegateAIUpdate = new FDelegateAIUpdate(Update_DashApproach); } break;
        }
    }
    
    protected void LeaveState(EOgreAIState inLeaveState, EOgreAIState inNextState)
    {
        switch(inLeaveState)
        {
            case EOgreAIState.OgreAI_Idle:                  { Leave_Idle(inNextState); } break;
            case EOgreAIState.OgreAI_PortalFollow:          { Leave_PortalFollow(inNextState); } break;
            case EOgreAIState.OgreAI_LeaderFollow:          { Leave_LeaderFollow(inNextState); } break;
            case EOgreAIState.OgreAI_EnemyFollow:           { Leave_EnemyFollow(inNextState); } break;
        }
    }
    

}
public class UOgreAI_Remote : UOgreAI_Pawn
{
    protected override void Enter_Idle(EOgreAIState inPreviousState)
    {
        base.Enter_Idle(inPreviousState);
    }

    protected override void Update_Idle()
    {
		if(myPawnForRemote.IsEnableReserveSkill)
		{
        }
    }

    protected override void Enter_PortalFollow(EOgreAIState inPreviousState)
    {
        base.Enter_PortalFollow(inPreviousState);
				
		ARemoteLeaderPawn leaderRemote = myPawnForRemote.LeaderPawnForRemote;
		Vector3 goalTargetPosition = leaderRemote.MoveGoalTargetPosition;

		// 씬 전체에 적이 있는지 검사.
		if(isFirstIngnoreAuto == false && UGameplayInfo.instance.gameplayHUD.IsPlayingCinematic == false && UInGamePlayerData.instance.isBestFindEnemy)
		{
		
		}

		// 적이 없으면 대쉬 초기화
		if(autoFllowEnemy == null)
		{
			isEnableFollowEnemyDash = true;
		}


        // 최종 목표점을 향해 고고.
		navMovement.SetDestination(goalTargetPosition);
    }

    protected override void Update_PortalFollow()
    {
		if(myPawnForRemote.IsEnableReserveSkill)
		{
        }
    }
}

假如你觉得框架太难理解,阅读单个实现代码

//代码类 UOgreAI_Remote.cs |--> : UOgreAI_Pawn
protected override void Update_PortalFollow()
    {
        //条件一
		if(myPawnForRemote.IsEnableReserveSkill)
		{
			// 드래그 및 버프 스킬은 즉시 스킬 사용.
			if(myPawnForRemote.IsDragReserveSkill || 
				myPawnForRemote.MySkillSystemForRemote.CurrentActiveSkill.IsBuffSkill ||
				myPawnForRemote.MySkillSystemForRemote.CurrentActiveSkill.isHealSKill)
			{
				ForceNextAIState = EOgreAIState.OgreAI_SkillDashFollowEnemy;
				return;
			}
		}

        //条件二
		//---- Auto Move Destination
		if(autoDestinationType == EAutoDestination.FarEnemy)
		{
			// 적을 향해 가야 할 경우, 도중에 없어졌다면 다시 포탈포인트를 찾아가도록..
			if(autoFllowEnemy == null || autoFllowEnemy.IsDeath)
			{
				NextAIState = EOgreAIState.OgreAI_Idle;
				return;
			}
		}
		else if(isFirstIngnoreAuto == false)
		{
			// 포탈 포인트를 찾아가는 중에, 적이 발견되었다면 적을 향해 가도록...
			if(UGameplayInfo.instance.gameplayHUD.IsPlayingCinematic == false && UInGamePlayerData.instance.isBestFindEnemy)
			{
				APawn findFollow = UGameplayInfo.instance.FindBestEnemy(myPawnForRemote.ActorPosition);
				if(findFollow != null)
				{
					NextAIState = EOgreAIState.OgreAI_Idle;
					return;
				}
			}
		}
		//----

        base.Update_PortalFollow();
        //条件?? 队长
        // 자동 이동 상태 끝.
		ARemoteLeaderPawn leaderRemote = myPawnForRemote.LeaderPawnForRemote;
		if(leaderRemote.IsCanMoveGoalTarget == false)
        {
            NextAIState = EOgreAIState.OgreAI_Idle;
            return;
        }
        //条件三:搜索敌人
        // 목표점을 향해 진행 하면서 리모트가 가지는 검색 범위에서 적을 찾는다.
		APawn TNewEnemy = FindEnemy();
        if(TNewEnemy)
        {
            //Debug.Log(TNewEnemy.name);
            myPawn.SetEnemy(TNewEnemy);
            NextAIState = EOgreAIState.OgreAI_EnemyFollow;
        }
    }

重点在于,这是一个向“”门口“”,传送门移动的状态 

AI分析首要条件,第一个条件

  • 条件包括:
    • 启用了“保留技能”(IsEnableReserveSkill
    • 当前技能是拖拽类、增益类(Buff)或治疗类(Heal)

移动逻辑,第二条件,处理移动,auto move xxxx

  • 如果目标敌人死亡/消失 → 切回 Idle
  • 如果在前往传送点途中发现新敌人 → 本应切换到追击状态,但这里却设为 OgreAI_Idle可能是个 bug
  • 如果敌人被消失,也会设为 state == Idle

(应为是攻击欲望强的AI,所以Update_Idle 会马上锁敌,所以先让AI Idle, AI还是会自动马上锁敌)

第三个条件 ,巡逻

最后,这是常规巡逻/移动中的敌人检测逻辑

总结:重点在哪里?三个条件

表格

优先级 代码段 说明
⭐⭐⭐ 最高 技能判断段 直接强制切换状态并 return决定性逻辑
⭐⭐ 中 自动目标处理 处理移动中断逻辑,但可能有逻辑错误(Idle 应为 Follow?)
⭐ 低 敌人检测段 常规行为,兜底逻辑

🔍 建议检查点:

  1. OgreAI_Idle 是否写错?
    在“发现敌人”时设为 Idle 不合理,很可能是应设为 OgreAI_EnemyFollow 或 OgreAI_SkillDashFollowEnemy
  2. 变量名拼写autoFllowEnemy → 应为 autoFollowEnemy(多了一个 l
  3. 技能名称一致性isHealSKill → 应为 isHealSkill(大小写错误)

ai认为的重在在第一个,因为第一个判断的优先级最高

但实际在于,前后(状态机)

Enter_Portal ,已经在于 Move 必须先制定目的地

Leave_Portal 要停止MovemntMent

新发哥的项目的思维是对的:EnterIdle和 EnterAttack

关键在于“”开关,“”

可以说,代码的这三个条件都不重要

而,上面这一整段代码都是不重要的

重要,Enter()

重要,OgreAI_SkillDashFollowEnemy //冲向敌人 + 技能

重要, Leave()

这段代码的逻辑就不怎么重要了,重要的模块完成,状态机框架完整,然后,这短不重要的 代码逻辑就随意怎么写都行

重要的代码并没有在这里提供,Sorry

参考:

https://chat.deepseek.com/a/chat/s/deccdd38-ce7a-4914-ba52-f2d6db0f6032

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐