【问题标题】:Trouble Checking A List检查列表时遇到问题
【发布时间】:2014-12-20 03:19:25
【问题描述】:

好吧,看来我正在重新解决这个问题。我正在经历的是,我想你可以说当我“消失”一个怪物(玩家已经杀死它)并“重生”它时,它会将所有动作重新添加到列表中。例如:

怪物 A 在他的列表中有 2 个动作:Scratch & Growl... 怪物 A 死了...... 怪物 A 重生... 怪物 A 现在在他的列表中有 4 个动作:Scratch & Growl...AND...抓挠和咆哮...

这是我的代码:

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

 public class MonsterMoves : MonoBehaviour {

 public List<BaseMove> moves;
 public int level;
 public Scratch scratch = new Scratch();
 public Growl growl = new Growl();
 public FireBall fireball = new FireBall();
 public PowerUp powerup = new PowerUp();

 void Start(){
     moves = gameObject.GetComponent<Monster>().monstersMoves;
     level = gameObject.GetComponent<Monster>().level;
 }

 void Update(){
     level = gameObject.GetComponent<Monster>().level;
     SetupMoves(level);
 }

 private void SetupMoves(int level){
     if(level >= 1 && !moves.Contains(scratch)){
         moves.Add(scratch);
     }
     if(level >= 1 && !moves.Contains(growl)){
         moves.Add(growl);
     }
     if(level >= 7 && !moves.Contains(fireball)){
         moves.Add(fireball);
     }
     if(level >= 10 && !moves.Contains(powerup)){
         moves.Add(powerup);
     }

对我忽略的内容有什么想法吗?

回答一些cmets:

当怪物死去时,它的脚本(简称 Monster)会这样调用:

public void SetDead(){
    isAlive = false;
    timeOfDeath = Time.time;

    ReSpawner.deadMonster.Add(this);

    this.gameObject.SetActive(false);
}

这会处理“消失”怪物,而不是实际摧毁它。然后是处理重生的这个脚本:

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

public class ReSpawner : MonoBehaviour {

public float spawnDistance = 50.0f;
public float minSpawnDensity = 6f;
public float minSpawnDistance = 20f;
public int respawnDelay = 10;
public static List<Monster> deadMonster = new List<Monster>();

private Vector3 spawnPoint;
private Vector3 lastSpawnPoint = Vector3.zero;

void Update(){
    for(var i = 0; i < deadMonster.Count; i++){
        Monster monster = deadMonster [i];

        float time = Time.time - monster.timeOfDeath;

        if(time > respawnDelay)
        {
            monster.gameObject.SetActive(true);
            monster.isAlive = true;
            monster.gameObject.rigidbody.WakeUp();
            monster.gameObject.GetComponent<Animator>().enabled = true;
            monster.gameObject.GetComponentInChildren<MonsterAI>().enabled = true;
            spawnPoint = new Vector3(Random.Range(0, 2000), Random.Range(0, 2000), Random.Range(0, 2000));
            spawnPoint.y = TerrainHeight(spawnPoint);
            if(!IsInvalidSpawnPoint(spawnPoint, lastSpawnPoint)){
                NavMeshHit closestHit;
                if(NavMesh.SamplePosition(spawnPoint, out closestHit, 500, 1)){
                    spawnPoint = closestHit.position;
                }else{
                    Debug.Log("...");
                }
                monster.gameObject.transform.position = spawnPoint;
                monster.SetupMonster();
                deadMonster.RemoveAt(i);
                i--;
            }
        }
    }
}

private bool IsInvalidSpawnPoint(Vector3 spawnPoint,Vector3 lastSpawnPoint){
    if(spawnPoint.y == Mathf.Infinity || (spawnPoint - lastSpawnPoint).magnitude <= minSpawnDensity){
        return true;
    }else{
        return false;
    }
}

private float TerrainHeight(Vector3 spawnPoint){
    Ray rayUp = new Ray(spawnPoint, Vector3.up);
    Ray rayDown = new Ray(spawnPoint, Vector3.down);
    RaycastHit hitPoint;
    if(Physics.Raycast(rayUp, out hitPoint, Mathf.Infinity)){
        return hitPoint.point.y;
    }
    else if(Physics.Raycast(rayDown, out hitPoint, Mathf.Infinity)){
        return hitPoint.point.y;
    }else{
        return Mathf.Infinity;
    }
}

}

我不愿发布整个“怪物”脚本,因为它相当广泛。

所以我做了一些改变。现在,每当第一次创建怪物时,我都会调用该函数,以及是否/何时升级。这是 MonsterMoves 的新脚本...

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

[System.Serializable]
public class Moves : MonoBehaviour {

public List<Move> moves;
public List<Move> movesToLearn = new List<Move>();

void Start(){
    moves = gameObject.GetComponent<Monster>().monstersMoves;
}

public void AddMoves(int level, List<Move> moves){
    foreach(Move move in movesToLearn){
        if(level >= move.levelLearned){
            if(!moves.Contains(move)){
                moves.Add(move);
            }
        }
    }
}

}

我在处理怪物所有属性的脚本中调用这个函数。如果 Move 列表中已经包含该 move,我不想再次添加它。但是,它仍然无法正常工作。它仍在将移动添加到列表中,即使它已经在列表中。

【问题讨论】:

  • 杀死的时候叫什么,带回来的时候叫什么。其他类的一些代码可能有助于弄清楚它在做什么。
  • 顺便说一句,你能用一组动作代替一个列表吗?
  • @9000 我不太清楚你的意思。您是否建议我将其硬编码到 Monster 类中?如果是这样就不行了,因为 Monster 类只是所有怪物的泛型,但并非所有怪物都有相同的攻击。
  • 9000 建议 List 移动为 Set 移动,这是一个很好的建议,但不是导致问题的原因
  • 我建议你创建一个minimal, self-contained example。这将帮助您自己找到问题或帮助我们查看问题。

标签: c# list unity3d


【解决方案1】:

在重生之前将怪物 A 从列表中移除!

【讨论】:

  • 不太清楚你的意思。怪物 A 不在列表中。怪物 A 有一个 BaseMove 列表。 (每个动作都源自 BaseMove)。
  • 这可能不是问题,但它提出了一个很好的问题,你是如何“消灭”怪物 A 的?
  • 我不这么认为。只是不要添加它们两次。没有理由为了重新填写而清除列表,这是低效的。
  • 您建议我在何时何地重置列表? ...为什么?
猜你喜欢
  • 1970-01-01
  • 2021-12-18
  • 2013-12-17
  • 1970-01-01
  • 2017-11-22
  • 2016-12-18
  • 1970-01-01
  • 2021-08-04
  • 1970-01-01
相关资源
最近更新 更多