2017-09-25 6 views
0

나는 Unity platformer 게임을 위해 적 AI 이동 시스템을 작업 중입니다. 일정한 기준으로 유휴, 오른쪽으로 이동 또는 왼쪽. 나는 결정을 결정한 사람이 다음 결정과 똑같을지라도 (즉, "오른쪽으로 이동"을 두 번 연속 선택하거나 그 이상의 횟수만큼 선택할 수 있더라도) 적의 결정을 선택할 수 있기를 바랍니다 싶어). 아래 스크립트는 오류가 없지만 게임을 테스트하면 적을 더듬 거리게 만듭니다. 때로는 두 번째로 오른쪽으로 이동 한 다음 왼쪽으로 이동합니다. 내 코드의 고유 한 논리가 다소 정확하다고 느껴지지만 구현 방식에 약간의 작업이 필요합니다. 네가 나에게 줄 수있는 도움에 감사한다.적의 인공 지능 이동 의사 결정

"Start"기능에 "MakeMovementDecision"기능을 넣으면 적을 .07을 왼쪽이나 오른쪽으로 이동하거나 정지 상태로두고 다른 이동 기능을 수행하지 않습니다.

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(); 
    } 

} 

}

+0

? 'FixedUpdate()'를 제거하고'Start()'안에'MakeMovementDecision()'함수를 넣으십시오 ... – 0014

+0

예, 이것을 시도했습니다 (원래의 게시물을 편집하여 이것에 대한 참고 사항을 포함 시켰습니다). 0.07 단위로 왼쪽 또는 오른쪽으로 이동하거나 "유휴"변형을 선택하기 만하면 적이 결코 다시 이동하지 않습니다. 검사관의 x 값을 보지 않으면 적들이 전혀 움직이지 않는다고 인식 할 수 없습니다. – Dalsia

답변

0

당신은 FixedUpdate() 내부의 시간을 계산해야합니다. 귀하의 코드는 다음과 같이 보입니다.

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

저와 함께 해 주셔서 감사합니다. 그러나이 솔루션은 원래 Start() 함수에 MakeMovementDecision()을 넣는 것에 대해 언급 한 내용도 포함되어 있습니다. – Dalsia

+0

@Dalsia 예. 잘못된 길로 통과 한 시간을 계산했다는 것을 깨달았습니다. 수정 된 FixedUpdate() 함수를 사용해보십시오. – 0014

+0

흠, 원래 문제가 다시 발생하는 것 같습니다 (격렬하게 이리저리 움직입니다). 이것이 작동하지 않는 이유를 이해하지 못한다. 이해가되는 것처럼 보이고, 변수를 Time.deltaTime으로 설정해야한다는 점을 잊어 버렸다. 나는이 변화와 함께 성공을 거두지 않고 몇 가지 다른 조치를 시도했다. FixedUpdate를 사용한다면 – Dalsia

2

나는 그것을 알아 냈다. 나는 오버 스크립팅의 희생자였습니다. 이것은 훨씬 간단하고 정확히 내가 원하는 것을 수행합니다. 열쇠는 timeTilNextMovement 변수가 다음 동작이 발생할 때를 결정하는 유일한 변수입니다. 나는 다른 스크립트에서이 간단한 작업을 수행하는 데 너무 많은 변수를 사용하고있었습니다.

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); 
} 

} 왜 당신이 당신의 FixedUpdate (에 MakeMovementDecision) 자체의 결정을 요구하고있다