Unity3D点击物体报出坐标,点击物体没反应怎么办

在unitgy3D里,我想做一个点击一个在运行后被我写的随机方块生成器生成的方块,会在控制台报出其在20207的随机生成器里的xyz坐标,左键单点是读出坐标,左键双击是在该位置的上方生成预制体宫殿。代码如下


```c#
using UnityEngine;
using UnityEngine.EventSystems;

public class StoneGenerator : MonoBehaviour
{
    public GameObject stonePrefab; // 石头的预制体
    public GameObject grassPrefab; // 草的预制体
    public GameObject palacePrefab; // 宫殿的预制体
    public static float spacing = 2f; // 方块间距

    public int length = 20; // 生成区域的长度
    public int width = 20; // 生成区域的宽度
    public int height = 7; // 生成区域的高度

    [Range(0f, 1f)]
    public float[] spawnChances; // 每层岩石方块生成的概率

    public int seed; // 地图种子
    public float additionalSpawnChance = 0.006f;

    void Start()
    {
        Random.InitState(seed);
        GenerateStones();
    }

    void GenerateStones()
    {
        // 遍历生成区域的每个方块
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < length; x++)
            {
                for (int z = 0; z < width; z++)
                {
                    // 根据每层的生成概率来生成岩石方块
                    if (y == 4) // 规律1:当y=4时,必定生成草方块。
                    {
                        Vector3 spawnPosition = new Vector3(x * spacing, y * spacing, z * spacing);
                        Instantiate(grassPrefab, spawnPosition, Quaternion.identity, transform);
                    }
                    else if (Random.value < spawnChances[y]) // 当前位置按概率生成石头方块
                    {
                        Vector3 spawnPosition = new Vector3(x * spacing, y * spacing, z * spacing);
                        GameObject blockObject = Instantiate(stonePrefab, spawnPosition, Quaternion.identity);
                        blockObject.transform.SetParent(transform);
                        blockObject.AddComponent<BlockEventListener>();//给我代码的人说这附近有可以引用其他脚本的代码

                        if (y == 5 && Random.value < additionalSpawnChance) // 在y=5处的岩石方块上方生成岩石方块的概率判断
                        {
                            Vector3 spawnPositionAbove = new Vector3(x * spacing, (y + 1) * spacing, z * spacing); // 上方生成岩石方块
                            GameObject blockObjectAbove = Instantiate(stonePrefab, spawnPositionAbove, Quaternion.identity);
                            blockObjectAbove.transform.SetParent(transform);
                        }
                    }
                }
            }
        }
    }
}

using UnityEngine;
using UnityEngine.EventSystems;

public class BlockEventListener : MonoBehaviour, IPointerClickHandler
{
    public void OnPointerClick(PointerEventData eventData)
    {
        Debug.Log(1);
        StoneGenerator stoneGenerator = FindObjectOfType<StoneGenerator>(); // 获取 StoneGenerator 脚本实例
        Debug.Log(2);
        if (stoneGenerator != null)
        {
            Debug.Log(3);
            Vector3 blockPosition = transform.position / StoneGenerator.spacing;
            int x = Mathf.FloorToInt(blockPosition.x);
            int y = Mathf.FloorToInt(blockPosition.y);
            int z = Mathf.FloorToInt(blockPosition.z);
            Debug.LogFormat("Clicked block position in StoneGenerator: ({0}, {1}, {2})", x, y, z); 
            Debug.Log(4);
        }
    }
}

img


上图可以展示第二个脚本被挂载在一个物体下,并且该物体有collider。用途不明(有人说这么做)

img


上图可以展示第一个脚本被挂载在空物体上,用来生成随机地图块。

img


上图可以展示被随机生成的方块各自都有collider。

我想要的效果是:左键单击方块,控制台报出其在随机生成器里的坐标。
通过第二段代码,经我试验,发现4个用来检测是否有运行的Debug.Log输出数字,结果运行后点击屏幕,一个数字都没出来。
如果可以的话,能不能给个左键双击方块,在该方块的上方,即y+1处生成宫殿的代码


不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这个问题的回答你可以参考下: https://ask.csdn.net/questions/744909
  • 除此之外, 这篇博客: 2022年第十三届蓝桥杯研究生Python组题目分享中的 有一根围绕原点 O 顺时针旋转的棒 OA,初始时指向正上方(Y 轴正向)。 在平面中有若干物件,第 i 个物件的坐标为 (xi , yi) ,价值为 zi。当棒扫到某个 物件时,棒的长度会瞬间增长 zi,且物件瞬间消失(棒的顶端恰好碰到物件也 视为扫到),如果此时增长完的棒又额外碰到了其他物件,也按上述方式消去 (它和上述那个点视为同时消失)。 如果将物件按照消失的时间排序,则每个物件有一个排名,同时消失的物 件排名相同,请输出每个物件的排名,如果物件永远不会消失则输出 −1 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

  • 以下回答来自chatgpt:

    回答如下:

    实现点击随机生成的方块并输出其在生成器中的坐标

    1. 给每个方块添加碰撞体组件

    在生成随机方块的脚本中,添加一个方法,用于为每个方块对象添加碰撞体组件。

    public class BlockGenerator : MonoBehaviour
    {
        public GameObject blockPrefab;
    
        void Start()
        {
            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    Vector3 position = new Vector3(i, Random.Range(0, 5), j);
                    Instantiate(blockPrefab, position, Quaternion.identity);
                }
            }
        }
    
        void AddColliderToBlock(GameObject block)
        {
            var collider = block.AddComponent<BoxCollider>();
            collider.isTrigger = true;
        }
    }
    

    然后在生成方块的循环中,调用 AddColliderToBlock 方法,将生成的方块添加碰撞体组件。

    void Start()
    {
        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 10; j++)
            {
                Vector3 position = new Vector3(i, Random.Range(0, 5), j);
                GameObject block = Instantiate(blockPrefab, position, Quaternion.identity);
                AddColliderToBlock(block);
            }
        }
    }
    

    2. 注册方块点击事件

    在控制器脚本中,为每个方块注册点击事件。

    public class BlockController : MonoBehaviour
    {
        void OnMouseDown()
        {
            Debug.Log("Block clicked.");
            Debug.Log("Position: " + transform.position);
        }
    }
    

    在这个脚本中,我们使用了 Unity 内置的 OnMouseDown 方法,该方法会在物体被鼠标左键按下时被调用。我们在其中输出了点击事件,并获取了物体的位置信息。

    3. 输出方块在生成器中的坐标

    BlockGenerator 脚本中,给生成的方块添加一个 Block 组件,用于存储方块在生成器中的坐标。

    public class Block : MonoBehaviour
    {
        public Vector2Int position;
    }
    

    在生成方块的循环中,给每个方块添加 Block 组件,并设置 position 属性,存储方块的位置信息。

    void Start()
    {
        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 10; j++)
            {
                Vector3 position = new Vector3(i, Random.Range(0, 5), j);
                GameObject block = Instantiate(blockPrefab, position, Quaternion.identity);
                AddColliderToBlock(block);
    
                Block blockInfo = block.AddComponent<Block>();
                blockInfo.position = new Vector2Int(i, j);
            }
        }
    }
    

    现在,我们可以在 BlockController 脚本中获取到点击的方块在生成器中的位置信息,输出到控制台中。

    public class BlockController : MonoBehaviour
    {
        void OnMouseDown()
        {
            Block blockInfo = GetComponent<Block>();
            Debug.Log("Block clicked.");
            Debug.Log("Position: " + transform.position);
            Debug.Log("Generator Position: " + blockInfo.position);
        }
    }
    

    添加左键双击生成宫殿的功能

    1. 给每个方块添加鼠标双击事件

    BlockGenerator 脚本中,为方块添加一个方法,用于注册鼠标双击事件。

    void AddDoubleClickToBlock(GameObject block)
    {
        var click = block.AddComponent<DoubleClick>();
        click.action = GeneratePalace;
    }
    

    这里我们给方块添加一个 DoubleClick 组件,该组件会在鼠标左键双击时被调用,我们将要执行的方法传入其中。

    在生成方块的循环中,调用 AddDoubleClickToBlock 方法,为每个方块注册鼠标双击事件。

    void Start()
    {
        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 10; j++)
            {
                Vector3 position = new Vector3(i, Random.Range(0, 5), j);
                GameObject block = Instantiate(blockPrefab, position, Quaternion.identity);
                AddColliderToBlock(block);
                AddDoubleClickToBlock(block);
    
                Block blockInfo = block.AddComponent<Block>();
                blockInfo.position = new Vector2Int(i, j);
            }
        }
    }
    

    2. 编写生成宫殿的方法

    BlockGenerator 脚本中,添加一个方法用于生成宫殿。

    public class BlockGenerator : MonoBehaviour
    {
        public GameObject blockPrefab;
        public GameObject palacePrefab;
    
        void GeneratePalace(GameObject block)
        {
            Vector3 position = block.transform.position + Vector3.up;
            Instantiate(palacePrefab, position, Quaternion.identity);
        }
    
        // ...
    }
    

    在这个方法中,我们获取传入的方块,取得其上方的位置,并生成宫殿实例。

    3. 添加双击组件

    BlockGenerator 脚本中,编写一个 DoubleClick 组件,用于处理鼠标双击事件。

    public class DoubleClick : MonoBehaviour
    {
        public float timeThreshold = 0.2f;
        public UnityAction<GameObject> action;
        float lastClickTime = 0f;
        GameObject lastClickObject = null;
    
        void OnMouseDown()
        {
            if (Time.time - lastClickTime < timeThreshold && lastClickObject == gameObject)
            {
                action(gameObject);
            }
            lastClickTime = Time.time;
            lastClickObject = gameObject;
        }
    }
    

    在这个组件中,我们设定了一个时间阈值,用于区分单击和双击事件。同时,我们使用了 Unity 的事件系统,注册了一个 UnityAction 委托,用于在双击事件发生时调用方法。

    然后,在 BlockGenerator 脚本中,对每个方块注册双击事件,将编写好的 GeneratePalace 方法传入。

    void AddDoubleClickToBlock(GameObject block)
    {
        var click = block.AddComponent<DoubleClick>();
        click.action = GeneratePalace;
    }
    

    现在,我们就成功的实现了在Unity3D中实现点击随机生成的方块并输出其在生成器中的坐标,并添加左键双击生成宫殿的功能。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^