Tôi đang làm một trò chơi trong đó người chơi AI ném bóng.
Trong ảnh chụp màn hình, bạn có thể thấy đấu trường được ngăn cách bởi một mạng ở giữa. Mỗi bên của đấu trường có 6 người chơi thuộc một trong 2 đội. Ngay bây giờ, một trong những cầu thủ ở phía bên phải có bóng (cầu thủ phía trên bên phải). Anh ấy sẽ ném bóng sang bên trái.
Theo mã của tôi, quả bóng phải luôn hạ cánh trên cùng một vị trí, bởi vì người chơi luôn áp dụng cùng một lực cho quả bóng. Tuy nhiên, tôi đã nhận thấy rằng quả bóng không phải lúc nào cũng hạ cánh ở cùng một nơi. Tôi đã đánh dấu nơi tôi đã nhìn thấy đất bóng với một vài vòng tròn màu đỏ.
Thật thú vị, trên PC chính của tôi, quả bóng hầu như luôn rơi vào vòng tròn bên phải nhất. Nó hiếm khi rơi vào các vòng tròn khác, mặc dù điều đó xảy ra. Tuy nhiên, trên 3 PC khác, tôi đã thử trò chơi này, quả bóng thường rơi vào chân của cầu thủ trên cùng bên trái, đôi khi trên đầu hoặc phía sau anh ta, nhưng không bao giờ ở vòng tròn bên phải nhất (trước mặt anh ta ).
Trò chơi của tôi phụ thuộc rất nhiều vào vật lý. AI có nhiệm vụ tính toán cách ném bóng để đưa nó hạ cánh xuống một vị trí rất cụ thể, cũng như đoán xem nó sẽ hạ cánh ở đâu tùy thuộc vào vị trí và chuyển động của quả bóng. Nếu vật lý không hoạt động nhất quán trên tất cả các máy mọi lúc, làm thế nào AI có thể tính toán chính xác tất cả những điều này?
Đây là mã phụ trách ném:
private IEnumerator Serve()
{
var ball = GameObject.Find("Ball").GetComponent<BallController>();
if (ball.ServingPlayer != this)
yield break;
yield return new WaitForSeconds(3);
Vector3 shootDirection = transform.forward.normalized;
var q = Quaternion.AngleAxis(-45, transform.right);
ball.RigidBody.AddForce(q * shootDirection * 20f, ForceMode.VelocityChange);
}
Như bạn có thể thấy, quả bóng luôn được ném "về phía trước" (hướng về phía lưới) ở góc lên 45 °, sử dụng một vectơ chuẩn hóa và tốc độ không đổi ( 20f
).
Trước mỗi lần ném, vị trí của các cầu thủ được đặt lại về cùng một vị trí (và xoay) mà họ nhìn thấy trên ảnh chụp màn hình.
player.transform.localEulerAngles = new Vector3(0, playerRotation, 0);
player.transform.position = startingposition + posOffset;
Trong trường hợp này, playerRotation
một trong hai 90f
hoặc -90f
tùy thuộc vào phía người chơi đang ở trên, startingposition
là vị trí "nằm ngang" của họ (so với mạng) và posOffset
là vị trí "dọc" của họ.
Quả bóng có tốc độ thiết lập lại vận tốc và góc, nhưng không phải là quả cầu (vì nó là một quả cầu, nên vòng quay của nó không ảnh hưởng gì). Vị trí của nó cũng được đặt ở một vị trí cố định liên quan đến bất kỳ cầu thủ nào phải giao bóng.
rb.velocity = Vector3.zero;
rb.angularVelocity = Vector3.zero;
transform.position = ServingPlayer.ServingPosition;
Đây rb
là quả bóng RigidBody
.
Cuối cùng, tôi không ảnh hưởng đến chuyển động của quả bóng theo bất kỳ cách nào. Tôi chỉ đơn giản là áp dụng một lực cho nó khi phục vụ, điều này chỉ xảy ra một lần. 3 giây sau khi bóng hạ cánh, trận đấu được đặt lại và mọi thứ lặp lại.
Luồng về cơ bản là như thế này (mã giả):
Start()
ResetCourt()
StartCoroutine(Players[0].Serve())
event BallLanded()
wait for 3 seconds
// repeat starting with ResetCourt()
Tôi thực sự cần quỹ đạo của quả bóng để có thể tái tạo mỗi lần trên mọi máy có thể. Rõ ràng là tôi đang làm gì đó sai ở đây, nhưng những gì?