如何使AI仅移动到场景中活动的对象(Unity Engine)

时间:2014-04-22 03:56:53

标签: loops artificial-intelligence scene

嗨,我正在开发一个餐厅策略游戏,顾客进来买东西。我已经创建了一个Transform类型对象数组,它们充当了路点,我希望客户只能朝着场景中活跃的点移动。我正在考虑做的是使用for循环或while循环,其中对于每个未激活的路点,移动到下一个路点并检查它是否有效。我不确定这是否是正确的方法,因为我似乎无法让它工作。无论如何我真的可以使用一些帮助。谢谢!

var waypoints : Transform[];
var waypoint : Transform;
var currentWaypoint : int;
var agent : NavMeshAgent;
var script1 : SlideOutMenu;

function Awake(){
agent = gameObject.GetComponent.<NavMeshAgent>();
agent.speed = Random.Range(2.5, 5);
script1 = gameObject.Find("GUIElements").GetComponent(SlideOutMenu);
}

function Update () {
waypoint = waypoints[currentWaypoint];
agent.SetDestination(waypoint.position);
}

function OnTriggerExit(other : Collider){
if (other.name == "0 Start"){
    currentWaypoint = Random.Range(1, 2);
    }
}

function OnTriggerEnter (other : Collider) {
EatMeal();
if (other.name == "0 Start"){
currentWaypoint++;
}
    if (other.name == "1"){
    script1.globalMoney += 50;
    WaitForSoda();
    }
        if (other.name == "2"){
        script1.globalMoney += 100;
        WaitForFood();
        }
    if (other.name == "4 End"){
    Destroy(gameObject);
    }
}

function WaitForSoda(){
yield WaitForSeconds(2);
currentWaypoint++;
}

function WaitForFood(){
yield WaitForSeconds(5);
currentWaypoint = Random.Range(5, 12);
}

function EatMeal(){
if (currentWaypoint >= 4 && currentWaypoint <= 12){
yield WaitForSeconds(Random.Range(5, 12));
currentWaypoint = 4;
}
}

1 个答案:

答案 0 :(得分:1)

当你发现自己采取“每次我这样做,我将遍历所有对象并检查它们是否活跃......”的解决方案时,它通常是游戏编程中的Bad Idea™。我说这是某人曾几何时在100000x100000网格上犯了这个错误。对这类问题的最佳解决方案通常是颠倒问题。每个航路点不应询问每个航点是否有效,而应询问它是属于有效还是非有效集。我建议至少有两个列表:activeWaypointsinactiveWaypoints。如果您需要它(有时候也可以),masterWaypoints可以用作通用集。

现在很简单:每个航点都知道它是活动的还是非活动的,当它激活时它会将自己从非活动列表中移除并将其自身添加到活动列表中,反之亦然。创建它时,您必须默认选择它是活动的还是非活动的(或者提供一个默认创建它的选项),但这是一个很小的设计问题。当它被销毁时,只需从目前的任何一个中移除它,如果它存在,则将其移除masterWaypoints

这样做的好处是,您只需在更改状态时更新内容,而不是每帧检查一次(或更糟糕的是:每帧检查每个NPC代理)。

从那里开始,现在您要检查activeWaypoints。如果您需要为每个客户进一步过滤,那会更加困难。在这种情况下,迭代所有activeWaypoints并忽略所有不符合标准的航路点是可以接受的。虽然取决于需要进行多少过滤,但我可能会考虑使用自己的逻辑来编写某种WaypointManager基于活动/非活动/红色/蓝色/制作果酱/疯狂诱导的过滤通过getWaypointsMeetingCriteria(list of filters)访问的/ etc。这可以使用地图,列表和迭代过滤的混合,具体取决于您为每个标记决定的内容。

这里有一个障碍,因为航点可能是有序的,这意味着当航点从非活动状态或活动状态移动时,他们需要保持其顺序,但是有很多方法可以快速插入和/或构建排序清单。