问题描述
我正在尝试处理对象生成器,但是它不能如我所愿。每当我的计时器通过对象的maxTime时,它都应该创建一个新对象,但是它只会执行一次并且在错误的位置(超出我的范围)。 这是我的代码:
public class Spawner : MonoBehavIoUr {
public float maxTime = 10;
private float timer = 0;
public GameObject obstacle;
private float width = (Screen.width)/2; //It doesn't recognize width as the variable that refeers the width of the screen,so i tried it
private float maxTime0 = 10;
public int pontos = 5;
public float score;
void Start() {
GameObject new_obstacle = Instantiate(obstacle);
new_obstacle.transform.position = transform.position + new Vector3(Random.Range(-width,width),0);
}
void Update()
{
if(timer > maxTime) {
GameObject new_obstacle = Instantiate(obstacle);
new_obstacle.transform.position = transform.position + new Vector3(Random.Range(-width,0);
if(new_obstacle.transform.position.y < (Screen.height - 7)){
DestroyImmediate(new_obstacle,true);
}
timer = 0;
maxTime = 0.9f * maxTime;
}
score += pontos;
timer += Time.deltaTime;
}
}
解决方法
听起来主要是因为您以 pixel 坐标生成了对象,因为Screen.width
是 pixels 的屏幕宽度。
但是您更想要的是在Camera
的平截头体中产生。
团结提供了一种找到Frustrum Size At Distance的方法。
因为您还要检查
if(new_obstacle.transform.position.y < (Screen.height - 7))
要销毁您的物件,我敢打赌您的Update
确实会产生该物件,但会立即销毁它们!
原因:您的生成者处于世界坐标,并且可能始终位于像素坐标的Screen.height - 7
下!
由于您没有在Start
中签入,这是它为您“工作”的唯一时间。
如果您真的需要此检查,则需要使用Camera.WorldToScreenPoint
Camera camera;
void Start()
{
camera = Camera.main;
// assuming that your camera points exactly forward (2D game like)
var distance = Mathf.Abs(transform.position.z - camera.tramsform.position.z);
var frustumHeight = 2.0f * distance * Mathf.Tan(camera.fieldOfView * 0.5f * Mathf.Deg2Rad);
var frustrumWidth = frustumHeight * camera.aspect;
// not anymore in pixel space but frustrum width in world coordinates
// at the z distance of the spawner
width = frustrumWidth / 2f;
var new_obstacle = Instantiate(obstacle);
new_obstacle.transform.position = transform.position + Vector3.right * Random.Range(-width,width);
}
void Update()
{
if(timer > maxTime)
{
var new_obstacle = Instantiate(obstacle);
new_obstacle.transform.position = transform.position + Vector3.right * Random.Range(-width,width);
if(camera.WorldToScreenPoint(new_obstacle.transform.position).y < Screen.height - 7)
{
DestroyImmediate(new_obstacle,true);
}
timer = 0;
maxTime = 0.9f * maxTime;
}
// as mentioned here multiply by Time.deltaTime in order to
// convert from pontos per frame into pontos per second
score += pontos * Time.deltaTime;
timer += Time.deltaTime;
}
是的,那么您可以使用Coroutine,它通常更易于维护..实际上是一种口味问题
void Start()
{
camera = Camera.main;
// assuming that your camera points exactly forward (2D game like)
var distance = Mathf.Abs(transform.position.z - camera.tramsform.position.z);
var frustumHeight = 2.0f * distance * Mathf.Tan(camera.fieldOfView * 0.5f * Mathf.Deg2Rad);
var frustrumWidth = frustumHeight * camera.aspect;
// not anymore in pixel space but frustrum width in world coordinates
// at the z distance of the spawner
width = frustrumWidth / 2f;
StartCoroutine(SpawnRoutine());
}
IEnumerator SpawnRoutine()
{
// looks dangerous but is fine for Coroutines as long as you yield somewhere
while(true)
{
var new_obstacle = Instantiate(obstacle);
new_obstacle.transform.position = transform.position + Vector3.right * Random.Range(-width,true);
}
// In Coroutines a yield tells Unity to "pause" here,// render this frame and continue from here in the next frame
yield return new WaitForSeconds(maxTime);
maxTime = 0.9f * maxTime;
}
}
private void Update()
{
score += pontos * Time.deltaTime;
}