在 Unity 中,如何根据另一个脚本中的随机选择动态修改游戏对象标签?

问题描述

问题

我正在尝试制作一个气泡/气球爆破器风格的游戏,并有一个 Spawner 脚本 (Spawner.cs) 来保存一个对象(气泡)池,然后这个 Spawner 脚本随机选择其中一个对象在游泳池里。

从这里开始,附加到池中所有气泡的另一个脚本 (Bubble.cs) 应该检查 Spawner 脚本以查看池中的哪个气泡当前被选为安全气泡。如果此气泡与当前的 safeBubble 匹配,则气泡应将其标签更改为“Safe”,如果与 safeBubble 不匹配,则其标签应为“Bad”。

似乎 Bubble.cs 最初确实进行了检查和设置(当我第一次点击播放时),但只有这样,他们才不会在选择第一个 safeBubble 后取消设置/重新检查,就像它应该的那样。

>

这个想法是 safeBubble 以随机间隔变化,因此活动/产生的气泡上的标签该改变以反映它们是“安全”还是“坏”。


代码和我尝试过的

这是我的脚本,唯一没有提供的脚本是 GM.cs,但那只是分数管理器。

Bubble.cs

  public class Bubble : MonoBehavIoUr{

  public Spawner spawner;

  public float popPoint = 10f;
  public float spinSpeed;
    public float riseSpeed;

  public AudioSource popAudio;

  public bool safe;

    void Start(){
      transform.name = transform.name.Replace("(Clone)","").Trim();
      riseSpeed= Random.Range(0.05f,0.1f);
      spinSpeed= Random.Range(0.1f,0.5f);

      if (this.gameObject == spawner.safeBubble) {
        this.tag ="Safe";
      } else{
        this.tag ="Bad";
      }
    }

    void Update(){
      if ( this.gameObject == spawner.safeBubble ){
        this.tag ="Safe";
      } else {
        this.tag ="Bad"; 
      }

      transform.Translate (Vector3.up * riseSpeed,Space.World);
        transform.Rotate (Vector3.right * 2* Time.deltaTime);
        transform.Rotate (Vector3.up * spinSpeed* Time.deltaTime);

        if(gameObject.transform.position.y >= popPoint ){
            gameObject.SetActive(false);
        }
    }

}

Spawner.cs

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

public class Spawner : MonoBehavIoUr{
  public int index;
  public int randomIndex;

  public List<GameObject>[] pool;
  public GameObject[] bubbles;

  public GameObject greenBubble;
  public GameObject orangeBubble;
  public GameObject pinkBubble;
  public GameObject purpleBubble;
  public GameObject redBubble;
  public GameObject blueBubble;

  public GameObject safeBubble;

  public float timeBetweenSpawns;
  public float speed = 1.0f;

  public float swapTime;
  public Transform spawnLoc;

  public Vector3 Position1;
  public Vector3 Position2;

  public Image BubbletoPopImg;
    public Sprite green;
    public Sprite orange;
    public Sprite pink;
    public Sprite purple;
    public Sprite red;
    public Sprite blue;

  public bool willGrow = true;

  void Awake(){
        bubbles = new GameObject[6];
        bubbles [0] = greenBubble;
        bubbles [1] = orangeBubble;
        bubbles [2] = pinkBubble;
        bubbles [3] = purpleBubble;
        bubbles [4] = redBubble;
        bubbles [5] = blueBubble;



        safeBubble = bubbles[Random.Range(0,5)];

        swapTime = Random.Range (2f,3f);
        // Randomiser ();

        timeBetweenSpawns = Random.Range (0.6f,1.2f);

        InvokeRepeating ("Spawn",1f,timeBetweenSpawns);

        pool = new List<GameObject>[bubbles.Length];
        for (int i = 0; i < bubbles.Length; i++){
            pool[i] = new List<GameObject>();
        }
    // Debug.Log("Safe Bubble is " + safeBubble);

    }


  public GameObject GetPooledobject(){

        randomIndex = Random.Range(0,pool.Length);

        for (int i = 0; i < pool[randomIndex].Count; i++){
            GameObject go = pool[randomIndex][i];
            if (!go.activeInHierarchy){
                return go;
            }
        }

        if (willGrow){
            GameObject obj = (GameObject)Instantiate(bubbles[randomIndex]);
            pool[randomIndex].Add(obj);
            return obj;
        }
        return null;
    }


  public void Spawn(){
        GameObject bubbles = GetPooledobject ();
        if(bubbles != null){
            bubbles.transform.position = spawnLoc.transform.position;
            bubbles.transform.rotation = spawnLoc.transform.rotation;
            bubbles.SetActive(true);
        }

    }


  void Update(){
        transform.position = Vector3.Lerp (Position1,Position2,Mathf.PingPong(Time.time*speed,1.0f));
    timeBetweenSpawns -= Time.deltaTime;
    swapTime -= Time.deltaTime;

        if(timeBetweenSpawns<=0){
            timeBetweenSpawns = Random.Range (0.6f,1.1f);
        }

        if(swapTime <= 0){
            Randomiser ();
            swapTime = Random.Range (3f,6f);
        }


     switch(index){
        case 5: BubbletoPopImg.sprite = blue; break;
        case 4: BubbletoPopImg.sprite = red; break;
        case 3: BubbletoPopImg.sprite = purple; break;
        case 2: BubbletoPopImg.sprite = pink; break;
        case 1: BubbletoPopImg.sprite = orange; break;
        case 0: BubbletoPopImg.sprite = green; break;
      }

    }

  public void Randomiser(){
        index = randomIndex;
        safeBubble = bubbles[index];
    // Debug.Log("Safe Bubble is " + safeBubble);
    }

}

Popper.cs

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

public class Popper : MonoBehavIoUr{

    public GM gm;

    void Update(){
      if (Input.GetMouseButtonDown(0)) {
        Shoot();
      }
    }

    void Shoot(){
      RaycastHit hit;
      Ray ray = GetComponent<Camera>().ScreenPointToRay(Input.mousePosition);
      if (Physics.Raycast(ray,out hit)) {

        if(hit.collider.tag == "Bad"){
            Debug.Log("Ouch");
        }
        
        if(hit.collider.tag == "Safe"){
            Debug.Log("Nice");
        }
        
      }
      
    }
    
}

我虽然在 Bubble.cs 的 Start 和 Update 函数中设置和检查标签的简单 if 语句会起作用,但它不起作用,我只是没有设法弄清楚. 我也试过使用 switch,但结果相同。


非常感谢任何帮助。

提前致谢。

解决方法

this.gameObject == spawner.safeBubble

您检查现有对象是否与您的预制件相同。

这当然会永远是真的!


相反,只需在您选择预制件后立即在预制件上设置标签

 // Note that here was another mistake: The maxValue is EXCLUSIVE
 // so Random.Range(0,5) returns the values 0 to 4!
 // rather simply use the length of the array
 safeBubble = bubbles[Random.Range(0,bubbles.Length)];
 foreach(var bubble in bubbles)
 {
     bubble.tag = bubble == safeBubble ? "Safe" : "Bad";
 }

这样每次您根据预制件 Instantiate 时,标签已经正确设置,以后无需从气泡本身执行此操作。

,

您可以在bubble.cs中添加一个函数(public)来切换bubble脚本的变量safe,然后在分配safebubble后从spawner.cs中调用它(您也必须在下次分配之前调用它) .

所以,在bubble.cs中添加这个

public void changestate()
{
safe = !safe ;
if (safe) this.Tag = "Safe";
else this.Tag = "Bad";
}

注意:我建议在上面的脚本中将“this”更改为“gameObject”。

现在,在 Spawner.cs 中,分配安全气泡后,您可以执行此操作..

safebubble.GetComponent<Bubble>().changestate();

在更改安全气泡以将其切换回坏之前,您应该做同样的事情。

在我看来,使用像这样不使用更新函数的代码对性能有好处。

我希望理解它并发现它有帮助。

额外:如果你对第一个代码感到困惑,你可以这样做..

public void makesafe() {this.Tag = "Safe";}
public void makebad() {this.Tag = "Bad";}

然后你可以像这样在 spawner 中使用它们..

safebubble = bubbles[Random.Range(0,5)];
safebubble.GetComponent<Bubble>().makesafe();

随机化函数应该是这样的..

public void Randomizer()
{
    if (safebubble != null) safebubble.GetComponent<Bubble>().makebad();
    index = randomindex;
    safebubble = bubbles[randomindex];
    safebubble.GetComponent<Bubble>().makesafe();

}

抱歉给您不好的解释。