Unity3D学习笔记(9) 坦克对战游戏 AI 设计

商店中的资源Tanks! Tutorial是一个完整的两个玩家进行对战的坦克游戏。预制、地图很优美、规范。遵循“感知-思考-行为”模型,使其中的红色坦克(Player2)具有智能跟踪Player1的功能,并在适当的时候射击Player1。

NavMesh是unity提供的导航寻路功能。给对象加上Nav Mesh Agent组件,在Navigation窗口给地图中的各个对象设置walkable或者not walkable等属性,然后bake烘培,就得到描述了游戏对象可行走的表面的数据结构Navigation Mesh,可通过这些三角网格计算其中任意两点之间的最短路径用于游戏对象的导航,作为“感知-思考-行为”模型中的“感知”
这里写图片描述
TankAI类作为“感知-思考-行为”模型中的“思考”。跟踪速度和角速度随距离发生变化,距离越近速度越慢角速度越快。射线检测玩家在正前方时发射子弹,使用射线使AI坦克不会频繁发射子弹,行为更自然。

using System;
using UnityEngine;
namespace Complete
{
    [RequireComponent(typeof (UnityEngine.AI.NavMeshAgent))]
    public class TankAI : MonoBehaviour
    {
        public UnityEngine.AI.NavMeshAgent agent { get; private set; }
        public Transform target;
        public float angle = 60f;

        private float countTime = 0;
        private void Start()
        {
            agent = GetComponentInChildren<UnityEngine.AI.NavMeshAgent>();
            agent.updateRotation = true;
            agent.updatePosition = true;
        }

        private void Update()
        {
            // 距离与40的比例
            float ratio = (target.transform.position - transform.position).magnitude / 40;
            // 导航速度与距离线性正相关
            agent.speed = 2f * ratio + 1.5f;
            // 导航角速度与距离线性负相关
            agent.angularSpeed = 120f - 60f * ratio;
            if (target != null)
                agent.SetDestination(target.position);
            // 玩家在正前方时,以0.2秒一次的频率发射子弹
            if (countTime >= 0.2f) {
                Ray ray = new Ray (transform.position, transform.forward);
                RaycastHit hit;  
                if (Physics.Raycast (ray, out hit, Mathf.Infinity)) { 
                    if (hit.collider.gameObject.tag == "Player")
                        GetComponent<TankShooting> ().MyShoot();
                }
                countTime = 0;
            }
            countTime += Time.deltaTime;
        }
    }
}

TankManager类,如果对象是AI,不激活TankMovement组件,使AI坦克不能被用户控制。

public class TankManager
{
    ...
    public bool AI;
    ...
    public void EnableControl ()
    {
        if (!AI)
            m_Movement.enabled = true;
        else
            m_Instance.GetComponent<TankAI> ().enabled = true;
        ...
    }
    ...
}

GameManager类,设置Player2坦克的TankManager的AI为true,TankAI的导航目标target为Player1的位置。

public class GameManager : MonoBehaviour
{
    ...
    private void SpawnAllTanks()
    {
        ...
        m_Tanks [0].AI = false;
        m_Tanks [1].AI = true;
        m_Tanks [1].m_Instance.GetComponent<TankAI> ().target = m_Tanks [0].m_Instance.transform;
        m_Tanks [1].m_Instance.GetComponent<TankAI> ().enabled = false;
    }
    ...
}

资源Tanks! Tutorial中有大量障碍物,干扰了“感知-思考-行为”模型中的“行动”,限制了agent发现玩家位置,给玩家足够的反应时间,地面的沟渠和子弹的重力造成了角度偏差,即使玩家在正前方也不一定会被击中,干扰了信息的准确性,使得玩家不会轻易被打死,使游戏更具可玩性。
这里写图片描述

猜你喜欢

转载自blog.csdn.net/Z_J_Q_/article/details/80732809