【问题标题】:Calling Methods Incorrectly? C#调用方法不正确? C#
【发布时间】:2015-05-08 01:38:43
【问题描述】:

我正在尝试从不同的脚本调用 AddFuel 方法,但我没有收到任何错误,但我的燃料不会更新,燃料类型的 UI 更新,除了它显示满燃料(即使燃料不应该是满的) 但是一旦我消耗燃料,燃料就会恢复到减去我消耗的燃料的状态。

我该如何解决这个问题?

加油脚本

void Collect()
{
    PlayerController playerController =gameObject.AddComponent<PlayerController>();
    float addFuel = .5f;
    playerController.AddFuel(addFuel);
}

PlayerController 脚本

public void AddFuel(float value)
{
    fuel += value;
    UIController.SetFuel(fuel);
}

UIController 脚本

using UnityEngine;
using System.Collections;

public class UIController : MonoBehaviour {

    private static UIController Instance { get; set; }

    public UIRemaining remaining;
    public UIFuel fuel;
    public UIGameOver gameOver;
    public UITimer timer;

    /// <summary>
    /// Update the UI to show the new number of remaining goals.
    /// </summary>
    /// <param name="value">The number of goals remaining.</param>
    public static void SetRemaining(int value)
    {
        Instance.remaining.SetValue(value);
    }

    /// <summary>
    /// Set the current value of the fuel bar
    /// </summary>
    /// <param name="value">A normalised value between 0 and 1, with 0 being empty and 1 being full.</param>
    public static void SetFuel(float value)
    {
        Instance.fuel.SetValue (value);
    }

    /// <summary>
    /// Update the game timer to display a new value
    /// </summary>
    /// <param name="gameTime">The time, in seconds, to display in the UI</param>
    public static void SetTime(float gameTime)
    {
        Instance.timer.SetTime(gameTime);
    }

    /// <summary>
    /// Display the game over screen with a custom message. This will not show any time information.
    /// </summary>
    /// <param name="message">The message to display on the game over screen.</param>
    public static void GameOver(string message)
    {
        Instance.gameOver.Show (message);
    }

    /// <summary>
    /// Display the game over screen with a custom message and time information.
    /// </summary>
    /// <param name="message">The message to display on the game over screen.</param>
    /// <param name="time">The last time, in seconds, played in this level</param>
    /// <param name="bestTime">The best time, in seconds, played in this level</param>
    /// <param name="isNewHighscore">True if the best time is a new highscore, otherwise false.</param>
    public static void GameOver(string message, float time, float bestTime, bool isNewHighscore)
    {
        Instance.gameOver.Show (message, time, bestTime, isNewHighscore);
    }

    public static void LoadUI()
    {
        if (Instance == null) {
            Application.LoadLevelAdditive("UI");
        }
    }

    void Awake()
    {
        Instance = this;
    }

    void OnDestroy()
    {
        Instance = null;
    }

    // Use this for initialization
    void Start () {
    }
}

UIFuel 脚本

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

public class UIFuel : MonoBehaviour {

    public Slider slider;

    public void SetValue (float value)
    {
        slider.value = value;
    }

    // Use this for initialization
    void Start () {

    }
}

【问题讨论】:

标签: c# methods unity3d


【解决方案1】:

线

PlayerController playerController=gameObject.AddComponent<PlayerController>();

创建一个新的 PlayerController 并附加它。所以,如果你收集了 20 个时间,你最终将有 20 个 PlayerControllers 附加到你的游戏对象上。我的猜测是您之前附加了一个 PlayerController,并且您希望获得对它的引用而不是创建一个新的。如果所有 20 人都竞相设置指示剩余燃料量的滑块的值,则这尤其糟糕。如果是这样,请改用它:

PlayerController playerController=gameObject.GetComponent<PlayerController>();

每当您使用 GetComponent 时,您可能想要测试返回的对象是否为空,并处理它。所以,你可以跟进

if (playerController == null)
{
    playerController = gameObject.AddComponent<PlayerController>();
}

这类似于 Gabriel Coutinho 的回答,但在这里我保留了您对 playerController 的使用作为局部变量。另外,我使用了GetComponent。使用 GetComponent 可能会对性能产生轻微影响,因此您不希望每次更新都多次调用它。 (您可以使用公共或私有字段,以便只使用一次 GetComponent。)但是,如果您已经附加了一个 PlayerController,比如说在编辑器中您还设置了初始燃料量,您想使用那个,并且不要仅仅因为您还没有对它的引用而创建第二个。您希望避免让两个具有不同想法的 PlayerController 竞争剩余多少燃料来设置燃料指示器的值。

【讨论】:

    【解决方案2】:

    在 RefuelPickup 脚本中,每次调用 Collect() 方法时都会实例化一个新的 PlayerController 组件。实例化新的 PlayerController 时,fuel 属性的起始值是多少?

    通过查看您的代码,我的猜测是 PlayerController 以燃料的最大值开始。这可以解释为什么 UIFuel 滑块值总是在新的燃料收集上设置为满。每次调用 Collect 时都会创建一个新的 PlayerController 实例,并更新 UIFuel 以显示完整的燃料值。

    如果您用于消耗燃料的方法也在 PlayerController 脚本上,那么您可能总是调用同一个 PlayerController 实例的 expend 方法,可能是第一个实例化的,因此将 UIFuel 滑块值设置为任何收集之前的值减去消耗的值。

    如果发生这种情况,要避免在每次调用 Collect() 方法时创建新的 PlayerController。相反,请在 RefuelPickup 脚本上尝试这样的操作:

    private PlayerController playerController;
    
    void Collect()
    {
        if(playerController == null)
        {
            PlayerController playerController = gameObject.AddComponent<PlayerController>();
        }
        playerController.AddFuel(.5f);
    }
    

    我不得不做出很多猜测,但我希望这会有所帮助:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-18
      • 1970-01-01
      • 2020-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-11
      • 2017-05-06
      相关资源
      最近更新 更多