我试图让我的游戏对象字符从一个位置移动到另一个在拾取4个对象后的视频游戏。它可以传送,但一旦传送,它就会一直传送到指定的位置。我不知道如何阻止它,所以它让我自由地移动到新的位置。让它转到新位置的是if (scoreValue == 4) transform position vector2
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerScript: MonoBehaviour {
private Rigidbody2D rd2d;
public float speed;
public Text scoreText;
private int scoreValue;
public GameObject winTextObject;
public GameObject loseTextObject;
private int lives;
public Text livesText;
// Start is called before the first frame update
void Start() {
rd2d = GetComponent < Rigidbody2D > ();
scoreValue = 0;
scoreText.text = "Score: " + scoreValue.ToString();
winTextObject.SetActive(false);
loseTextObject.SetActive(false);
lives = 3;
}
// Update is called once per frame
void FixedUpdate() {
float hozMovement = Input.GetAxis("Horizontal");
float verMovement = Input.GetAxis("Vertical");
rd2d.AddForce(new Vector2(hozMovement * speed, verMovement * speed));
}
private void OnCollisionEnter2D(Collision2D collision) {
if (collision.collider.tag == "Coin") {
scoreValue += 1;
scoreText.text = "Score: " + scoreValue.ToString();
Destroy(collision.collider.gameObject);
} else if (collision.collider.tag == "Enemy") {
lives -= 1;
livesText.text = lives.ToString();
Destroy(collision.collider.gameObject);
}
}
void Update() {
if (scoreValue >= 4) {
winTextObject.SetActive(true);
} {
livesText.text = "Lives: " + lives.ToString();
}
if (lives <= 0) {
loseTextObject.SetActive(true);
}
}
private void OnCollisionStay2D(Collision2D collision) {
if (collision.collider.tag == "Ground") {
if (Input.GetKey(KeyCode.W)) {
rd2d.AddForce(new Vector2(0, 3), ForceMode2D.Impulse);
}
}
if (Input.GetKey("escape")) {
Application.Quit();
}
if (scoreValue == 4) {
transform.position = new Vector2(64.0 f, -1.0 f);
}
}
}
您可以添加一个额外的布尔变量,以便它只输入一次if
。
- 开头申报
private bool isGameOver;
- 在
Start()
内,确保isGameOver = false
- 使用 更改最终条件
if (scoreValue == 4 && !isGameOver)
{
isGameOver = true;
transform.position = new Vector2(64.0f, -1.0f);
}
有了这个附加功能,你将启动你的"瞬间传送"。只有一次。
我认为你应该在你想要运输事件发生的地方放一个标志。
bool isTransported = false;
then compare in Update()
if (scoreValue >= 4) isTransported == true;
if (isTransported) transform.position = new Vector2(64.0 f, -1.0 f);
,然后重置布尔值,如果你想做另一个传输:
isTranported == false;
我也建议你,如果你想在你的游戏中做一些更多的运输事件。您应该明确地将您的分数与一个值或值范围进行比较。否则,您的事件将无法正常工作。例如,当得分>=4时,你希望你的角色传送到位置A,当得分>=10时,你的角色移动到位置B,那么这里的条件重叠。游戏将同时执行这两个事件,因为>=10也是>=4。
一般来说,不是每帧都轮询检查这些值让你的代码事件驱动
!根本不需要额外的标志。
由于OnCollisionEnter2D
实际上似乎是唯一改变两个值的地方,而不是这样做,例如
// NOT NEEDED AT ALL
// private void Update() { }
private void OnCollisionEnter2D(Collision2D collision)
{
// In general rather use "CompareTag" instead of string "=="
// While "==" silently fails in case of typos or non-existent tags
// "CompareTag" will throw an error making your debugging easier and is also slightly faster since it uses Hashes
if (collision.gameObject.CompareTag("Coin"))
{
Destroy(collision.gameObject);
scoreValue++;
scoreText.text = $"Score: {scoreValue}";
if(scoreValue == 4)
{
winTextObject.SetActive(true);
// in general never set the position via Transform when dealing with Rigidbodis!
rd2d.position = new Vector2(64.0 f, -1.0 f);
}
}
else if (collision.gameObject.CompareTag("Enemy"))
{
Destroy(collision.gameObject);
lives--;
livesText.text = $"Lives: {lives}";
if (lives <= 0)
{
loseTextObject.SetActive(true);
}
}
}
private void OnCollisionStay2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Ground"))
{
if (Input.GetKey(KeyCode.W))
{
rd2d.AddForce(new Vector2(0, 3), ForceMode2D.Impulse);
}
}
if (Input.GetKey("escape"))
{
Application.Quit();
}
// no need to poll check the "lives" here either
}
你甚至可以更进一步,使用properties这样,您可以将行为与字段的任何更改耦合在一起,甚至可以从外部设置它们,而无需双重实现:
// This only stores the value (backing field) but you will never touch it directly ;)
private int _scoreValue;
// This now is a property that allows everyone to read the value
// but only this class to set it (for now)
// additionally every time you set the value it will update the display and react to the => 4 condition
public int scoreValue
{
get => _scoreValue;
private set
{
_scoreValue = value;
scoreText.text = $"Score: {_scoreValue}";
if(_scoreValue == 4)
{
winTextObject.SetActive(true);
// in general never set the position via Transform when dealing with Rigidbodis!
rd2d.position = new Vector2(64.0 f, -1.0 f);
}
}
}
// The same thing you can also make for the lives
private int _lives;
public int lives
{
get => _lives;
private set
{
_lives = value;
livesText.text = $"Lives: {_lives}";
if (_lives <= 0)
{
loseTextObject.SetActive(true);
}
}
}
现在你只需输入
private void OnCollisionEnter2D(Collision2D collision)
{
// In general rather use "CompareTag" instead of string "=="
// While "==" silently fails in case of typos or non-existent tags
// "CompareTag" will throw an error making your debugging easier and is also slightly faster since it uses Hashes
if (collision.gameObject.CompareTag("Coin"))
{
Destroy(collision.gameObject);
scoreValue++;
}
else if (collision.gameObject.CompareTag("Enemy"))
{
Destroy(collision.gameObject);
lives--;
}
}
,但后来可以添加越来越多的方法,你如何失去或获得分数和生命,而不必记住实现文本更新和条件检查。这些只做一次在属性内;)