YueZHeng_917 2023-06-20 22:24 采纳率: 57.9%
浏览 23
已结题

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处生成宫殿的代码


  • 写回答

1条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-06-21 08:25
    关注
    不知道你这个问题是否已经解决, 如果还没有解决的话:
    • 这个问题的回答你可以参考下: 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中实现点击随机生成的方块并输出其在生成器中的坐标,并添加左键双击生成宫殿的功能。


    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 6月29日
  • 已采纳回答 6月21日
  • 创建了问题 6月20日