unity3d 将对象添加到列表中“OnEnable”之前

sc4hvdpw  于 2022-11-15  发布在  其他
关注(0)|答案(2)|浏览(118)

我有一个目标列表,当我示例化我游戏对象时,我将这个对象添加到一个列表中,并使用PlayerPrefs为我的对象设置一个Id。我的问题是我调用了一个使用列表的方法onEnable,因为OnEnable发生在脚本的下一行之前,我得到一个ArgumentOutOfRangeException。我可以禁用我的预置,但我不喜欢的想法,如果有人激活它错误,它会给予我一个错误。有人知道我如何添加对象到我的列表之前,“启用”发生?
这是我最后示例化游戏对象的脚本:

private void CreateTargetOnNetwork(Vector3 position, Quaternion rotation)
    {
        PlayerPrefs.SetInt("Index", index);
        targetsList.Add(Instantiate(Resources.Load("TargetPrefabNetwork") as GameObject, position, rotation, areaTargetManager.GetCurrentArea().transform));
        index++;
    }
    [PunRPC]
    private void UpdateTargetOnOffOnNetwork(int id, bool status)
    {
        targetsList[id].SetActive(status);
    }

这是我在游戏对象上的脚本:

private void Awake()
    {
        _targetIndex = PlayerPrefs.GetInt("Index");
        PlayerPrefs.DeleteKey("Index");
        targetManager = FindObjectOfType<TargetManager>();
        targetManagerPhotonView = targetManager.GetComponent<PhotonView>();
    }
    private void OnEnable()
    {
        targetManagerPhotonView.RPC("UpdateTargetOnOffOnNetwork", RpcTarget.AllBuffered, _targetIndex, true);
    }

我使用光子,但这不是我的问题,所以RPC就像调用一个方法。

sauutmhj

sauutmhj1#

您可以使用较早的执行顺序向示例化的GameObject添加第二个组件,并让该组件在其初始化期间调用静态事件,该事件将在其他组件初始化之前发生。

[DefaultExecutionOrder(-1000)]
public sealed class OnBefore : MonoBehaviour
{
    public static event Action<GameObject> Enabled;
    public static event Action<GameObject> Disabled;
    
    private void OnEnable() => Enabled?.Invoke(gameObject);
    private void OnDisable() => Disabled?.Invoke(gameObject);
}

用法:

private void CreateTargetOnNetwork(Vector3 position, Quaternion rotation)
{
    PlayerPrefs.SetInt("Index", index);
    var prefab = Resources.Load<GameObject>("TargetPrefabNetwork");
    
    OnBefore.Enabled += OnBeforeEnabled;
    Instantiate(prefab);
    OnBefore.Enabled -= OnBeforeEnabled;

    index++;

    void OnBeforeEnabled(GameObject instance)
    {
        targetsList.Add(instance, position, rotation, areaTargetManager.GetCurrentArea().transform));
    }
}
qnakjoqk

qnakjoqk2#

我能想到的一个解决方案是相反的,通过一个标志来防止OnEnable在一个特殊的初始化情况下出现。
然后,在将其添加到列表后,显式调用一次,设置标志,并从那里开始使用OnEnable
通过一些重构,我可能会做如下操作

private Action<YourTargetClass> onEnableDisable;
private bool initialized;

public int Index => _targetIndex;

public void Initialize(int index, Action<YourTargetClass> onEnableDisableCallback)
{
    _targetIndex = index;
    onEnableDisable = onEnableDisableCallback;
    initialized = true;

    onEnableDisable?.Invoke(this);
}

private void OnEnable()
{
    if(initialized) onEnableDisable?.Invoke(this);
}

private void OnDisable()
{
    if(initialized)  onEnableDisable?.Invoke(this);
}

然后装上

private void CreateTargetOnNetwork(Vector3 position, Quaternion rotation)
{
    var targetPrefab = Resources.Load("TargetPrefabNetwork");
    var newTarget = Instantiate(targetPrefab);
    targetsList.Add(newTarget, position, rotation, areaTargetManager.GetCurrentArea().transform));

    newTarget.Initialize(index, OnTargetEnableDisable);

    index++;
}

// Leave all networked code together
// Your target doesn't need to know 
private void OnTargetEnableDisable(YourTargetClass target)
{
    photoView.RPC(nameof(UpdateTargetOnOffOnNetwork), RpcTarget.AllBuffered, target.Index, target.enabled));
}

[PunRPC]
private void UpdateTargetOnOffOnNetwork(int id, bool status)
{
    targetsList[id].SetActive(status);
}

相关问题