c# - Unity 在重播时将分数重置为 0
问题描述
问候!我有一个工作脚本,可以将我的游戏分数从一个级别传递到另一个级别。问题是我的重播级别脚本没有重置为 0,而是保留了重置之前的分数。关于如何在不干扰分数结转脚本的情况下让重播脚本将分数重置为 0 的建议将不胜感激
分数结转脚本
{
public static int scoreValue = 0;
Text score;
void Start()
{
score = GetComponent<Text>();
scoreValue = PlayerPrefs.GetInt("Player Score");
}
void Update()
{
score.text = " " + scoreValue;
PlayerPrefs.SetInt("Player Score", scoreValue);
}
}
重播关卡脚本
{
public static int scoreValue = 0;
Text score;
public void RestartLevel()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
score = GetComponent<Text>();
score.text = " " + 0;
}
public void Awake()
{
Time.timeScale = 1;
}
解决方案
好吧抱歉刚到家。评论中已经解决了一些问题。我看到的一个问题是PlayerPrefs.SetInt("Player Score", scoreValue);
在Update()
函数中的不断使用。除非绝对需要,否则我不会使用任何类型的Update()
方法,因为某些调用的方法在计算上会变得相当繁重。对于一个较小的项目,它可以忽略不计,但经过几个月的项目工作后,这样的事情可能会成为您项目的瓶颈。
除了没有这种方法的挑剔原因之外Update()
,这很可能是数据没有重置的原因,因为它每帧都设置它。我做了一些重写来帮助你。我将使用一些人认为不好的单例模式,但我不同意。我发现它们在适当的情况下使用并且没有过度使用时非常有用。为了简要和一般地解释单例模式,它实际上是一个全局类的静态实例,因此所有其他脚本都可以通过访问它的实例来访问它。把它想象成一个只存在一次的类,其他所有脚本都可以使用它。
首先,创建一个名为Singleton.cs
并复制以下代码的新脚本。我剥离了 Unity 的实现,并评论说它不那么令人困惑。
// from the Unity wiki
// http://wiki.unity3d.com/index.php/Singleton
// base class of a singelton pattern
using UnityEngine;
/// <summary>
/// Inherit from this base class to create a singleton.
/// e.g. public class MyClassName : Singleton<MyClassName> {}
/// </summary>
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
// Check to see if we're about to be destroyed.
private static object m_Lock = new object();
private static T m_Instance;
/// <summary>
/// Determines if this instance exists
/// </summary>
/// <returns></returns>
public static bool HasInstance() { return m_Instance != null; }
/// <summary>
/// Access singleton instance through this propriety.
/// </summary>
public static T Instance
{
get
{
lock (m_Lock)
{
if (m_Instance == null)
{
// Search for existing instance.
m_Instance = (T)FindObjectOfType(typeof(T));
// Create new instance if one doesn't already exist.
if (m_Instance == null)
{
// Need to create a new GameObject to attach the singleton to.
var singletonObject = new GameObject();
m_Instance = singletonObject.AddComponent<T>();
singletonObject.name = typeof(T).ToString() + " (Singleton)";
// Make instance persistent.
DontDestroyOnLoad(singletonObject);
}
}
return m_Instance;
}
}
}
}
现在为分数carry over script
。我改变了一点,成为一名得分经理。这意味着什么取决于您,但管理器的一般概念是它保存与其管理的任何内容相关的所有数据。在您的情况下,它将管理、保存、操作和显示分数。其他需要访问分数、更改分数等的脚本调用它。
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
/// <summary>
/// Scoremanager that handles all score related functionality
/// </summary>
public class ScoreManager : Singleton<ScoreManager>
{
[SerializeField] private Text score;
private int scoreValue = 0;
private void OnEnable()
{
SceneManager.sceneLoaded += NewSceneLoaded;
}
private void OnDisable()
{
SceneManager.sceneLoaded -= NewSceneLoaded;
}
/// <summary>
/// Listen for when a new scene is loaded - set our score to the current player value
/// </summary>
/// <param name="scene"></param>
/// <param name="mode"></param>
public void NewSceneLoaded(Scene scene, LoadSceneMode mode)
{
// again just reusing the same function for less code rewriting
AddScore(PlayerPrefs.GetInt("Player Score"));
}
/// <summary>
/// Adds any given amount to our score, saves it and displays it to the user
/// </summary>
/// <param name="amount"></param>
public void AddScore(int amount)
{
scoreValue += amount;
UpdateScoreUI();
PlayerPrefs.SetInt("Player Score", scoreValue);
}
public void ResetScore()
{
// nice trick to reset the score to 0 by negating the entire score
// re-uses all of the other code as well to update UI and save the score to Player Prefs
AddScore(-scoreValue);
}
/// <summary>
/// Updates the UI of our score
/// </summary>
private void UpdateScoreUI()
{
score.text = "Score: " + scoreValue;
}
}
如您所见,它是从Singleton
类继承的,这意味着只要对象存在于场景中,就可以从项目中的任何位置调用它。确保ScoreManager
在每个场景中放置一个。另一个更改是我将Text
对象设置为私有字段,并将Serialized
其设置在检查器中。这只是意味着其他类无法访问它,但 Unity 会在检查器中显示它,因此您可以将Text
对象拖到脚本中以获取参考集。我要说明的另一点是,我正在订阅 SceneManager 委托事件,sceneLoaded
当场景完成加载时会调用该委托事件。我正在使用它来初始设置 UI 并正确初始化您的分数。
接下来是一个示例脚本,它调用ScoreManager
来增加分数。它有一个 int 值,可以将分数增加我在检查器中设置的某个值。您可以将其附加到任何更改分数的对象上,或者您可以复制重要的一行。
使用 UnityEngine;
/// <summary>
/// Example object that increases our score
/// </summary>
public class IncreaseScore : MonoBehaviour
{
// the amount of score that this object gives when its IncScore is called
[SerializeField] private int PointsWorth = 0;
/// <summary>
/// Increaes our score after some event - this example I am using a button to increase it
/// whenever you click an enemy or object, etc. use the same function
/// </summary>
public void IncScore()
{
ScoreManager.Instance.AddScore(PointsWorth);
}
}
重申一下,改变当前分数的一行是这一行:ScoreManager.Instance.AddScore(PointsWorth);
. 更改PointsWorth
为您想要更改的任何值。
最后,我ReplayLevel
稍微修改了您的内容,以确保在ResetLevel
调用该函数时将分数重置为 0。
using UnityEngine;
using UnityEngine.SceneManagement;
public class ReplayLevel : MonoBehaviour
{
public void Awake()
{
Time.timeScale = 1;
}
public void RestartLevel()
{
// reset our score as we are resetting the level
PlayerPrefs.SetInt("Player Score", 0);
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
public void NewLevel()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
如果您有任何问题,请告诉我,因为这非常多。我自己对此进行了测试,因为它涉及更多,并且我让它在一个场景中本地工作,其中有一堆按钮只是调用函数。
推荐阅读
- aws-lambda - 如何使用无服务器数据狗插件监控 HTTP 状态代码
- python - 在 Python 中提高 BFS 的性能
- openshift - Windows Jenkins Slave 无法连接到托管在 Openshift 实例上的主服务器
- python - Pyspark 从列表中创建组合
- flutter - ChipSelect 回调未更新 UI。扑
- javascript - 达到 EOF,但没有关闭 MIME 边界 [node.js]
- python - 如何在 Google Colab 上使用 Patool 提取受密码保护的 Rar 文件
- amazon-web-services - 如何修复“WebSocket API 的连接持续时间:2 小时”的 websocket 限制
- python - 计数对象内 Json 数组中的出现次数
- callback - 在 connectedCallback 中等待 Element Upgrade:FireFox 和 Chromium 的区别