ฉันกำลังสร้างเกมแข่งรถหินอ่อนที่ค่อนข้างง่ายใน Unity3D ลูกบอลเป็นวัตถุฟิสิกส์ 3 มิติที่เคลื่อนที่บนแกน X และ Y เท่านั้น มันมีความสามารถในการหมุนไปทางซ้ายและขวาและกระโดด สิ่งพื้นฐานที่น่ารักยกเว้นว่าฉันเคยเจอปัญหาการทำลายเกม: เมื่อล้มและกระทบพื้นความสูงของการตีกลับของลูกบอลสามารถรวมกับแรงกระโดดเพื่อสร้างการกระโดดสูงเป็นพิเศษ ซึ่งหมายความว่าเมื่อกดปุ่มตามเวลาที่กำหนดผู้เล่นสามารถทำให้ลูกบอลกระดอนสูงกว่าแบบทวีคูณได้ถึงความสูงที่ไม่ได้ตั้งใจ ฉันไม่สามารถออกแบบระดับได้อย่างถูกต้องจนกว่าข้อผิดพลาดนี้จะได้รับการแก้ไข ฉันได้แสดงตัวอย่างนี้:
อย่างไรก็ตามการกระโดดไม่ใช่เรื่องง่ายเหมือนยิงลูกขึ้นไปด้านบน เพื่ออำนวยความสะดวกให้กับความซับซ้อนมากขึ้นในการออกแบบระดับฉันได้ตั้งโปรแกรมมุมกระโดดที่จะสัมพันธ์กับพื้นผิวที่ลูกบอลกลิ้งไปมา
รูปที่ 3ในภาพประกอบนั้นเป็นวิธีที่เกมของฉันทำงานได้ดี ไม่ได้รูปที่ 4 นี่ทำให้การแก้ปัญหาการตีกลับ + กระโดดมีความท้าทายมากขึ้นเพราะฉันไม่สามารถวัดและกำหนดแรงหรือความเร็วที่แน่นอนบนแกน Y ได้ การทำเช่นนี้ส่งผลให้เกิดพฤติกรรมแปลก ๆ ซึ่งจะเห็นได้ชัดเจนมากขึ้นเมื่อลูกบอลเคลื่อนที่บนทางลาดชัน
จนถึงตอนนี้ฉันสามารถเข้าใจวิธีการแก้ปัญหาการออกแบบอื่น ๆ ทั้งหมดในเกมนี้แล้วค้นหาวิธีการตั้งโปรแกรมพวกเขา แต่อันนี้ฉันติดอยู่ ฉันพยายามหลายวิธี แต่ก็ไม่ได้ผลเลย
นี่คือสคริปต์ C # ที่ควบคุมการกระโดดของลูกบอล:
using UnityEngine;
using System.Collections;
public class BallJumping : MonoBehaviour {
public System.Action onJump;
public Rigidbody objRigidbody; // Set this to the player
public bool isGrounded; // Determines whether or not the ball is on the ground
public Transform groundChecker; // A child object that's slightly larger than the ball
public float groundRadius = 0.6f;
public LayerMask whatIsGround; // Determines what layers qualify as ground
public AudioClip jumpSFX;
public AudioClip stickyJumpSFX;
private float p_WillJumpTimeRemaining; // Grace periods before/after hitting the ground to trigger jump
private float p_CanJumpTimeRemaining;
public float earlyJumpToleranceDuration = 0.2f;
public float lateJumpToleranceDuration = 0.2f;
public float jump = 500f; // Jumping power
private float halfJump = 250f; // Used for the sticky puddles
public bool stuck = false; // Used for sticky materials
private float contactX;
private float contactY;
// Input for jumping
void Update () {
if (Input.GetButtonDown ("Jump") && isGrounded == true) {
ProcessJump();
}
}
// Continuously checks whether or not the ball is on the ground
void FixedUpdate () {
if (Physics.CheckSphere (groundChecker.position, groundRadius, whatIsGround) == true) {
isGrounded = true;
} else {
isGrounded = false;
}
}
// Sets a grace period for before or after the ball contacts the ground for jumping input
void ProcessJump () {
bool boolGetJump = Input.GetButtonDown("Jump");
if (boolGetJump && isGrounded == false) {
p_WillJumpTimeRemaining = earlyJumpToleranceDuration;
} else {
if (p_WillJumpTimeRemaining > 0) {
p_WillJumpTimeRemaining -= Time.fixedDeltaTime;
}
}
if (isGrounded) {
p_CanJumpTimeRemaining = lateJumpToleranceDuration;
}
if (isGrounded || p_WillJumpTimeRemaining > 0) {
Jump();
}
if (p_CanJumpTimeRemaining > 0) {
p_CanJumpTimeRemaining -= Time.fixedDeltaTime;
}
}
// Sticky puddles script -- hinders jumping while in the puddle
void OnTriggerEnter (Collider collision) {
if (collision.gameObject.tag == "Sticky") {
stuck = true;
}
}
void OnTriggerExit (Collider collision) {
if (collision.gameObject.tag == "Sticky") {
stuck = false;
}
}
// Calculates the normals for the jump angle
void OnCollisionStay (Collision collision) {
Debug.Log ("Collision.");
foreach (ContactPoint contact in collision.contacts) {
contactX = contact.normal.x;
contactY = contact.normal.y;
}
}
// Controls jumping
void Jump() {
Debug.Log ("Jump.");
p_WillJumpTimeRemaining = 0.0f;
p_CanJumpTimeRemaining = 0.0f;
halfJump = jump * 0.5f; // Cuts jumping force in half while in a sticky puddle
GetComponent<AudioSource>().volume = 1;
GetComponent<AudioSource>().pitch = Random.Range (0.9f, 1.1f);
if (stuck == false) {
objRigidbody.AddForce (contactX * jump, contactY * jump, 0);
GetComponent<AudioSource>().clip = jumpSFX;
GetComponent<AudioSource>().Play ();
}
else if (stuck == true) {
objRigidbody.AddForce (contactX * halfJump, contactY * halfJump, 0);
GetComponent<AudioSource>().clip = stickyJumpSFX;
GetComponent<AudioSource>().Play ();
}
if (onJump != null) {
onJump();
}
}
}
ความพยายามครั้งล่าสุดของฉันคือลองกระโดด - rigidbody.velocity.magnitude * 50เพื่อลดพลังการกระโดดด้วยความเร็วที่ลูกบอลเคลื่อนที่ มันเกือบแก้ปัญหาการตีกลับ + กระโดดโดยการลดแรงกระโดดลงไปที่ศูนย์อย่างเป็นสัดส่วนเมื่อความเร็วของลูกถึงสิ่งที่ดูเหมือนจะเท่ากับความเร็วในการหมุน มันทำงานได้จากการหยุดนิ่ง แต่ปัญหาคือมันยังคำนึงถึงขนาดในขณะที่ลูกบอลถูกต่อสายดินป้องกันไม่ให้ลูกบอลกลิ้งด้วยความเร็วเต็มที่และกระโดด ฉันสนิท แต่ก็ไม่ค่อยมี!
ฉันเป็นโปรแกรมเมอร์มือใหม่และฉันก็นิ่งงันอยู่ที่นี่ ใครช่วยฉันหาวิธีแก้ปัญหาที่สร้างสรรค์กับปัญหานี้ได้หรือไม่? ตราบใดที่ผู้เล่นสามารถตีกลับและกระโดดได้สูงขึ้นเรื่อย ๆ ฉันไม่สามารถออกแบบด่านต่าง ๆ ได้เพราะพวกเขาจะสามารถโกงได้ ฉันชอบที่จะเดินหน้าต่อไป - ปัญหานี้ทำให้ฉันกลับมาเป็นเวลานานดังนั้นฉันจึงขอขอบคุณคำแนะนำบางอย่าง!