Ich baue ein ziemlich einfaches Marmor-Rennspiel in Unity3D. Der Ball ist ein 3D-Physikobjekt, das sich nur auf der X- und Y-Achse bewegt. Es hat die Fähigkeit, nach links und rechts zu rollen und zu springen. Ziemlich einfaches Zeug, außer dass ich auf ein bahnbrechendes Problem gestoßen bin: Beim Fallen und Schlagen auf den Boden kann die Sprungstärke des Balls mit seiner Sprungkraft kombiniert werden, um einen extra hohen Sprung zu erzielen. Dies bedeutet, dass der Spieler bei gut getimten Tastendrücken dazu führen kann, dass der Ball exponentiell höher springt und unbeabsichtigte Höhen erreicht. Ich kann Levels nicht richtig entwerfen, bis dieser Fehler behoben ist. Ich habe dieses Beispiel illustriert:
Das Springen ist jedoch nicht so einfach, wie den Ball gerade nach oben zu schießen. Um das Level-Design komplexer zu gestalten, habe ich den Sprungwinkel so programmiert, dass er relativ zur Oberfläche ist, auf der der Ball rollt.
Abbildung 3 in dieser Abbildung zeigt, wie mein Spiel bisher funktioniert. nicht Abbildung 4 . Dies macht das Lösen des Bounce + Jump-Problems viel schwieriger, da ich nicht einfach eine genaue Kraft oder Geschwindigkeit auf der Y-Achse messen und einstellen kann. Dies führt zu einem seltsamen Verhalten, das sich dramatisch bemerkbar macht, wenn sich der Ball auf steileren Hängen bewegt.
Bisher war ich in der Lage, eine Lösung für alle anderen Designprobleme in diesem Spiel zu finden und dann herauszufinden, wie man sie programmiert, aber dieses hat mich festgefahren. Ich habe verschiedene Ansätze versucht, aber keiner von ihnen hat funktioniert.
Hier ist das C # -Skript, das das Springen des Balls steuert:
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();
}
}
}
Mein letzter Versuch war, Jump - Rigidbody.velocity.magnitude * 50 zu versuchen , um die Sprungkraft um die Geschwindigkeit zu reduzieren, mit der sich der Ball bewegt . Es löste fast das Bounce + Jump-Problem, indem es die Sprungkraft proportional auf Null reduzierte, als die Geschwindigkeit des Balls das erreichte, was der Geschwindigkeit zu entsprechen schien. Es hat aus dem Stand heraus funktioniert, aber das Problem ist, dass es auch die Größe berücksichtigt, während der Ball geerdet ist, wodurch verhindert wird, dass der Ball mit voller Geschwindigkeit rollt und springt. Ich war nah dran, aber nicht ganz da!
Ich bin ein Anfänger Programmierer, und ich bin hier ratlos. Kann mir jemand helfen, eine kreative Lösung für dieses Problem zu finden? Solange der Spieler in der Lage ist, kontinuierlich höher und höher zu springen und zu springen, kann ich keine Level entwerfen, da sie alle nur betrogen werden können. Ich würde gerne weitermachen - dieses Problem hat mich schon lange zurückgehalten, daher würde ich mich über Ratschläge sehr freuen!