Тема: AI в Unity3D
Показать сообщение отдельно
Старый 05.11.2011, 15:19   #8
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений
(для 5,323 пользователей)
Ответ: AI в Unity3D

Немного сложнее
using UnityEngine;

public class 
Enemy : MonoBehaviour
{
    
// скорость ходьбы и скорость поворота в секунду
    
public float moveSpeed = 2;
    public 
float turnSpeed = 90;

    
// угол области видимости
    
public float visibleAreaAngle = 120;
    
// дистанция видимости
    
public float visibleAreaDistance = 15;

    private 
CharacterController _controller;
    private 
Transform _thisTransform;
    private 
Transform _playerTransform;

    private 
bool _isPursuit = false;

    public 
void Start()
    {
        
// Получаем контроллер
        
_controller = GetComponent<CharacterController>();

        
// Получаем компонент трансформации объекта, к которому привязан данный компонент
        
_thisTransform = transform;

        
// Получаем компонент трансформации игрока
        
Player player = (Player)FindObjectOfType(typeof(Player));
        
_playerTransform = player.transform;
    }

    
// Все что связано с физикой выполняем в FixedUpdate
    
public void FixedUpdate()
    {
        
// направление на игрока
        
Vector3 playerDirection = (_playerTransform.position - _thisTransform.position).normalized;

        
// если не преследуем
        
if (!_isPursuit)
        {
            
// переменная для результата попадания
            
RaycastHit hit;
            
// луч
            
Ray ray = new Ray(transform.position, playerDirection);

            
// тест попадания луча
            
if (Physics.Raycast(ray, out hit))
            {
                
// рисуем луч для дебага
                
Debug.DrawLine(ray.origin, hit.point, Color.yellow);

                
// если попали в игрока, то начинаем преследование
                
if (hit.collider.GetComponent<Player>() != null)
                {
                    
// половина угла видимости
                    
var halfAngle = visibleAreaAngle / 2;

                    
// если угол между направлением врага и направлением на игрока входит в область видимости
                    // то начинаем преследование
                    
if (Vector3.Angle(transform.forward, playerDirection) <= halfAngle)
                    {
                        
_isPursuit = true;
                    }

                }
            }

            return;
        }



        
// угол поворота на игрока
        
float angle = Vector3.Angle(_thisTransform.forward, playerDirection);

        
// максимальный угол поворота на текущем кадре
        
float maxAngle = turnSpeed * Time.deltaTime;

        
// Вычисляем прямой поворот на игрока
        
var playerDir = _playerTransform.position - _thisTransform.position;
        
playerDir.y = 0;
        var 
rot = Quaternion.LookRotation(playerDir);

        
// поворачиваем врага на игрока с учетом скорости поворота
        
if (maxAngle < angle)
        {
            
_thisTransform.rotation = Quaternion.Slerp(_thisTransform.rotation, rot, maxAngle / angle);
        }
        else
        {
            
_thisTransform.rotation = rot;
        }

        
// если дистанция до игрока больше трех метров
        
if (Vector3.Distance(_playerTransform.position, _thisTransform.position) > 3.0f)
        {
            
// двигаемся к игроку
            
_controller.Move(_thisTransform.forward * moveSpeed * Time.deltaTime);
        }
        else 
// если меньше или равна трем метрам
        
{
            
// здесь например стреляем в игрока
        
}

        
// гравитация
        
_controller.Move(Vector3.down * 10.0f * Time.deltaTime);
    }


    
// рисуем область видимости
    
public void OnDrawGizmos()
    {
        var 
halfAngle = visibleAreaAngle / 2;
        var 
startDir = Quaternion.AngleAxis(-halfAngle, Vector3.up) * transform.forward;

        var 
count = Mathf.Max(1, (int)visibleAreaAngle / 5);

        var 
stepRotation = Quaternion.AngleAxis(visibleAreaAngle / count, Vector3.up);

        
Gizmos.color = new Color(0.5f, 0.5f, 0, 0.5f);

        
Gizmos.DrawLine(transform.position, transform.position + startDir * visibleAreaDistance);

        var 
currentVector = startDir;

        for (
int i = 1; i <= count; i++)
        {
            var 
prevPos = transform.position + currentVector * visibleAreaDistance;
            
currentVector = stepRotation * currentVector;
            var 
curPos = transform.position + currentVector * visibleAreaDistance;
            
Gizmos.DrawLine(transform.position, curPos);
            
Gizmos.DrawLine(prevPos, curPos);
        }
    }
} 
Чтобы снизить немного нагрузку - надо тестировать видимость не каждый апдейт физики.
Миниатюры
Нажмите на изображение для увеличения
Название: 97eca6cd6fc0830fe4099c8e48565da1.png
Просмотров: 1991
Размер:	232.5 Кб
ID:	15322  
__________________
Blitz3d to Unity Wiki
(Offline)
 
Ответить с цитированием