我正在研究2D无限跑者。我有以下代码从屏幕滑动输入跳转,滑动和快速运行。我从编辑器提供jumpHeight,值为500,帧率为30.代码工作正常,但有时候玩家跳得太高而无法刷卡。如果输入来自键盘,则类似代码按预期工作。为什么会发生这种情况超出了我对统一的理解。非常感谢任何帮助。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include android:id="@+id/action_back"
layout="@layout/action_back"
android:layout_height="match_parent"
android:layout_width="wrap_content" />
<LinearLayout
android:layout_toRightOf="@id/action_back"
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Title"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="17sp"
android:textStyle="bold"/>
</LinearLayout>
</RelativeLayout>
答案 0 :(得分:1)
您的代码有2个问题。
你的第一个问题在于这行代码:
grounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, groundLayer);
这行代码失败了。 grounded
始终为true
。因此,当玩家没有接地时,跳跃被称为太多次。
用
替换这行代码 Collider2D playerCollider = gameObject.GetComponent<Collider2D>();
grounded = Physics2D.OverlapCircle(playerCollider.transform.position, 1, groundLayer);
或强>
Collider2D playerCollider = gameObject.GetComponent<Collider2D>();
grounded = playerCollider.IsTouchingLayers(groundLayer.value);
您的代码的另一个问题是false
报告。有时,对等重叠会返回true
,即使它是false
。我尝试将这部分代码移动到LateUpdate函数,但是没有修复它。
您可以通过实施计时器来修复它。当玩家跳跃时,计时器将重置为 0 并开始计数 0.5 。当计时器未达到计数值时,请勿跳转。 .5 to 1
对此非常有用。使用Time.deltaTime
增加计时器。下面是您的整个代码,包括计时器和修复程序。
public class PlayerControl : MonoBehaviour
{
public float ForwardSpeed = 3.7f; //moves player in forward direction
public float speedOffset = 0.0f; //offset speed of player
public float JumpHeight = 250; //moves player in verticle direction
bool grounded = false; //checks if player is grounded or not
public Transform groundCheck;
float groundCheckRadius = 0.3f; //radius of groundcheck circle to check grounded bool
public LayerMask groundLayer;
Vector2 fingerStart;
Vector2 fingerEnd;
public float resetTimer = 0.5f; //.5 second
float timerCounter = 0;
Collider2D playerCollider = null;
Rigidbody2D playerRigidBody;
void Start()
{
playerRigidBody = GetComponent<Rigidbody2D>();
playerCollider = gameObject.GetComponent<Collider2D>();
}
void Update()
{
foreach (Touch touch in Input.touches)
{
if (touch.phase == TouchPhase.Began)
{
fingerStart = touch.position;
fingerEnd = touch.position;
}
if (touch.phase == TouchPhase.Moved)
{
fingerEnd = touch.position;
if (Mathf.Abs(fingerEnd.y - fingerStart.y) > 50)//Vertical swipe
{
if (fingerEnd.y - fingerStart.y > 50)//up swipe
{
Jump();
}
else if (fingerEnd.y - fingerStart.y < -50)//Down swipe
{
//Slide();
}
fingerStart = touch.position;
}
}
if (touch.phase == TouchPhase.Stationary)
{
RunFast();
}
if (touch.phase == TouchPhase.Ended)
{
fingerEnd = touch.position;
if (Mathf.Abs(fingerEnd.y - fingerStart.y) > 50)//Vertical swipe
{
if (fingerEnd.y - fingerStart.y > 50)//up swipe
{
Jump();
}
else if (fingerEnd.y - fingerStart.y < -50)//Down swipe
{
//Slide();
}
}
}
}
if (Input.GetButton("Fire1"))
{
speedOffset = 2.5f;
}
else
{
speedOffset = 0.0f;
}
if (grounded && Input.GetKeyDown(KeyCode.UpArrow))
{
grounded = false;
playerRigidBody.AddForce(new Vector2(0, JumpHeight));
}
//check if circle overlaps with ground layer
grounded = Physics2D.OverlapCircle(playerCollider.transform.position, 1, groundLayer);
//OR Use grounded = playerCollider.IsTouchingLayers(groundLayer.value);
//Increment Timer if it is still less than resetTimer
if (timerCounter < resetTimer)
{
timerCounter += Time.deltaTime;
}
}
void FixedUpdate()
{
//set players forward velocityto forward speed variable
Vector2 PlayerForwardvelocity = playerRigidBody.velocity;
// Vector2 PlayerJumpHeight = playerRigidBody.AddForce()
PlayerForwardvelocity.x = ForwardSpeed + speedOffset;
playerRigidBody.velocity = PlayerForwardvelocity;
}
void Jump()
{
if (grounded)
{
//Exit if timer has not reached the required value to jump again
if (timerCounter < resetTimer)
{
Debug.Log("Failed To Jump because timer has not yet reached");
return; //Exit
}
timerCounter = 0; //Reset Timer
playerRigidBody.AddForce(new Vector2(0, JumpHeight));
speedOffset = 0.0f;
Debug.Log("Jumped");
}
else
{
Debug.Log("Not on the Ground");
}
}
void RunFast()
{
if (Input.GetButton("Fire1"))
{
speedOffset = 2.5f;
}
else
{
speedOffset = 0.0f;
}
}
}