简体   繁体   English

Object 对程序生成的平面不满意

[英]Object Insatiate with a plane that is procedurally generated

I am new to procedural generation in Unity and I am making a simple game with a player in a plane that is procedurally generated, the requirement is that I am trying to bring up some walls simultaneously with the generation of the plane which is not working.我是 Unity 程序生成的新手,我正在用程序生成的平面上的玩家制作一个简单的游戏,要求是我试图在生成不起作用的平面的同时建立一些墙壁。 The code so far for this is below:到目前为止的代码如下:

    public GameObject WorldPlane;
    public GameObject Cube;
    public GameObject walls;

    private int radius = 5;
    private int planeOffset = 10;

    private Vector3 startPos = Vector3.zero;

    private int XPlayerMove => (int)(Cube.transform.position.x - startPos.x);
    private int ZPlayerMove => (int)(Cube.transform.position.z - startPos.z);

    private int XPlayerLocation => (int)Mathf.Floor(Cube.transform.position.x / planeOffset) * planeOffset;
    private int ZPlayerLocation => (int)Mathf.Floor(Cube.transform.position.z / planeOffset) * planeOffset;

    Hashtable tilePlane = new Hashtable();

    void Update()
    {
        generateWorld();
    }

    private void generateWorld()
    {
        if (startPos == Vector3.zero)
        {
            for (int x = -radius; x < radius; x++)
            {
                for (int z = -radius; z < radius; z++)
                {
                    Vector3 pos = new Vector3((x * planeOffset + XPlayerLocation),
                    0,
                    (z * planeOffset + ZPlayerLocation));

                    if (!tilePlane.Contains(pos))
                    {
    
                        GameObject tile = Instantiate(WorldPlane, pos, Quaternion.identity); 
                        tilePlane.Add(pos, tile);
                    }
                }
            }
        }
        if (hasPlayerMoved(XPlayerMove, ZPlayerMove))
        {
            for (int x = -radius; x < radius; x++)
            {
                for (int z = -radius; z < radius; z++)
                {
                    Vector3 pos = new Vector3((x * planeOffset + XPlayerLocation),
                    0,
                    (z * planeOffset + ZPlayerLocation));

                    if (!tilePlane.Contains(pos))
                    {
                        GameObject Wall=Instantiate(walls, pos, Quaternion.identity);
                        GameObject tile = Instantiate(WorldPlane,pos,Quaternion.identity);
                        tilePlane.Add(pos, tile); 
                        tilePlane.Add(pos, Wall);

                    }
                }
            }
        }
    }

    private bool hasPlayerMoved(int playerX, int playerZ)
    {
        if (Mathf.Abs(XPlayerMove) >= planeOffset || Mathf.Abs(ZPlayerMove) >= planeOffset)
        {
            return true;
        }
        return false;
    }

Here the cube is the player, the world plane is the prefab for the plane which should be generated, and the walls are the prefab for the game object that I am trying to instantiate with the plane, as of now the plane is getting generated without any issues.这里的立方体是玩家,世界平面是应该生成的平面的预制件,墙壁是我试图用平面实例化的游戏 object 的预制件,到目前为止,飞机正在生成任何问题。 I really stuck with this, requesting help.我真的坚持这一点,请求帮助。

This condition is alway true:这个条件总是成立的:

if (startPos == Vector3.zero)

Because you never change startPos .因为你永远不会改变startPos Therefore, you already assigned a Tile to pos via tilePlane.Add(pos, tile);因此,您已经通过tilePlane.Add(pos, tile);将 Tile 分配给pos

So in the lower if you check this:因此, if您检查以下内容,请在下方:

if (!tilePlane.Contains(pos)) // fails, because you already added a Plane above.

To solve this, you can set StartPos to something else than zero after running the double-loop once.为了解决这个问题,您可以在运行一次双循环后将 StartPos 设置为非零。 So later, when the cube(player) moves, new tiles + wall get generated using the lower if .所以稍后,当立方体(玩家)移动时,使用较低的if生成新的瓷砖 + 墙。

But you should not add 2 entries to one hashtable-key.但是您不应该将 2 个条目添加到一个哈希表键。 So this will throw an error:所以这会抛出一个错误:

 tilePlane.Add(pos, tile); 
 tilePlane.Add(pos, Wall);

 ArgumentException: Item has already been added. Key in dictionary: '(0.00, 0.00, 70.00)'  Key being added: '(0.00, 0.00, 70.00)'

So you either need 2 Hashtables (1 for tiles, 1 for wall) or you need a struct/class to hold both.因此,您要么需要 2 个哈希表(1 个用于瓷砖,1 个用于墙),要么需要一个结构/类来保存两者。

Example:例子:

class Helper {
    public GameObject wall;
    public GameObject tile;
}

then in your code:然后在您的代码中:

GameObject Wall = Instantiate(walls, pos, Quaternion.identity);
GameObject tile = Instantiate(WorldPlane,pos,Quaternion.identity);
                    
Helper help = new Helper();
help.wall = Wall;
help.tile = tile;
tilePlane.Add(pos, help); // add the class containing both to key `pos`.

在此处输入图像描述


Edit : Yes it's procedural.编辑:是的,它是程序性的。 I added random rotation to the walls to make it a maze.我在墙壁上添加了随机旋转以使其成为迷宫。 (Wall is an empty GameObject with the wall as child, so that I could offset the wall so it rotates around the tiles center.) (墙是一个空的游戏对象,墙是孩子,所以我可以偏移墙,让它围绕瓷砖中心旋转。)

Check it out:一探究竟:

在此处输入图像描述

Here is the code:这是代码:

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

public class PlaneGeneration : MonoBehaviour
{
    // Start is called before the first frame update
    public GameObject WorldPlane;
    public GameObject Cube;
    public GameObject walls;

    private int radius = 5;
    private int planeOffset = 10;

    private bool startAreaGenerated = false;
    private Vector3 startPos = Vector3.zero;
    

    private int XPlayerMove => (int)(Cube.transform.position.x - startPos.x);
    private int ZPlayerMove => (int)(Cube.transform.position.z - startPos.z);

    private int XPlayerLocation => (int)Mathf.Floor(Cube.transform.position.x / planeOffset) * planeOffset;
    private int ZPlayerLocation => (int)Mathf.Floor(Cube.transform.position.z / planeOffset) * planeOffset;

    Hashtable tilePlane = new Hashtable();

    private void Start()
    {
        startPos = Cube.transform.position;
    }

    class Helper
    {
        public GameObject tile;
        public GameObject wall;
    }

    void Update()
    {
        generateWorld();
    }

    private void generateWorld()
    {
        if (!startAreaGenerated)
        {
            for (int x = -radius; x < radius; x++)
            {
                for (int z = -radius; z < radius; z++)
                {
                    Vector3 pos = new Vector3((x * planeOffset + XPlayerLocation), 0, (z * planeOffset + ZPlayerLocation));

                    if (!tilePlane.Contains(pos))
                    {

                        GameObject tile = Instantiate(WorldPlane, pos, Quaternion.identity);
                        Helper helper = new Helper();
                        helper.tile = tile;
                        tilePlane.Add(pos, helper);
                    }
                }
            }
            startAreaGenerated = true;
        }
        if (hasPlayerMoved(XPlayerMove, ZPlayerMove))
        {
            for (int x = -radius; x < radius; x++)
            {
                for (int z = -radius; z < radius; z++)
                {
                    Vector3 pos = new Vector3((x * planeOffset + XPlayerLocation),0, (z * planeOffset + ZPlayerLocation));

                    if (!tilePlane.Contains(pos))
                    {
                        int random0to3 = Random.Range(0, 4); // 0, 1, 2 or 3.
                        Quaternion randomRotation = Quaternion.Euler(0, random0to3 * 90, 0); // rotated 0°, 90°, 180° or 270° around Y-Axis.
                        GameObject Wall = Instantiate(walls, pos, randomRotation);
                        GameObject tile = Instantiate(WorldPlane, pos, Quaternion.identity);

                        Helper helper = new Helper();
                        helper.tile = tile;
                        helper.wall = Wall;
                        tilePlane.Add(pos, helper);
                    }
                }
            }
        }
    }

    private bool hasPlayerMoved(int playerX, int playerZ)
    {
        if (Mathf.Abs(XPlayerMove) >= planeOffset || Mathf.Abs(ZPlayerMove) >= planeOffset)
        {
            return true;
        }
        return false;
    }
}

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

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