unity-game-engine - String.Format 显示 SerializeField 数据中的旧实例数据 - 如何修复?

标签 unity-game-engine serialization string.format

我试图在运行时在 Unity 中显示一个工具提示,其中包含以下信息:

Spell Name (string)
Cast Time (float)
Damage (int)
Description (string)

我在脚本中正确设置了所有内容,并且工具提示 GetDescription() 函数正确地从包含所需信息的序列化字段中提取了法术名称、施法时间和伤害所需的信息。但是,“描述序列化”字段尽管已填充,但并未显示在工具提示中。

当我将 Debug.Log(description) 行放入函数中时,控制台显示描述的内容为空。我将描述存储在名为“description”的字符串中,它是一个 [SerializeField],以便可以在 Unity Inspector 中设置描述。这与我存储其他法术信息(法术名称、施法时间和伤害)的方法相同。

当我运行游戏构建并转到工具提示文本字段所在的层次结构时,我可以直观地确认“描述”字符串的内容没有附加到文本字段(我正在使用启用了富文本的字段)。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

[Serializable]
public class Spell : IUseable, IMoveable, IDescribable
{
    [SerializeField]
    private string name;

    [SerializeField]
    private int damage;

    [SerializeField]
    private float castTime;

    [SerializeField]
    private string description;

    public string GetDescription()
    {
        return string.Format("{0}\n Cast time: {1} second(s) 
            \n Damage:{2} \n {3}", name, castTime, damage, description);
    }
}

当我运行构建并尝试工具提示时,我得到如下内容:

Explosion
Cast Time: 2.5 second(s)
Damage: 5

不过,它应该显示类似这样的内容:

Explosion
Cast Time: 2.5 second(s)
Damage: 5
Creates a powerful explosion, injuring those caught in its blast.

更新:

private void Awake()
{
    toolTipTitle = toolTip.GetComponentInChildren<Text>();
}

public void ShowTooltip(Vector3 position, IDescribable description)
{
    toolTip.SetActive(true);
    toolTip.transform.position = position;
    toolTipTitle.text = description.GetDescription();
}

更新:

我将 Debug.Log 附加到 ShowTooltip() 函数以查看 description.GetDescription() 的内容,它确实引用了序列化字段中数据的旧实例(我将其更改为 FireTest,并使用 10第二次施法时间)。

Explosion
Cast time: 2.5 second(s)
Damage:5

UnityEngine.Debug:Log(Object)
UIManager:ShowTooltip(Vector3, IDescribable) (at Assets/Scripts/Managers/UIManager.cs:179)
ActionButton:OnPointerEnter(PointerEventData) (at Assets/Scripts/Buttons/ActionButton.cs:151)
UnityEngine.EventSystems.EventSystem:Update()

更新:

附加一些 Debug.Log 命令后,看起来代码正在引用 SerializeFields 中包含的旧数据实例的名称、castTime 和损坏情况。这个旧实例没有描述字段,这解释了为什么它没有被添加到工具提示中。寻找有关如何强制代码从 SerializeFields 重新获取所需数据的建议,而不是依赖于似乎是缓存的数据值(老实说,不确定这如何可能......但这个缓存的数据也是出现在应该从这些字段中提取数据的其他地方,例如显示法术名称并倒计时施法时间的施法栏,测试显示施法栏使用旧实例数据而不是法术书中的数据。法术书以及下面的操作按钮供引用:

代码:ActionButton.cs

public class ActionButton : MonoBehaviour, IPointerClickHandler, IClickable, IPointerEnterHandler, IPointerExitHandler
{

    public IUseable MyUseable { get; set; }

    [SerializeField]
    private Text stackSize;

    private Stack<IUseable> useables = new Stack<IUseable>();

    private int count;

    public Button MyButton { get; private set; }

    public Image MyIcon
    {
        get
        {
            return icon;
        }

        set
        {
            icon = value;
        }
    }

    public int MyCount
    {
        get
        {
            return count;
        }
    }

    public Text MyStackText
    {
        get
        {
            return stackSize;
        }
    }    

    [SerializeField]
    private Image icon;

    // Use this for initialization
    void Start ()
    {
        MyButton = GetComponent<Button>();
        MyButton.onClick.AddListener(OnClick);
        InventoryScript.MyInstance.itemCountChangedEvent += new ItemCountChanged(UpdateItemCount);
    }

    // Update is called once per frame
    void Update ()
    {

    }

    public void OnClick()
    {
        if (HandScript.MyInstance.MyMoveable == null)
        {
            if (MyUseable != null)
            {
                MyUseable.Use();
            }
            if (useables != null && useables.Count > 0)
            {
                useables.Peek().Use();
            }
        }        
    }

    public void OnPointerClick(PointerEventData eventData)
    {
        if (eventData.button == PointerEventData.InputButton.Left)
        {
            if (HandScript.MyInstance.MyMoveable != null && HandScript.MyInstance.MyMoveable is IUseable)
            {
                SetUseable(HandScript.MyInstance.MyMoveable as IUseable);
            }
        }
    }

    public void SetUseable(IUseable useable)
    {
        if (useable is Item)
        {
            useables = InventoryScript.MyInstance.GetUseables(useable);
            count = useables.Count;
            InventoryScript.MyInstance.FromSlot.MyIcon.color = Color.white;
            InventoryScript.MyInstance.FromSlot = null;
        }
        else
        {
            this.MyUseable = useable;
        }        

        UpdateVisual();
    }

    public void UpdateVisual()
    {
        MyIcon.sprite = HandScript.MyInstance.Put().MyIcon;
        MyIcon.color = Color.white;

        if (count > 1)
        {
            UIManager.MyInstance.UpdateStackSize(this);
        }
    }

    public void UpdateItemCount(Item item)
    {
        if (item is IUseable && useables.Count > 0)
        {
            if (useables.Peek().GetType() == item.GetType())
            {
                useables = InventoryScript.MyInstance.GetUseables(item as IUseable);

                count = useables.Count;

                UIManager.MyInstance.UpdateStackSize(this);
            }
        }
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
        IDescribable tmp = null;

        if (MyUseable != null && MyUseable is IDescribable)
        {
            tmp = (IDescribable)MyUseable;
            // Need to implement!
            // UIManager.MyInstance.ShowTooltip(transform.position);
        }
        else if (useables.Count > 0)
        {
            // Need to implement!
            // UIManager.MyInstance.ShowTooltip(transform.position);
        }
        if (tmp != null)
        {
            UIManager.MyInstance.ShowTooltip(transform.position, tmp);
        }
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        UIManager.MyInstance.HideTooltip();
    }
}

代码:SpellBook.cs

public class SpellBook : MonoBehaviour
{

    private static SpellBook instance;

    public static SpellBook MyInstance
    {
        get
        {
            if (instance == null)
            {
                instance = FindObjectOfType<SpellBook>();
            }

            return instance;
        }
    }

    [SerializeField]
    private Image castingBar;

    [SerializeField]
    private Text currentSpell;

    [SerializeField]
    private Text castTime;

    [SerializeField]
    private Image icon;

    [SerializeField]
    private CanvasGroup canvasGroup;

    [SerializeField]
    private Spell[] spells;

    private Coroutine spellRoutine;

    private Coroutine fadeRoutine;


    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }

    public Spell CastSpell(string spellName)
    {
        Spell spell = Array.Find(spells, x => x.MyName == spellName);

        castingBar.fillAmount = 0;

        castingBar.color = spell.MyBarColor;

        currentSpell.text = spell.MyName;

        icon.sprite = spell.MyIcon;

        spellRoutine = StartCoroutine(Progress(spell));

        fadeRoutine = StartCoroutine(FadeBar());

        return spell;
    }

    private IEnumerator Progress(Spell spell)
    {
        float timePassed = Time.deltaTime;

        float rate = 1.0f / spell.MyCastTime;

        float progress = 0.0f;

        while (progress <= 1.0)
        {
            castingBar.fillAmount = Mathf.Lerp(0, 1, progress);

            progress += rate * Time.deltaTime;

            timePassed += Time.deltaTime;

            castTime.text = (spell.MyCastTime - timePassed).ToString("F2");

            if (spell.MyCastTime - timePassed < 0)
            {
                castTime.text = "0.00";
            }

            yield return null;
        }

        StopCasting();
    }

    private IEnumerator FadeBar()
    {
        float rate = 1.0f / 0.50f;

        float progress = 0.0f;

        while (progress <= 1.0)
        {
            canvasGroup.alpha = Mathf.Lerp(0, 1, progress);

            progress += rate * Time.deltaTime;

            yield return null;
        }
    }

    public void StopCasting()
    {
        if (fadeRoutine != null)
        {
            StopCoroutine(fadeRoutine);
            canvasGroup.alpha = 0;
            fadeRoutine = null;
        }
        if (spellRoutine != null)
        {
            StopCoroutine(spellRoutine);
            spellRoutine = null;
        }
    }

    public Spell GetSpell(string spellName)
    {
        Spell spell = Array.Find(spells, x => x.MyName == spellName);

        return spell;
    }
}

最佳答案

弄清楚了 - 我不小心在另一个游戏对象中创建了脚本字段数据的克隆,而游戏正在使用它。按照回答结束此问题 - 非常感谢您的帮助! =)

关于unity-game-engine - String.Format 显示 SerializeField 数据中的旧实例数据 - 如何修复?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53860883/

相关文章:

java - 将可序列化对象存储到文件中,并排除一些数据

c# - Unity 插件内的 C# 脚本中未触发回调

android - 阻止 Unity Android 应用程序中的屏幕捕获

c# - 无效的 Json 原语

java - 如何在 servlet 中创建多个 JSON 数组到 JSON 对象

java - 返回格式化字符串无法正常工作

c# - 以CSV格式导出到EXCEL时用逗号(,)分隔字符串c#

Python 字符串格式为 float ,如何截断而不是舍入

c# - Unity3d 后台实时计数器

unity-game-engine - "stamp"正确的是 Unity 中游戏对象上的图像吗?