Unity实战 RTS3D即时战略游戏开发(十) AiController

          大家好,我是Zander,我们接着来开发Rts3D即时战略游戏开发。这节课我们开讲AI的相关部分。在游戏中,游戏AI有行为树,决策树、状态机等可选。我们将使用基本的等待队列,AI的每次决策都会返回一个权重,然后根据这个值来执行相应功能,这里只需要考虑两件事,是否值得做,怎么做。

             首先,在Scripts文件夹下创建一个新的文件夹AI,并创建两个脚本,AiBehaviour  AiController,分别编辑

using UnityEngine;
using System.Collections;

public abstract class AiBehavior : MonoBehaviour {

	public float WeightMultiplier = 1; //可以让设计者设定数值对AI的影响
	public float TimePassed = 0;
	public abstract float GetWeight(); //表示Ai重要度的值,假如有两个AI,建造AI想创建一个指挥部,攻击AI想寻路到敌方,也会坚持有无敌人要攻击,然后根据权重值,来判断优先执行那个AI
	public abstract void Execute();  //执行决策的方法
}

using UnityEngine;
using System.Collections.Generic;

public class AiController : MonoBehaviour {


	public float Confusion = 0.3f; // 添加在AI权重上的随机值
	public float Frequency = 1;    //我们检测的频率

	private float waited = 0;   //两次决策间隔时间的花费
	private List<AiBehavior> Ais = new List<AiBehavior>();

	// Use this for initialization
	void Start () {
		foreach (var ai in GetComponents<AiBehavior>())
			Ais.Add (ai);
	}
	
	// Update is called once per frame
	void Update () {
		waited += Time.deltaTime;
		if (waited < Frequency)  //间隔时间判断
			return;


		float bestAiValue = float.MinValue;
		AiBehavior bestAi = null;

        foreach (var ai in Ais) //判断哪个是需要最先执行的AI
        {
			ai.TimePassed += waited;
			var aiValue = ai.GetWeight() * ai.WeightMultiplier + Random.Range(0, Confusion);
			if (aiValue > bestAiValue)
			{
				bestAiValue = aiValue;
				bestAi = ai;
			}
		}

		bestAi.Execute ();
		waited = 0;
	}
}

好了,现在就实现了AI的控制,现在有两种方法来控制AI,一种是通过决策执行的频率,另一种是通过混淆值。

      现在我们就来创建空闲AI,这个默认AI行为什么都不做,它不依赖权重和行为的暂停,也让我们有机会执行操作,在AI文件夹中创建一个DoNothingAI,如下

using UnityEngine;
using System.Collections;

public class DoNothingAi : AiBehavior {
	public float ReturnWeight = 0.5f;  //方便设计者设置的明确的权重

	public override float GetWeight ()
	{
		return ReturnWeight;
	}

	public override void Execute ()
	{
		Debug.Log ("Doing Nothing");
	}
}

AI需要知道所属玩家名字,以及获得相关玩家的信息,所以回到AiController脚本中,添加一下信息:

public string PlayerName;  //所属玩家的名字
	private PlayerSetupDefinition player;  //所属玩家的详细信息
	public PlayerSetupDefinition Player { get { return player; } }
并在Start函数里面赋值
void Start () {
		foreach (var ai in GetComponents<AiBehavior>()) {
			Ais.Add (ai);
		}
		foreach (var p in RtsManager.Current.Players) {
			if (p.Name == PlayerName) player = p;
		}
		gameObject.AddComponent<AiSupport> ().Player = player;
	}

返回到Unity中,在Manager下创建一个新的空物体命名Player2Ai ,并为其添加脚本,如图
现在就做好了一个空闲的AI,接下来我们将处理建造AI,我们要创建一个AISupport来检测每个AiController的单位数量,编辑如下:

using UnityEngine;
using System.Collections.Generic;

public class AiSupport : MonoBehaviour {

	public List<GameObject> Drones = new List<GameObject>();  //无人机 
	public List<GameObject> CommandBases = new List<GameObject>();//建筑

	public PlayerSetupDefinition Player = null;

	public static AiSupport GetSupport (GameObject go)
	{
		return go.GetComponent<AiSupport>();
	}

	public void Refresh()
	{
		Drones.Clear ();
		CommandBases.Clear ();
		foreach (var u in Player.ActiveUnits) {
			if (u.name.Contains("Drone Unit")) Drones.Add (u);
			if (u.name.Contains("Command Base")) CommandBases.Add(u);
		}
	}
}
每个AIController都需要获得AISupport脚本,然后返回到AIController中,在Start里面添加一下:
	void Start () {
		foreach (var ai in GetComponents<AiBehavior>()) {
			Ais.Add (ai);
		}
		foreach (var p in RtsManager.Current.Players) {
			if (p.Name == PlayerName) player = p;
		}
		gameObject.AddComponent<AiSupport> ().Player = player;
	}
然后在Update里面调用Refesh函数进行刷新,如下

void Update () {
		waited += Time.deltaTime;
		if (waited < Frequency)
			return;

		float bestAiValue = float.MinValue;
		AiBehavior bestAi = null;
		AiSupport.GetSupport (gameObject).Refresh ();
		foreach (var ai in Ais) {
			ai.TimePassed += waited;
			var aiValue = ai.GetWeight() * ai.WeightMultiplier + Random.Range(0, Confusion);
			if (aiValue > bestAiValue)
			{
				bestAiValue = aiValue;
				bestAi = ai;
			}
		}

		bestAi.Execute ();
		waited = 0;
	}
好了,运行如下图,



    好了,这一章就写到这,欢迎大家加入QQ群:280993838  或者关注我的公众号:

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值