简体   繁体   English

如何统一处理随机生成的障碍物?

[英]How to handle a random spawner of obstacles in unity?

I'm trying to handle a object spawner but it isn't work as i wish.我正在尝试处理一个对象生成器,但它不能如我所愿。 It should create a new object every time my timer pass the maxTime of the object, but it does it just once and in the wrong position (out of my range).每次我的计时器通过对象的 maxTime 时,它​​都应该创建一个新对象,但它只执行一次并且在错误的位置(超出我的范围)。 Here is my code:这是我的代码:

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, 0);
    }

    void Update()
    {
        if(timer > maxTime) {
            GameObject new_obstacle = Instantiate(obstacle);
            new_obstacle.transform.position = transform.position + new Vector3(Random.Range(-width, width), 0, 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; 
    }
}

It sounds like the main issue is that you spawn the object in pixel coordinates since Screen.width is the Screens width in pixels .这听起来像的主要问题是,你在产卵像素坐标的对象,因为Screen.width是屏幕像素宽度。

But what you rather want is spawning in the extends of the Camera 's frustrum.但是你更想要的是在Camera的截头体的延伸部分产生。

Unity provides a way of finding that Frustrum Size At Distance . Unity 提供了一种在距离处找到视锥体大小的方法。

Since you then also check既然你也检查

   if(new_obstacle.transform.position.y < (Screen.height - 7))

to destroy your object I bet your Update indeed spawns the object but immediately destroys them!销毁您的对象我敢打赌,您的Update确实会生成该对象,但会立即销毁它们!

Reason: Your spawner is in World coordinates and probably always under the Screen.height - 7 which is in pixel coordinates!原因:你的Screen.height - 7在世界坐标中,并且可能总是Screen.height - 7下,像素坐标!

Since you don't have this check in Start it is the only time that it "works" for you.由于您没有在Start进行此检查,因此它是唯一一次对您“有效”。

If you really need this check at all you would need to convert the position into screen pixel space using Camera.WorldToScreenPoint如果你真的需要这个检查,你需要使用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; 
}

and yes then you could use a Coroutine which is often a bit easier to maintain .. a matter of taste actually是的,那么你可以使用一个协程,它通常更容易维护......实际上是一个品味问题

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, width);

        if(camera.WorldToScreenPoint(new_obstacle.transform.position).y < Screen.height - 7)
        {
            DestroyImmediate(new_obstacle, 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; 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM