问题描述
问题
我正在尝试制作一个气泡/气球爆破器风格的游戏,并有一个 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();
}
抱歉给您不好的解释。