在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);
}
}
}
我想要的效果是:左键单击方块,控制台报出其在随机生成器里的坐标。
通过第二段代码,经我试验,发现4个用来检测是否有运行的Debug.Log输出数字,结果运行后点击屏幕,一个数字都没出来。
如果可以的话,能不能给个左键双击方块,在该方块的上方,即y+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);
}
}
}
在控制器脚本中,为每个方块注册点击事件。
public class BlockController : MonoBehaviour
{
void OnMouseDown()
{
Debug.Log("Block clicked.");
Debug.Log("Position: " + transform.position);
}
}
在这个脚本中,我们使用了 Unity 内置的 OnMouseDown
方法,该方法会在物体被鼠标左键按下时被调用。我们在其中输出了点击事件,并获取了物体的位置信息。
在 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);
}
}
在 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);
}
}
}
在 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);
}
// ...
}
在这个方法中,我们获取传入的方块,取得其上方的位置,并生成宫殿实例。
在 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中实现点击随机生成的方块并输出其在生成器中的坐标,并添加左键双击生成宫殿的功能。