unity-game-engine - Unity即时模拟游戏

标签 unity-game-engine

我正在寻找一种模拟游戏直到输赢的方法,以输入蒙特卡罗树搜索算法。

我的游戏是一款回合制、基于图 block 的战术角色扮演游戏,类似于《最终幻想战略版》、《火焰纹章》等。

这个想法是人工智能将执行数千次比赛(或直到达到阈值),直到他们确定最佳的下一步行动。

模拟

每个人工智能和玩家代理都会做出随机有效的移动,直到游戏结束。

为什么要进行 MCTS 模拟?为什么不是最小最大?

出于以下几个原因,我需要尽可能接近真实地模拟游戏:

  1. 将游戏状态编码为低维结构是不可能的,因为大多数 Action 都与碰撞体和射线等 Unity 结构紧密耦合。
  2. 在不了解之前的 Action 的情况下,静态评估前进 X 步的游戏状态即使不是不可能,也是相当困难的。因此,我需要在游戏状态上按顺序执行每个 Action ,以在评估任何内容之前生成下一个游戏状态。

扩展第 2 点: 使用简单的最小最大方法,并通过查看所有玩家的当前健康状况等静态评估游戏状态,虽然有用,但并不准确。 因为并非每项行动都会立即改变健康状况。

示例:

这会在 2 回合内产生更高的(最大伤害):

  1. 移动到玩家前面,攻击 -> 移动到玩家后面,攻击

或者

  • 移动到玩家面前,使用攻击增益 -> 攻击造成 x4 伤害
  • 在这个例子中,最小最大方法永远不会导致第二个选项,即使它在 2 回合内造成更多伤害,因为它对 buff 移动的静态评估导致 0,甚至可能是负值。

    为了选择第二个选项,它需要保留先前操作的知识。 IE。它需要几乎完美地模拟游戏。

    当我们添加其他元素时,例如:舞台陷阱、可破坏的环境和状态效果。使用静态评估几乎变得不可能

    我尝试过的

    时间.timeScale

    这使我能够加快物理和其他交互的速度,这正是我所需要的。 但是 - 这是一个全局属性,因此当人工智能“思考”时,游戏会在几分之一秒内以超快的速度运行。

    提高 NavMesh 代理的速度

    我的所有 Action 都发生在导航网格上 - 因此使这些 Action “即时”的唯一可感知的方法是提高速度。这是有问题的,因为移动速度不够快 - 并且由于速度增加而导致物理问题,有时角色会失去控制并飞出 map 。


    这里是我的(正在积极开发的)游戏的屏幕截图,供引用。

    enter image description here

     问题

    我需要的是一种能够非常快速地“玩”我的游戏的方法。

    我只需要能够在每次 AI 移动之前快速有效地运行这些模拟。

    我很乐意听到有一些经验的人做类似的事情 - 但任何意见将不胜感激!

    谢谢

    最佳答案

    构建核心机制的抽象模型

    为了让某些东西快速运行,我们需要它简单 - 这意味着将游戏剥离到其基 native 制,并代表它(并且仅此而已)。

    那么,这是什么意思呢?好吧,首先我们有一个基于图 block 的世界。一个简单的表示是 Tile 对象的 2D 数组,如下所示:

    /// <summary>
    /// This gameworld is 20x20 tiles
    /// </summary>
    public Tile[,] Tiles = new Tile[20,20];
    

    世界上无法到达的地方 - 例如因为房间不是矩形的或者有非交互式家具挡住了 - 该数组中可以简单地为空值。

    接下来,角色会在这些图 block 上移动。每个角色也有生命值:

    public class Character {
        /// <summary>
        /// The tile this character is on.
        /// </summary>
        private Tile _currentLocation;
    
        /// <summary>
        /// The tile this character is on.
        /// </summary>
        public Tile CurrentLocation{
            get{
                return _currentLocation;
            }
            set{
                if(_currentLocation != null)
                {
                    _currentLocation.Occupier = null;
                }
                _currentLocation = value;
                _currentLocation.Occupier = this;
            }
        }
    
        /// <summary>
        /// Its HP
        /// </summary>
        public float Hitpoints = 100f;
    
        public void SetLocation(Tile newLocation){
            CurrentLocation = newLocation;
        }
    
    }
    

    我们可以制作更专业的角色变体,例如具有特殊属性的 class Hero : Character,但我们暂时忽略它。

    上面的 CurrentLocation 也会更新图 block - 为了提高速度,它有助于了解哪个角色站在特定图 block 上,因此这里有一个图 block 类:

    public class Tile{
        public Character Occupier;
        public int X;
        public int Y;
    }
    

    好吧,让我们来举例一个世界 - 为了简单起见,这个世界是矩形的,因此所有图 block 都已填充:

    for(var x=0;x<20;x++){
        for(var y=0;y<20;y++){
            Tiles[x,y] = new Tile(){X = x, Y = y};
        }
    }
    

    我们将在特定位置拍下 2 个角色:

    var badGuy = new Character();
    badGuy.CurrentLocation = Tiles[3,4];
    
    var hero = new Character();
    hero.CurrentLocation = Tiles[9,9];
    

    从这一点来看,我们有了一个非常简单的世界模型。例如,我们可以通过检查Tiles[x,y].Occupier来询问它在tile x,y处有什么。从这里开始,您开始将机制添加到模型中 - 例如,这可能是某种 aTile.Attack(AttackType.IceBlast) 方法:

    public void Attack(AttackType type, Character attackedBy){
        // impacts type.Range tiles around this one, dealing damage to each Occupier.
        // Get a neighbouring tile via e.g. yourReferenceToTheTilesArray[X+1, Y].
    }
    

    重要的是,游戏随后被修改为仅反射(reflect)模型 - 这样模型总是准确的,因为它驱动游戏并且是伤害量等的真正来源。您可以向其中添加事件,因此当调用上述 Attack 方法时,会触发一些 OnAttack 处理程序,然后在整个游戏运行时触发动画。

    这样的模型可以作为独立的 C# 程序运行,完全在 Unity 之外运行,能够每秒生成数百万圈以用于测试或 AI 训练目的。

    关于unity-game-engine - Unity即时模拟游戏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60155133/

    相关文章:

    android - 如何在屏幕上放置控件?

    unity-game-engine - unity 设置 Google Play 服务时出错

    ios - 使用 Unity3D 按钮执行 xcode 函数?

    c# - "unknown status code: 17042 Invalid format"使用验证码时出错

    c# - 如何在 Unity 中每次更新时插入一个获得新位置的相机?

    javascript - 使用Unityscript读取鼠标点击Input.GetMouseDown

    c# - 团结 : Diagonal movement not corresponding to correct key inputs

    ios - Unity 应用程序启动时使用 Vungle 的 NSInvalidArgumentException

    android - 如何在android Unity应用程序中禁用android运行时位置权限提示

    unity-game-engine - Unity 变换.lookAt