【问题标题】:Teach an AI to catch a ball?教人工智能接球?
【发布时间】:2014-11-11 13:13:23
【问题描述】:

我有一个游戏,其中实际上有两个桨,我已经对其进行了设置,以便玩家或 AI 可以控制任一桨。但是,我试图弄清楚如何让我的 AI 真正平稳地追球并接住它,而不是简单地用基本的“球的方向”= AI 移动的相反方向来强制它。

为了做到这一点,我正在尝试编写一些代码,让 AI 能够预测它会降落的位置、球何时在球场上或将在球场上。事情进展不顺利。这是我想要实现的图表:

所以,我一直在研究 Unity3D 并想出了这个:

Vector3 BallMinder = BallPosition.gameObject.rigidbody.velocity;
float BallX = BallMinder.x;
float BallY = BallMinder.y * Time.deltaTime;
float GroundHitPointX = (BallY + BallX);

Vector3 BallImpactPoint = new Vector3 (GroundHitPointX, 0, 0);
Debug.Log (BallImpactPoint);
Debug.DrawRay (BallImpactPoint, Vector3.up, Color.green);

但是,我觉得我把它过分简化了或者忘记了一些东西。我的计算很差,而且光线没有出现在它应该出现的地方,如果它出现的话。我做错了什么?

【问题讨论】:

  • 我认为你可以很简单地做到这一点。你拿球的 X 位置并使计算机桨以他的最大速度移动到那个位置。对于计算机桨应在球触地的位置等待的解决方案,您需要计算下拉点(就像您所做的那样),但显然它的计算错误嘿:)
  • 这就是我以前做的事情,但它从来没有让人觉得很人性化——我希望 AI 至少表现得像另一个球员一样,并尝试接球而不是朝它移动并获得 50%时间。

标签: c# unity3d artificial-intelligence physics


【解决方案1】:

您只需要Kinematics 方程。

这些方程完美地描述了运动中的弹丸。因此,您可以使用它们来预测球将落在何处以及使用哪些组件。

这里有一个图表可以帮助你理解。

【讨论】:

  • 请记住,游戏的物理引擎可能不如现实世界强大,事实上这可能不是一个合适的预测对象实际最终位置的指标。
  • @Servy 我认为 OP 会处理他自己的物理,例如向球添加力,然后自己控制加速度。我倾向于依赖我的物理而不是 Unity3d 给我的东西;我只将它用于图形渲染。但是,如果 OP 严重依赖引擎的物理,您确实提出了一个很好的观点。
【解决方案2】:

这将通过假设重力向下而简化,并且地板位于Y=0。它可以使用矢量数学来扩展任意地板线和重力方向,但出于您的目的,您应该可以使用上述两个假设。对于这个解释,我还假设 BallPositionTransform 对象,但如果不是,数学将是相同的。我还假设球上没有空气摩擦,这会使数学变得相当复杂。

本质上,您需要计算直到球落地的时间,然后推断当时球的 X 位置。

指示加速物体运动的经典公式是d = vt + at^2 / 2,其中v 是当前速度,a 是加速度,t 是经过的时间量。为了计算出影响的时间,我们只需求解t

要确定球何时落地,您需要设置d = BallPosition.position.y * -1a = Physics.gravity.yv = BallPosition.rigidbody.velocity.y。这将为我们提供距离撞击的秒数。

由于假设重力完全向下并且没有其他力作用在球上,我们可以知道球在撞击时的 X 位置是BallPosition.position.x + BallPosition.rigidbody.velocity.x * impactTime。这将是您的计算机播放器应该移动的 X 位置。

...只要重力完全向下,即使球处于其轨迹的向上部分或远离您的计算机玩家,该公式也应该起作用。你可能想想出一些策略,让计算机在等待人类击球并设置球的新轨迹时应该做什么,因为你可能不希望计算机试图跑向人类一侧的网。根据您的球员击球的方式,您可能能够预测人类击球后球的新速度,然后将该数据输入到这个公式中。

【讨论】:

    【解决方案3】:

    基本上你在每一步都对球施加重力,使其看起来很自然,如下所示:

    球在你的位置准备好被夺冠

    ball.x = 20;
    ball.y = 10;
    xVelocity = 0; 
    yVelocity = 0;
    gravity = 0.1;
    

    你扔球
    当你投掷球时,你将 xVelocity 设置为一个常数,假设 1 和 yVelocity 为 5。所以:

    xVelocity = 1;
    yVelocity = 5;
    ball.x+=xVelocity;
    ball.y+=yVelocity; //to start the ball moving
    

    现在在游戏循环中,您可以像这样计算球的位置:

    tick
    {
        if(ball.y > 10)  //if the ball is off the ground (i asume 10 is ground) 
        {
            ball.x+=xVelocity;
            ball.y+=yVelocity;
            yVelocity-=gravity;
        }
    }
    

    有了这个,球现在应该以完美的弧线飞行以计算着陆区,您可以简单地用虚拟数字再次做同样的事情

    while(dummyBall.y > 10)
    {
        dummyBall.x+=xVelocity;
        dummyBall.y+=yVelocity;
        yVelocity-=gravity;
    }
    landingPosX = dummyBall.x;
    

    您可能需要调整数字,但如果我没记错的话,它应该会像这样工作。希望有意义

    【讨论】:

    • 所以我很接近但没有雪茄。球已经通过物理和重力自行移动,但我试图弄清楚如何将重力应用于着陆区计算。我会尽可能地尝试这个。
    • 在有这么多好答案的情况下选择一个答案有点困难。我到了一半,并用它来帮助修复其余部分。或者至少是其中的一部分。它应该得到认可标记。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-10
    相关资源
    最近更新 更多