मैं यूनिटी 3 डी में एक काफी सरल संगमरमर रेसिंग गेम बना रहा हूं। गेंद एक 3 डी भौतिकी वस्तु है जो केवल एक्स और वाई कुल्हाड़ियों पर चलती है। इसमें बाएं और दाएं रोल करने और कूदने की क्षमता है। सुंदर बुनियादी सामान, सिवाय इसके कि मैंने एक गेम-ब्रेकिंग समस्या को मारा है: जब जमीन गिरती है और स्ट्राइक होती है, तो गेंद की उछाल परिमाण को एक अतिरिक्त-उच्च कूद बनाने के लिए अपने जंपिंग बल के साथ जोड़ा जा सकता है। इसका मतलब यह है कि, अच्छी तरह से समय पर बटन दबाने के साथ, खिलाड़ी गेंद को तेजी से उछाल देने का कारण बन सकता है, अनपेक्षित ऊंचाइयों तक पहुंच सकता है। जब तक यह गड़बड़ ठीक नहीं हो जाती, तब तक मैं स्तरों को ठीक से डिज़ाइन नहीं कर सकता। मैंने इसका उदाहरण दिया है:
हालाँकि, कूदना उतना आसान नहीं है, जितना कि सीधे गेंद को ऊपर की तरफ मारना। स्तर के डिजाइन में अधिक जटिलता की सुविधा के लिए, मैंने गेंद को रोल करने वाली सतह के सापेक्ष होने के लिए कूद कोण को क्रमादेशित किया है।
चित्र 3 , उस दृष्टांत में, इस तरह से मेरा खेल काम करता है; चित्र 4 नहीं । यह उछाल + कूदने की समस्या को और अधिक चुनौतीपूर्ण बनाता है, क्योंकि मैं केवल Y- अक्ष पर एक सटीक बल या वेग नहीं माप सकता / सकती हूं। ऐसा करने से अजीब व्यवहार होता है, जो नाटकीय रूप से अधिक ध्यान देने योग्य हो जाता है क्योंकि गेंद स्टिपर स्लोप पर जाती है।
अब तक, मैं इस गेम में अन्य सभी डिज़ाइन समस्याओं का समाधान करने में सक्षम हूं और फिर पता लगाऊं कि उन्हें कैसे प्रोग्राम करना है, लेकिन यह मुझे अटक गया है। मैंने कई अलग-अलग तरीकों से प्रयास किया है, लेकिन उनमें से किसी ने भी काम नहीं किया है।
यहाँ सी # स्क्रिप्ट है जो गेंद की कूद को नियंत्रित करती है:
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 , जिस गति से गेंद यात्रा कर रही है, उससे कूदने की शक्ति को कम करना। इसने उछाल + कूद की समस्या को लगभग हल कर दिया, आनुपातिक रूप से कूद बल को शून्य से कम करने के रूप में गेंद की गति तक पहुंच गई जो वेगमान गति में बराबर प्रतीत होती थी। यह एक ठहराव से काम करता है, लेकिन समस्या यह है, यह भी परिमाण के लिए जिम्मेदार है, जबकि गेंद जमीन पर है, गेंद को पूरी गति से लुढ़कने और कूदने से रोकती है। मैं करीब था, लेकिन काफी नहीं!
मैं नौसिखिया प्रोग्रामर हूं, और मैं यहां आकर रुक गया हूं। क्या कोई इस समस्या का रचनात्मक समाधान खोजने में मेरी मदद कर सकता है? जब तक खिलाड़ी लगातार उछाल और उच्चतर कूदने में सक्षम होता है, मैं किसी भी स्तर को डिजाइन नहीं कर सकता, क्योंकि वे सभी के माध्यम से धोखा देने में सक्षम होंगे। मैं आगे बढ़ना पसंद करूँगा - यह मुद्दा मुझे लंबे समय से पकड़ रहा है, इसलिए मैं कुछ सलाह देना चाहूँगा!