Unity 3D将成绩显示脚本附加到预制件

时间:2018-07-16 20:47:59

标签: c# user-interface unity3d

我正在学习Learn Unity网站上的Unity 3d教程,但这是我想做一些不同的事情。一开始效果很好,但最终这是一个错误的决定,现在我需要手动将脚本附加到每个可拾取对象上。

这是我的代码: 注意:它的作用是旋转拾音器并在拾音器与玩家球碰撞时显示得分。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class PickUps : MonoBehaviour {

    public Vector3 Rotate;
    private int Score;
    public Text ScoreGUI;

    private void Start()
    {
        Rotate = new Vector3(0, 25, 0);
        Score = 0;
        DisplayScore();

    }
    void Update () {
        transform.Rotate(Rotate*Time.deltaTime);
    }
    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("Ball"))
        {
            Destroy(this.gameObject);
            Score = Score + 1;
            DisplayScore();
        }
    }
    void DisplayScore()
    {
        ScoreGUI.text = "SCORE " + Score.ToString();
    }
}

问题:

可以,但是我需要手动将文本(在画布下)附加到每个拾取对象,这很累,不是一件好事。

我想要实现的目标:

就像在教程中一样,大多数情况下,他们在这种工作中使用预制件(我认为),问题是我可以将文本附加到当前场景中的拾取器(对象/饼干)上,但不能将文本拖动并附加到饼干的预制件,我使文本不会附加在“文本”的空白处。

1 个答案:

答案 0 :(得分:1)

您不应该直接更改得分Text。请使用Controller来建立网桥。我会做这样的事情:

将此脚本放在您的场景中的某个地方:

public class ScoreManager : Singleton<ScoreManager>
{
    private int score = 0;

    // Event that will be called everytime the score's changed
    public static Action<int> OnScoreChanged; 

    public void SetScore(int score)
    {
        this.score = score;
        InvokeOnScoreChanged();
    }

    public void AddScore(int score)
    {
        this.score += score;
        InvokeOnScoreChanged();
    }

    // Tells to the listeners that the score's changed
    private void InvokeOnScoreChanged()
    {
        if(OnScoreChanged != null)
        {
            OnScoreChanged(score);
        }
    }
}

此脚本附加在Text游戏对象中:

[RequireComponent(typeof(Text))]
public class ScoreText : MonoBehaviour
{
    private Text scoreText;

    private void Awake()
    {
        scoreText = GetComponent<Text>();
        RegisterEvents();
    }

    private void OnDestroy()
    {
        UnregisterEvents();
    }

    private void RegisterEvents()
    {
        // Register the listener to the manager's event 
        ScoreManager.OnScoreChanged += HandleOnScoreChanged; 
    }

    private void UnregisterEvents()
    {
        // Unregister the listener
        ScoreManager.OnScoreChanged -= HandleOnScoreChanged;
    }

    private void HandleOnScoreChanged(int newScore)
    {
        scoreText.text = newScore.ToString();
    }
}

在您的Pickups类中:

void DisplayScore()
{
    ScoreManager.Instance.SetScore(Score); // Maybe what you need is AddScore to not 
                                           // reset the value everytime
}

您可以使用一个简单的单例(您可以在互联网上找到更完整的单例):

public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
    static T instance;

    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                instance = (T)FindObjectOfType(typeof(T));

                if (instance == null) Debug.LogError("Singleton of type " + typeof(T).ToString() + " not found in the scene.");
            }

            return instance;
        }
    }
}

但是请注意,如果使用不正确,单例模式可能是脚上的射击。对于管理人员,您应该只适当地使用它们。