Unity让物体根据实时坐标进行快速生成

我想实现:给一组坐标,轮流读取这些坐标,每次读到新坐标时物体就在此刻的坐标生成,同时上次生成的物体消失。

using UnityEngine;

public class CoordinateSpawner : MonoBehaviour
{
    public GameObject Prefab;
    public Vector3[] coordinates;
    private GameObject lastInstance;

    void Start()
    {
        // 循环遍历坐标数组
        foreach (Vector3 coord in coordinates)
        {
            // 如果 lastInstance 不为空,则销毁它
            if (lastInstance != null)
            {
                Destroy(lastInstance);
            }

            // 在 coord 处实例化 Prefab 的副本
            lastInstance = Instantiate(Prefab, coord, Quaternion.identity);
        }
    }
}

望采纳

望采纳


要实现这个效果,你可以创建一个脚本,定时读取当前的坐标并创建物体。你可以使用 InvokeRepeating 方法来定时调用函数,如下所示:

using UnityEngine;

public class Spawner : MonoBehaviour
{
    // 物体预制
    public GameObject prefab;

    // 生成物体的间隔(秒)
    public float interval = 1.0f;

    void Start()
    {
        // 每隔 interval 秒调用一次 SpawnObject 函数
        InvokeRepeating("SpawnObject", 0, interval);
    }

    void SpawnObject()
    {
        // 在当前坐标生成物体
        Instantiate(prefab, transform.position, Quaternion.identity);
    }
}

上述代码中,我们在 Start 函数中调用 InvokeRepeating 方法来定时调用 SpawnObject 函数。每当 SpawnObject 函数被调用时,它会在当前坐标生成一个新的物体。


为了让上一次生成的物体消失,可以在生成新物体之前先销毁之前的物体。这可以通过让 SpawnObject 函数维护一个变量来存储当前生成的物体,然后在生成新物体之前销毁之前的物体,如下所示:

using UnityEngine;

public class Spawner : MonoBehaviour
{
    // 物体预制
    public GameObject prefab;

    // 生成物体的间隔(秒)
    public float interval = 1.0f;

    // 当前生成的物体
    private GameObject currentObject;

    void Start()
    {
        // 每隔 interval 秒调用一次 SpawnObject 函数
        InvokeRepeating("SpawnObject", 0, interval);
    }

    void SpawnObject()
    {
        // 销毁之前生成的物体
        if (currentObject != null)
        {
            Destroy(currentObject);
        }

        // 在当前坐标生成物体
        currentObject = Instantiate(prefab, transform.position, Quaternion.identity);
    }
}

在这段代码中,我们在 SpawnObject 函数中维护了一个变量 currentObject 来存储当前生成的物体。每当 SpawnObject 函数被调用时,它会先销毁之前的物体,然后再在当前坐标生成新的物体。

unity 地图物体的随机生成

对一些2d游戏反复用一个关卡,但不希望每次的地图中物体出现的都一样,这就需要用到随机生成地图的方法;怪物也是如此;

首先要得到各种预制体;

如

 public GameObject[] OutwallArray;
    public GameObject[] leaArray;
    public GameObject[] wallArray;
    public GameObject[] foodPrefab;
    public GameObject[] enemyPrefab;
    public GameObject ExitPrefab;
当然我只是举个例子;

最关键的就是要定义一个队列

private List<Vector2> wallList = new List<Vector2>();

关于坐标的队列;

wallList.Clear();
        for(int x=2;x<cols-2;x++)
        {
            for(int y=2;y<rows-2;y++)
            {
                wallList.Add(new Vector2(x, y));
            }
        }

首先要将他清空,因为每次都要用这个队列,然后就是要将你所需要产生物体的平面坐标范围内加入到队列当中;

 private Vector2 RandomPosition()
    {
        int Index = Random.Range(0, wallList.Count);
        Vector2 pos = wallList[Index];
        wallList.RemoveAt(Index);
        return pos;
    }

这是一个从队列当中随机产生一个索引给与你想要产生的物体,这样它的坐标就会随机产生且不会重复;


例子:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
 
public class TestRoomJudget : MonoBehaviour {
 
    #region
    //摄像机朝向的目标模型
    public Transform target;//玩家操控 的 人物
    public GameObject BaseWall;//基础墙壁
 
    int leng = 10;//向量坐标 长度
    float posx;//物体 坐标X,Y,Z
    float posy;
    float posz;
 
    float scalx;
    float scaly;
    float scalz;
 
    Vector3 dirX;//6个方向的向量
    Vector3 dirX_;
    Vector3 dirY;
    Vector3 dirY_;
    Vector3 dirZ;
    Vector3 dirZ_;
 
    Vector3 A1;
    Vector3 A2;
    Vector3 A3;
    Vector3 A4;
    Vector3 B1;
    Vector3 B2;
    Vector3 B3;
    Vector3 B4;
 
    float unitlength1;//墙壁 的单位长度
    float unitlength2;//一半 的单位长度
    float Yf;
 
    private Transform maincamera;//找到 主摄像机
 
    #endregion
    // Use this for initialization
    void Start ()
    {
        maincamera = GameObject.Find("Main Camera").transform;//找到 主摄像机
 
        unitlength1 = target.transform.lossyScale.x;// Debug.DrawLine(transform.position, PCube.transform.position, Color.green);//Debug.DrawLine(ray.origin, hit.point, Color.green);
        unitlength2 = target.transform.lossyScale.x/2;
        posx = transform.position.x; posy = transform.position.y; posz = transform.position.z;
        //Debug.DrawLine(transform.position, transform.position + new Vector3(1,0,0), Color.red);
         //new Vector3(maincamera.position.x,target.transform.position.y,maincamera.position.z);
        dirX = new Vector3(posx + leng, posy, posz);
        dirX_ = new Vector3(posx - leng, posy, posz);
        dirY = new Vector3(posx, posy + leng, posz);
        dirY_ = new Vector3(posx, posy - leng, posz);
        dirZ = new Vector3(posx, posy, posz + leng);
        dirZ_ = new Vector3(posx, posy, posz - leng);
        
        scalx = transform.localScale.x / 2;
        scaly = transform.localScale.y / 2;
        scalz = transform.localScale.z / 2;
 
        A1 = new Vector3(posx + scalx, posy + scaly, posz - scalz);
        A2 = new Vector3(posx + scalx,posy + scaly, posz + scalz);
        A3 = new Vector3(posx - scalx,posy + scaly, posz + scalz);
        A4 = new Vector3(posx - scalx,posy + scaly, posz - scalz);
 
        B1 = new Vector3(posx + scalx, posy - scaly, posz - scalz);
        B2 = new Vector3(posx + scalx, posy - scaly, posz + scalz);
        B3 = new Vector3(posx - scalx, posy - scaly, posz + scalz);
        B4 = new Vector3(posx - scalx, posy - scaly, posz - scalz);
 
 
 
        /*JudgetDirWall(dirX);
        JudgetDirWall(dirX_);
        JudgetDirWall(dirY);
        JudgetDirWall(dirY_);
        JudgetDirWall(dirZ);
        JudgetDirWall(dirZ_);*/
        //Test();
        /*
        Debug.Log("A1-A2");
         InstantiateWall_XZ(A1,A2);// varv1 - varv2
         Debug.Log("A2-A3");
         InstantiateWall_XZ(A2,A3);// varv1 - varv2
         Debug.Log("A4-A3");
         InstantiateWall_XZ(A3, A4);// varv1 - varv2
         Debug.Log("A1-A4");
         InstantiateWall_XZ(A4, A1);// varv1 - varv2
         Debug.Log("B1-B2");
         InstantiateWall_XZ(B1, B2);// varv1 - varv2
         Debug.Log("B2-B3");
         InstantiateWall_XZ(B2, B3);// varv1 - varv2
         Debug.Log("B4-B3");
         InstantiateWall_XZ(B4, B3);// varv1 - varv2
         Debug.Log("B1-B4");
         InstantiateWall_XZ(B1, B4);// varv1 - varv2
         */
        InstantiateWall_Y();
    }
 
    private void Update()
    {
        Debug.DrawLine(maincamera.position, target.position, Color.red);
        Debug.DrawLine(new Vector3(maincamera.position.x, target.transform.position.y, maincamera.position.z), target.position, Color.green);
       // Test();
    }
 
    void InstantiateWall_Y()
    {
        float Ynum = transform.localScale.y / unitlength1;//标记点 的 Y轴长度 / 墙壁单位长度   =    Y轴生成的数量
        Debug.Log("Ynum          "+ Ynum);
        for(int k = 0; k<Ynum;k++)
        {//new Vector3(posx - scalx, posy + scaly -, posz - scalz);为最上面平面上的 A1 点
            //向下每隔 一个墙壁 单位 的 Y轴长度 ,为平面 A1-A2-A3-A4 执行生成墙壁的指令
 
            Yf = posy + scaly; //Debug.Log("Yf      " + Yf); Debug.Log("unitlength1      " + unitlength1); Debug.Log("k      " + k);
            Vector3 YWall_1 = new Vector3(posx + scalx, Yf - (unitlength2 + k * unitlength1), posz - scalz);//unitlength1 = target.transform.lossyScale.x
            Vector3 YWall_2 = new Vector3(posx + scalx, Yf - (unitlength2 + k * unitlength1), posz + scalz);
            Vector3 YWall_3 = new Vector3(posx - scalx, Yf - (unitlength2 + k * unitlength1), posz + scalz);
            Vector3 YWall_4 = new Vector3(posx - scalx, Yf - (unitlength2 + k * unitlength1), posz - scalz);
 
            InstantiateWall_XZ(YWall_1, YWall_2 , k);
            InstantiateWall_XZ(YWall_2, YWall_3 , k);
            InstantiateWall_XZ(YWall_3, YWall_4 , k);
            InstantiateWall_XZ(YWall_4, YWall_1 , k);
 
        }//
 
 
    }//
 
    void InstantiateWall_XZ(Vector3 varv1,Vector3 varv2,int g)// varv1 - varv2 X,Z平面判断
    {
        Vector3 testV = varv1 - varv2;//两个点相减  的矢量V
        Debug.Log("两点相减向量 varv1" + varv1 + "   " + "    varv2     " + varv2 + "   " );
 
        //Debug.Log("两点相减向量 testV.x" + testV.x + "   " + "testV.y" + testV.y + "   " + "testV.z" + testV.z);
 
        float[] f = new float[3] { testV.x, testV.y, testV.z};//矢量V 的XYZ坐标
        string[] fs = new string[3] { "testV.x", "testV.y", "testV.z" };//矢量V 的XYZ坐标 的名字
        float ff;//表达 要生成 的 基础 墙壁 的数量
        Vector3 v = new Vector3(1,1,1);//判断 方向 的生成 向量
 
        if (testV.x == 0 || testV.y == 0 || testV.z == 0 )
        {
 
 
           // float jx = 1;
           // float jy = 1;
           // float jz = 1;
            float jx = (float)((varv1.x - posx) / scalx);//判断大小方向
            float jy = (float)((varv1.y - posy) / scaly);
            float jz = (float)((varv1.z - posz) / scalz);
            // Debug.Log("********testV.x " + testV.x+ "********testV.y " + testV.y+ "********testV.z " + testV.z);
            if (testV.x * v.x != 0)
            {
                ff = Mathf.Abs(testV.x);//表达 要生成 的 基础 墙壁 的数量 绝对值
                ff = Mathf.Round(ff);//表达 要生成 的 基础 墙壁 的数量 四舍五入
                //float jx = (float)((varv1.x - posx) / scalx);//判断大小方向
                //float jy = (float)((varv1.y - posy) / scaly);
                //float jz = (float)((varv1.z - posz) / scalz);
                
                // Debug.Log("---varv1.x" + varv1.x);
                // Debug.Log("---posx" + posx);
                // Debug.Log("---varv1.x - posx       " + (varv1.x - posx));
                // Debug.Log("---posx" + posx);
                // Debug.Log("---scalx" + scalx);
 
                //Debug.Log("墙长度 ffx" + ff + "   " + "jXx" + jx + "   " + "jXy" + jy + "   " + "jXz" + jz);
                //X方向创建 ff个
                for (int j = 0; j<ff; j++)
                {//varv1.y - jy * ((float)0.5 + jy * j * 1)
                  Debug.Log("---jy   " + jy);
                    GameObject GO_X = Instantiate(BaseWall, new Vector3(varv1.x - jx*(unitlength2 + j * unitlength1), varv1.y, varv1.z - jz * unitlength2), Quaternion.identity);
 
                    Debug.Log("varv1.y - jy * unitlength2" + (varv1.y - jy * unitlength2) + "   " );
                    //GO_X.transform.parent = transform;
                }//
            }//
 
            if (testV.y * v.y != 0)
            {
                ff = Mathf.Abs(testV.y);//表达 要生成 的 基础 墙壁 的数量 绝对值
                ff = Mathf.Round(ff);//表达 要生成 的 基础 墙壁 的数量 四舍五入
                
 
                //float jx = (float)((varv1.x - posx) / scalx);//判断大小方向
                //float jy = (float)(((varv1.y - posy) / scaly)+g * unitlength1);
                //float jz = (float)((varv1.z - posz) / scalz);
                /*if (jx == 0)
                    jx = 1;
                if (jy == 0)
                    jy = 1;
                if (jz == 0)
                    jz = 1;*/
                // Debug.Log("墙长度 ffy" + ff + "   " + "jXx" + jx + "   " + "jXy" + jy + "   " + "jXz" + jz);
                //X方向创建 ff个
                for (int j = 0; j < ff; j++)
                {
                    GameObject GO_Y= Instantiate(BaseWall, new Vector3(varv1.x - jx * unitlength2, varv1.y, varv1.z - jz * unitlength2), Quaternion.identity);
 
                    Debug.Log("66666666                " +(varv1.y - jy * (unitlength2 + j * unitlength1)) + "   ");
                    // GO_Y.transform.parent = transform;
                }//
            }//
 
            if (testV.z * v.z != 0)
            {
                ff = Mathf.Abs(testV.z);//表达 要生成 的 基础 墙壁 的数量 绝对值
                ff = Mathf.Round(ff);//表达 要生成 的 基础 墙壁 的数量 四舍五入
                
                //Debug.Log("---varv1.x" + varv1.x);
                //Debug.Log("---posx" + posx);
               // Debug.Log("---varv1.x - posx       " + (varv1.x - posx));
               // Debug.Log("---posx" + posx);
               // Debug.Log("---scalx" + scalx);
 
               // Debug.Log("varv1.x - posx" + (varv1.x - posx));
               // Debug.Log("墙长度 ffz" + ff + "   " + "jXx" + jx + "   " + "jXy" + jy + "   " + "jXz" + jz);
 
                //X方向创建 ff个
                for (int j = 0; j < ff; j++)
                {
                    GameObject GO_Z = Instantiate(BaseWall, new Vector3(varv1.x - jx * unitlength2, varv1.y, varv1.z - jz * (unitlength2 + j * unitlength1)), Quaternion.identity);
 
                    Debug.Log("varv1.y - jy * unitlength2" + (varv1.y - jy * unitlength2) + "   ");
                    //GO_Z.transform.parent = transform;
                }//
            }//
 
        }//
 
        //new Vector3(transform.position.x + transform.localScale.x / 2, transform.position.y + transform.localScale.y / 2, transform.position.z + transform.localScale.z / 2);
        //Instantiate(BaseWall, new Vector3(1, 1, 1), Quaternion.identity);
    }//
 
 
    void OnDrawGizmos()//画一个立方体,用于判断这个 孵化器 的范围
    {
#if UNITY_EDITOR
 
        Gizmos.color = Color.blue;//栏线
        Gizmos.DrawLine(transform.position, dirX);
        Gizmos.DrawLine(transform.position, dirX_);
        //Gizmos.DrawSphere(A1, (float)0.5);
        //Gizmos.DrawSphere(A2, (float)0.5);
 
        Gizmos.color = Color.green;//绿线
        Gizmos.DrawLine(transform.position, dirY);
        Gizmos.DrawLine(transform.position, dirY_);
        //Gizmos.DrawSphere(A3, (float)0.5);
       // Gizmos.DrawSphere(A4, (float)0.5);
       // Gizmos.DrawSphere(B4, (float)0.5);
 
        Gizmos.color = Color.black;//黑线
        Gizmos.DrawLine(transform.position, dirZ);
        Gizmos.DrawLine(transform.position, dirZ_);
        //Gizmos.DrawSphere(B1, (float)0.5);
        //Gizmos.DrawSphere(B2, (float)0.5);
        //Gizmos.DrawSphere(B3, (float)0.5);
 
        Gizmos.color = Color.red;//红线
        Gizmos.DrawSphere(transform.position, (float)0.5);//描述:用在transform.position绘制一个大小为2绘制一个球体.
        Gizmos.DrawWireCube(transform.position, this.transform.localScale);//    描述:用transform.position和this.transform.localScale绘制一个线框立方体.
        Handles.Label(transform.position, "Room Wall Judget");//在transform.position位置 绘制一个"Enemy Spawner"的文本
        //handles.label需要下面撒谎那个行作为头文件
        //#if UNITY_EDITOR
        //using UnityEditor;
        //#endif
#endif
    }
 
    void JudgetDirWall(Vector3 dirV)//判断6个方向的墙壁
    {
        RaycastHit hit;
        if (Physics.Linecast(target.position, dirV, out hit))
        {
            string tagname = hit.collider.gameObject.tag;
            if (tagname != "MainCamera" && tagname != "terrain")
            {
                if (tagname == "Wall")//如果 碰撞到墙壁,使其透明
                {
                    hit.collider.gameObject.GetComponent<MeshRenderer>().enabled = false;
                }//
 
            }//
        }//
    }//
 
 
    void Test()
    {
        Debug.Log("1");
        RaycastHit hit1;
        RaycastHit hit2;
        if (Physics.Linecast(maincamera.position, target.position, out hit1))
        {
            string tagname1 = hit1.collider.gameObject.tag;
            if (tagname1 != "MainCamera" && tagname1 != "terrain")
            {
                if (tagname1 == "Wall")//如果 碰撞到墙壁,使其透明
                {
                    hit1.collider.gameObject.GetComponent<MeshRenderer>().enabled = false;
                }//
 
            }//
 
            Vector3 CameraToTarget = new Vector3(maincamera.position.x, target.transform.position.y, maincamera.position.z);
            if (Physics.Linecast(CameraToTarget, target.position, out hit2))
            {
                Debug.Log("111");
                string tagname2 = hit2.collider.gameObject.tag;
                if (tagname2 != "MainCamera" && tagname2 != "terrain")
                {
                    if (tagname2 == "Wall")//如果 碰撞到墙壁,使其透明
                    {
                        hit2.collider.gameObject.GetComponent<MeshRenderer>().enabled = false;
                    }//
 
                }//
                
            }//
        }//
 
    }
 
}//