首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >敌方AI移动决策

敌方AI移动决策
EN

Stack Overflow用户
提问于 2017-09-26 06:34:05
回答 2查看 1.5K关注 0票数 0

我正在为Unity platformer游戏开发一个敌人AI移动系统,它将允许敌人在不变的基础上做出三个决定之一:空闲,向右移动,或向左移动。我希望敌人能够选择这些决定中的任何一个,即使它刚刚选择的决定将与它的下一个决定相同(即它可以连续两次选择“向右移动”,或者想要多少次就选择多少次)。下面的脚本没有错误,但当我测试游戏时,它会导致我的敌人结巴。有时它会在瞬间向右移动,然后向左移动,等等。我觉得我的代码的内在逻辑有点正确,但它的实现方式需要一些工作。感谢你能给我的任何帮助。

顺便说一句,如果我把"MakeMovementDecision“函数放在"Start”函数中,敌人会将.07向左或向右移动,或者只是静止不动,而永远不会执行另一个移动函数。

代码语言:javascript
复制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AIMovement : MonoBehaviour {

// References the enemy's Rigidbody2D component
private Rigidbody2D enemyRigidbody;

// Sets the enemy's movement speed
[SerializeField]
private int movementSpeed;

// Checks if the enemy is moving (to be used with animations)
private bool isMoving;

// The direction in which the enemy will move
private Vector2 directionToMove;

// The random decision (0, 1 or 2) that represents which movement function the enemy will perform
private int decisionValue;

// The time remaining before the enemy chooses which movement function to perform again
private float timeTilNextDecision;

// The random float that will be used to determine for how long the enemy remains idle
private float idleTime;

// The random float that will be used to determine for how long the enemy moves left or right
private float moveTime;

// Use this for initialization
void Start () {

    // Accesses the enemy's Rigidbody2D component
    enemyRigidbody = GetComponent<Rigidbody2D>();
}

void FixedUpdate () {

    MakeMovementDecision();
}

/// <summary>
/// Generates the decision for which type of movement the enemy will perform
/// </summary>
private void MakeMovementDecision ()
{
    // Chooses a value upon which the movement decision will be based
    decisionValue = Random.Range(0, 3);

    switch (decisionValue)
    {
        // Keeps the enemy standing still
        case 0:
            Idle();
            break;

        // Moves the enemy to the right
        case 1:
            MoveRight();
            break;

        // Moves the enemy to the left
        case 2:
            MoveLeft();
            break;
    }
}

/// <summary>
/// Causes the enemy to stand still with idle animations 
/// </summary>
private void Idle ()
{
    // Sets the idle stance duration
    idleTime = Random.Range(5.0f, 10.0f);

    // Calculates the time until the enemy may decide to change its movement
    timeTilNextDecision = idleTime - Time.deltaTime;

    // Sets the movement bool to false to play the idle animations
    isMoving = false;

    // Stops the enemy's movement
    enemyRigidbody.velocity = Vector2.zero;

    // Checks if the enemy should make a decision on its next movement
    if (timeTilNextDecision < 0)
    {
        MakeMovementDecision();
    }

}

private void MoveRight()
{
    moveTime = Random.Range(2.0f, 5.01f);
    timeTilNextDecision = moveTime - Time.deltaTime;
    isMoving = true;
    directionToMove = Vector2.right;
    transform.Translate(directionToMove * (movementSpeed * Time.deltaTime));

    if (timeTilNextDecision < 0)
    {
        MakeMovementDecision();
    }

}

private void MoveLeft()
{
    moveTime = Random.Range(2.0f, 5.01f);
    timeTilNextDecision = moveTime - Time.deltaTime;
    isMoving = true;
    directionToMove = Vector2.left;
    transform.Translate(directionToMove * (movementSpeed * Time.deltaTime));

    if (timeTilNextDecision < 0)
    {
        MakeMovementDecision();
    }

}

}

EN

回答 2

Stack Overflow用户

发布于 2017-09-26 09:11:26

我想通了。我是一个过度脚本的受害者。这要简单得多,而且做的正是我想要的。关键是timeTilNextMovement变量是决定下一次移动何时发生的唯一变量。在我的另一个脚本中,我使用了太多的变量来完成这个简单的任务。

代码语言:javascript
复制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyMovement : MonoBehaviour {

private Rigidbody2D enemyRigidbody;

private int movementValue;

private float timeTilNextMovement;

private bool isMoving;

[SerializeField]
private float movementSpeed;

private Vector2 moveRight;
private Vector2 moveLeft;

// Use this for initialization
void Start () {

    enemyRigidbody = GetComponent<Rigidbody2D>();
    moveRight = Vector2.right;
    moveLeft = Vector2.left;

    MakeMovementDecision();
}

// Update is called once per frame
void FixedUpdate () {

    timeTilNextMovement -= Time.fixedDeltaTime;

    switch (movementValue)
    {
        case 0:
            Debug.Log("IDLE"); 
            isMoving = false;
            enemyRigidbody.velocity = Vector2.zero;
            break;
        case 1:
            Debug.Log("RIGHT");
            isMoving = true;
            transform.Translate(moveRight * (movementSpeed * Time.fixedDeltaTime));
            break;
        case 2:
            Debug.Log("LEFT");
            isMoving = true;
            transform.Translate(moveLeft * (movementSpeed * Time.fixedDeltaTime));
            break;
    }

    if (timeTilNextMovement < 0)
    {
        MakeMovementDecision();
    }

}

private void MakeMovementDecision()
{
    movementValue = Random.Range(0, 3);
    timeTilNextMovement = Random.Range(2.0f, 5.0f);
}

}

票数 2
EN

Stack Overflow用户

发布于 2017-09-26 06:52:59

您需要计算FixedUpdate()内部的时间。你的代码应该看起来像这样;

代码语言:javascript
复制
void FixedUpdate () {
    // Calculates the time until the enemy may decide to change its movement
    moveTime += Time.deltaTime;
    timeTilNextDecision = idleTime - moveTime;

    if (timeTilNextDecision < 0)
    {
        MakeMovementDecision();
    }
}

/// <summary>
/// Generates the decision for which type of movement the enemy will perform
/// </summary>
private void MakeMovementDecision ()
{
    // Chooses a value upon which the movement decision will be based
    decisionValue = Random.Range(0, 3);

    switch (decisionValue)
    {
        // Keeps the enemy standing still
        case 0:
            Idle();
            break;

        // Moves the enemy to the right
        case 1:
            MoveRight();
            break;

        // Moves the enemy to the left
        case 2:
            MoveLeft();
            break;
    }
}

/// <summary>
/// Causes the enemy to stand still with idle animations 
/// </summary>
private void Idle ()
{

    // Sets the idle stance duration
    idleTime = Random.Range(5.0f, 10.0f);
    // Sets the movement bool to false to play the idle animations
    isMoving = false;

    // Stops the enemy's movement
    enemyRigidbody.velocity = Vector2.zero;

    // Checks if the enemy should make a decision on its next movement


}

private void MoveRight()
{
    moveTime = Random.Range(2.0f, 5.01f);
    isMoving = true;
    directionToMove = Vector2.right;
    transform.Translate(directionToMove * (movementSpeed * Time.deltaTime));
}

private void MoveLeft()
{
    moveTime = Random.Range(2.0f, 5.01f);
    isMoving = true;
    directionToMove = Vector2.left;
    transform.Translate(directionToMove * (movementSpeed * Time.deltaTime));
}

编辑:我发现你计算时间的方式是错误的。Time.deltaTime是一个固定参数,它不返回经过的时间。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46415170

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档