教AI去接球?

时间:2014-11-11 13:13:23

标签: c# unity3d artificial-intelligence physics

我有一个游戏,它有效地有两个拨片,我已经设置了它,以便玩家或AI可以控制任何一个划桨。但是,我试图弄清楚如何让我的AI实际上顺利地跑到球后并抓住它,而不是简单地用基本的方式强制它"球的方向" =相反方向AI移动。

为了做到这一点,我试图编写一些代码,让AI预测它将落地的位置,当球进入球场或将要进入时。它进展不顺利。这是我想要实现的图表:

Parabolic arc of ball and prediction points

所以,我一直在研究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);

然而,我觉得我过度简化或遗忘了一些东西。我的计算方法已经过时了,光线并没有出现在它应该的位置,如果有的话。我弄错了什么?

3 个答案:

答案 0 :(得分:1)

假设重力向下,地板处于Y=0,这将简化。可以使用矢量数学扩展任意地板线和重力方向,但是出于您的目的,您应该使用前面提到的两个假设。我也假设这个解释BallPosition是一个Transform对象,但如果不是,数学将是相同的。我也假设球上没有空气摩擦,这会使数学变得更加复杂。

基本上,你需要计算直到球击中地面的时间,然后在那时推断球的X位置。

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

d = vt + at^2/2 solve for t

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

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

......当重力完全向下时,公式应该可以工作,即使球位于其轨迹的向上部分或远离计算机播放器。你可能想要想出一些策略来计算计算机在等待人类击球和设置球的新轨迹时应该做些什么,因为你可能不希望计算机试图奔向人类的一边网。根据你的球员如何击球,你可以预测球击中球后的新速度,然后将这些数据提供给这个公式。

答案 1 :(得分:1)

您需要的只是Kinematics等式。

enter image description here

这些方程式完美地描述了一个运动中的抛射物。因此,您可以使用它们来预测球将落在何处以及具有哪些组件。

这是一个帮助您理解的图表。

enter image description here

答案 2 :(得分:0)

essentialy你在每一步都将重力应用到球上,使其看起来很自然:

球已经准备就绪了

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;

您可能需要调整数字,但如果我记得一切正确,它应该是这样的。希望有意义