Saya sedang membangun game balap marmer yang cukup sederhana di Unity3D. Bola adalah objek fisika 3D yang hanya bergerak pada sumbu X dan Y. Ia memiliki kemampuan untuk berguling ke kiri dan ke kanan, dan untuk melompat. Hal-hal yang cukup mendasar, kecuali bahwa saya telah memecahkan masalah: Ketika jatuh dan menyerang tanah, bouncing magnitude bola dapat dikombinasikan dengan kekuatan lompatnya untuk menciptakan lompatan ekstra tinggi. Ini berarti bahwa, dengan penekanan tombol yang tepat waktu, pemain dapat menyebabkan bola memantul secara eksponensial lebih tinggi, mencapai ketinggian yang tidak diinginkan. Saya tidak dapat mendesain level dengan baik sampai kesalahan ini diperbaiki. Saya telah menggambarkan contoh ini:
Melompat, bagaimanapun, tidak sesederhana hanya menembakkan bola lurus ke atas. Untuk memfasilitasi lebih banyak kerumitan dalam desain level, saya telah memprogram sudut lompatan agar relatif terhadap permukaan tempat bola bergulir.
Gambar 3 , dalam ilustrasi itu, adalah bagaimana permainan saya bekerja sejauh ini; bukan Gambar 4 . Ini membuat pemecahan untuk masalah bouncing + lompat jauh lebih menantang, karena saya tidak bisa hanya mengukur dan mengatur kekuatan atau kecepatan yang tepat pada sumbu Y. Melakukannya menghasilkan perilaku aneh, yang menjadi jauh lebih terlihat ketika bola bergerak di lereng yang lebih curam.
Sejauh ini, saya sudah bisa memikirkan solusi untuk semua masalah desain lainnya dalam game ini dan kemudian mencari tahu bagaimana memprogramnya, tetapi yang satu ini membuat saya macet. Saya telah mencoba sejumlah pendekatan yang berbeda, tetapi tidak satupun yang berhasil.
Inilah skrip C # yang mengontrol lompatan bola:
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();
}
}
}
Upaya terakhir saya adalah mencoba melompat - rigidbody.velocity.magnitude * 50 , untuk mengurangi kekuatan lompatan dengan kecepatan bola melakukan perjalanan. Itu hampir memecahkan masalah bouncing + lompatan, dengan secara proporsional mengurangi gaya lompat turun ke nol ketika kecepatan bola mencapai apa yang tampaknya setara dalam kecepatan. Ini bekerja dari macet, tetapi masalahnya adalah, ia juga menghitung besarnya saat bola di-ground, mencegah bola bergulir dengan kecepatan penuh dan melompat. Saya dekat, tetapi tidak cukup di sana!
Saya seorang programmer pemula, dan saya bingung di sini. Adakah yang bisa membantu saya menemukan solusi kreatif untuk masalah ini? Selama pemain dapat terus melambung dan melompat semakin tinggi, saya tidak bisa mendesain level apa pun, karena mereka semua hanya bisa ditipu. Saya ingin terus maju - masalah ini telah menahan saya sejak lama, jadi saya sangat menghargai beberapa saran!