【问题标题】:List add function isn't performing correctly列表添加功能未正确执行
【发布时间】:2018-11-16 20:51:44
【问题描述】:

我的代码:

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

public class BattleCore : MonoBehaviour {

public List<GameObject> Enemy = new List<GameObject> ();
public List<EnemyFollow1> EnemyScript =  new List<EnemyFollow1>();
public List<StatData> stat = new List<StatData> ();
public int length;
public bool canMelee = false;
public List<ParticleSystem> ps = new List<ParticleSystem> (); 
public float AttackCooldownT = 0;
public float AttackCooldownTI = 3;

void OnTriggerEnter(Collider other)
{
    Debug.Log("ENTERED!");
    if (other.CompareTag("Enemy"))
    {
        canMelee = true;
        Enemy.Add (other.gameObject);
        for (int i = 0; i < Enemy.Count; i++)
        {
            ps.Add(Enemy[i].GetComponent<ParticleSystem>());
            EnemyScript.Add(Enemy[i].GetComponent<EnemyFollow1>());
            stat.Add(EnemyScript[i].enemyData);
        }
    }
}

void OnTriggerExit(Collider other) {
    if (other.CompareTag("Enemy"))
    {
        canMelee = false;       
        for (int i = 0; i < length; i++)
        {
            if (Enemy[i] == other.gameObject) 
            {
                Enemy.RemoveAt(i);
                stat.RemoveAt(i);
                EnemyScript.RemoveAt(i);
                ps.RemoveAt (i);
            }
        }
    }
}

void Update()
{
    if (canMelee && Input.GetKeyDown(KeyCode.Q) && Time.time > AttackCooldownT && Enemy.Count > 0)
    {
        for (int i = 0; i < Enemy.Count; i++)
        {
            stat[i].HP -= 20;
            ps [i].Play ();
        }
        AttackCooldownT = Time.time + AttackCooldownTI;
    }
}
}

我创建了一些对象(敌人)的列表,其中包含一些我用统一的可脚本对象制作的数据列表。这个脚本添加和删除敌人和 这个脚本工作正常,但是当有 2 个敌人时,许多敌人(同一个游戏对象开始多次添加)并且在删除所有数据时不会被删除,所以即使我杀死了一个敌人,他仍然在场景中。

我的项目数据:

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

[CreateAssetMenu]
public class StatData : ScriptableObject {

    public string Name;
    public bool Boss;
    public int HP, MaxHP, Atk, MaxAtk, SpAtk, MaxSpAtk, Def, MaxDef, SpDef, MaxSpDef;
    public Sprite sprite;
}

另外,当我试图用相同的统计数据杀死一个敌人时,两个敌人同时死亡,而我只攻击一个。由于健康是全球性的,两者都会死亡。我不知道如何解决它。

在我的敌人跟随我写道:

enemyStat.HP = enemyStat.MaxHP;

在新游戏中让敌人活着。 请帮忙!

【问题讨论】:

  • 短语“当我试图杀死一个具有相同统计数据的敌人时,两个敌人一起死,而我只攻击一个”表示您可能复制了对对象的引用,而不是创建一个新的副本那个物体。因此,您的列表包含对同一对象的两个引用。
  • 我想帮助你,但是我注意到你还有一些其他的问题显然有答案,但你没有接受它们作为答案。
  • Richardissimo 我趋之若鹜,但没有奏效。我应该做公众浮动健康吗?

标签: c# unity3d arraylist


【解决方案1】:

这是parallel collections anti-pattern 的示例:

Enemy.RemoveAt(i);
stat.RemoveAt(i);
EnemyScript.RemoveAt(i);
ps.RemoveAt (i);

您应该避免这样做,因为它会在您的数组中创建不受任何强制执行的依赖项。例如,如果您尝试对其中一个数组进行排序,则会破坏索引之间的关系。

您应该创建一个“包装器”对象,将这些不同的对象绑定在一起,然后创建一个列表。

class EnemyCollator {
    public GameObject go;
    public EnemyFollow1 script;
    public StatData stats;
    public ParticleSystem particles;
}
...
public List<EnemyCollator> allEnemies;

如果您希望您的数据具有查找关系(即“找到与此 GameObject 关联的数据”),请使用字典:

public Dictionary<GameObject,EnemyCollator> dataLookup;

或者使用 Linq 查询:

GameObject go = allEnemies.Find(x => x.go == someGameObject);

一旦您开始以这种方式组织代码,您遇到的问题很可能就会消失。

【讨论】:

  • @GamingForever 不要忘记对您认为有帮助的任何帖子进行投票,并将答案标记为“已接受”(您可以选择哪一个;因此,这通常被视为“最正确”的答案)。
【解决方案2】:

理解和阅读您的代码非常困难。

但是我确实注意到了一些可能对你有帮助的事情。

当您创建脚本对象并将其分配给多个其他脚本/游戏对象时,它们都将引用同一个脚本对象。因此,更改运行状况将更改所有调用它的对象的运行状况参考。

有几种方法可以解决这个问题,但我认为最简单的实现方式是:

当你实例化它时(或在它是 Awake 时)将变量从 StatData 分配给你的 Enemyscript

public class EnemyFollow1 : MonoBehaviour
{
    public string Name;
    public bool Boss;
    public int HP, MaxHP, Atk, MaxAtk, SpAtk, MaxSpAtk, Def, MaxDef, SpDef, MaxSpDef;
    public Sprite sprite;

    [SerializeField]
    private StatData statData;

    void Awake()
    {
        Name = statData.Name;
        Boss = StatData.Boss;
        // Etc...
    }
}

现在您始终可以确定正确敌人的生命值已得到修改。 您也可以使用您拥有的游戏对象列表调用此脚本所以您不需要“EnemyFollow1 列表。

Enemy[i].GetComponentInChildren<EnemyFollow1>().HP -= 20;

// You can remove these
public List<EnemyFollow1> EnemyScript =  new List<EnemyFollow1>();
public List<StatData> stat = new List<StatData> ();

我也不确定你是否理解这一点。但是从列表中删除一个游戏对象,并不会破坏它! 因此,如果您想在 从列表中删除游戏对象后销毁它,请使用

Destroy(Enemy[i]);

【讨论】:

  • 不知何故,某些东西正在破坏/禁用您的游戏对象。我必须看看你的其他脚本,因为游戏对象不会自动销毁。
  • 我实际上在另一个脚本中销毁了它,所以这不是问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-27
  • 1970-01-01
  • 2013-08-11
  • 2018-06-29
  • 2021-01-22
  • 2013-05-10
相关资源
最近更新 更多