AI决策算法 之 GOAP (三)

源码地址:http://pan.baidu.com/s/1dFwzmfB


这篇我们使用上篇文章写的GOAP框架来完成一个实例:


实例内容:

AI有10HP, 需要去站岗,站岗完成扣5HP

当HP<=5必须去补充HP,找到HP球补充HP,每个HP球补充5HP




根据GOAP框架逻辑推断出需要:AI数据提供者,站岗Action,补充HPAction,HP点脚本,站岗点脚本, AI属性脚本


主要脚本:


AI数据提供者

public class Worker : MonoBehaviour,IGoap{

    private PropertyComponent property;    //属性脚本
    public float moveSpeed = 3;            //移动速度

    void Start()
    {
        property = GetComponent<PropertyComponent>();
    }

    public System.Collections.Generic.HashSet<System.Collections.Generic.KeyValuePair<string, object>> GetState()
    {
        HashSet<KeyValuePair<string, object>> state = new HashSet<KeyValuePair<string, object>>();
        //当前状态HP是否足够
        state.Add(new KeyValuePair<string, object>("EnoughHP", property.HP > 5));
        return state;
    }

    public System.Collections.Generic.HashSet<System.Collections.Generic.KeyValuePair<string, object>> CreateGoalState()
    {
        HashSet<KeyValuePair<string, object>> goal = new HashSet<KeyValuePair<string, object>>();
        //站岗完成目标
        goal.Add(new KeyValuePair<string, object>("SentryComplete", true));
        return goal;
    }

    public void PlanFailed(System.Collections.Generic.HashSet<System.Collections.Generic.KeyValuePair<string, object>> failedGoal)
    {
        
    }

    public void PlanFound(System.Collections.Generic.HashSet<System.Collections.Generic.KeyValuePair<string, object>> goal, System.Collections.Generic.Queue<Action> actions)
    {
        
    }

    public void ActionsFinished()
    {
        Debug.LogError("FinishedSentry");
    }

    public void PlanAborted(Action aborterAction)
    {
        
    }

    public bool MoveAgent(Action tagetAction)
    {
        //移动
        float step = moveSpeed * Time.deltaTime;
        gameObject.transform.position = Vector3.MoveTowards(gameObject.transform.position, tagetAction.target.transform.position, step);

        if (gameObject.transform.position.Equals(tagetAction.target.transform.position))
        {
            tagetAction.IsInRange = true;
            return true;
        }
        else
            return false;
    }
}

站岗Action

public class SentryAction : Action {

    private SentryComponent targetSentry;      //站岗目标脚本
    private float SentryTimer = 0;             //站岗计时
    public float SentryTime = 3;
    bool isDone = false;                       //是否完成

    public SentryAction()
    {
        AddPrecondition("EnoughHP", true);  //前置条件:必须HP足够
        AddEffect("SentryComplete", true);  //完成效果:站岗完成
    }


    public override void Reset()
    {
        targetSentry = null;
        SentryTimer = 0;
        isDone = false;
    }

    public override bool IsDone()
    {
        return isDone;
    }


    public override bool CheckProcedualPrecondition(GameObject agent)
    {
        //得到最近的站岗目标
        SentryComponent[] sentryComponents = GameObject.FindObjectsOfType<SentryComponent>();


        SentryComponent temp = null;

        foreach(var v in sentryComponents)
        {
            if (temp == null)
            {
                temp = v;
                continue;
            }

            if (Vector3.Distance(agent.transform.position, v.transform.position) < Vector3.Distance(agent.transform.position, temp.transform.position))
                temp = v;
        }

        targetSentry = temp;
        target = temp.gameObject;

        return temp != null;
    }

    public override bool Perform(GameObject agent)
    {
        //站岗执行
        SentryTimer += Time.deltaTime;
        if(SentryTimer > SentryTime)
        {
            //站岗完成消耗HP
            agent.GetComponent<PropertyComponent>().HP -= 5;
            isDone = true;
        }
        return true;
    }

    public override bool RequiresInRange()
    {
        return true;
    }
}

补充HPAction

public class GetHPAction : Action {

    private HPPointComponent targetHPPoint;     //HP点目标脚本
    bool isDone = false;

    void Start()
    {
        AddEffect("EnoughHP", true);   //完成效果:HP补充到足够
    }

    public override void Reset()
    {
        targetHPPoint = null;
        isDone = false;
    }

    public override bool IsDone()
    {
        return isDone;
    }

    public override bool CheckProcedualPrecondition(GameObject agent)
    {
        HPPointComponent[] tempComponents = GameObject.FindObjectsOfType<HPPointComponent>();


        HPPointComponent temp = null;

        foreach (var v in tempComponents)
        {
            if (temp == null)
            {
                temp = v;
                continue;
            }

            if (Vector3.Distance(agent.transform.position, v.transform.position) < Vector3.Distance(agent.transform.position, temp.transform.position))
                temp = v;
        }

        targetHPPoint = temp;
        target = temp.gameObject;

        return temp != null;
    }

    public override bool Perform(GameObject agent)
    {
        DestroyImmediate(targetHPPoint.gameObject);
        isDone = true;
        agent.GetComponent<PropertyComponent>().HP += 5;
        return true;
    }

    public override bool RequiresInRange()
    {
        return true;
    }

}




  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值