Raycast instantiation only sometimes working.
I have a script that places blocks on a designated area only. It's supposed to be a very Minecraft-like system. However, my blocks will only instantiate at certain camera angles. I can't discern any pattern with the way they place. More confusing yet, is that the scripting for erasing blocks seems to work fine at any angle. Can anybody explain to me why this is happening so I can try to solve my issue? I'm running Unity 5.6.0f 64 bit. Thanks in advance. using UnityEngine; using System.Collections; using UnityEngine.UI;
public class BlockPlacing : MonoBehaviour
{
//Handles # of blocks the user has
public bool unlimitedBlocks = false;
public int blocksLeft = 0;
public Slider indicator;
public bool maxxed;
//If the player wants to lock the cursor somewhere else instead, they can do that.
public bool lockCursor = true;
//static reference to the script. This is so blocks can be added via a static method.
static BlockPlacing obj;
//The block prefab to instantiate
public GameObject blockPrefab;
//Maximum range that the player can place a block from
public float range = 7f;
void Start()
{
//This assigns the static reference
BlockPlacing.obj = this;
}
void Update()
{
//Locks the cursor. Running this in update is only done because of weird unity editor shenanigans with cursor locking
if (lockCursor)
Cursor.lockState = CursorLockMode.Locked;
//Make sure the player has enough blocks
if (blocksLeft > 0 || unlimitedBlocks)
{
//Place blocks using the LMB
if (Input.GetMouseButtonDown(0))
{
//Make a ray and raycasthit for a raycast
Ray ray = new Ray(transform.position, transform.TransformDirection(Vector3.forward));
RaycastHit hit;
//Perform the raycast
if (Physics.Raycast(ray, out hit, range))
{
//The raycast is backed up so that placing works and won't place blocks inside of the ground.
//After testing, 0.2 units back had the best result
Vector3 backup = ray.GetPoint(hit.distance - 0.1f);
//Round the placement so they place like blocks should
Vector3 placeAt = new Vector3(
Mathf.RoundToInt(backup.x), Mathf.RoundToInt(backup.y), Mathf.RoundToInt(backup.z));
//Instantiate the block and save it so that we can do other stuff with it later
if(hit.collider.gameObject.tag == "Foundation" || hit.collider.gameObject.tag == "Built")
{
GameObject block = (GameObject)GameObject.Instantiate(blockPrefab, placeAt, Quaternion.Euler(Vector3.zero));
indicator.value = blocksLeft;
if (block.GetComponent<Collider>().bounds.Intersects(this.transform.parent.GetComponent<Collider>().bounds))
{
//If they are, destroy the block
GameObject.Destroy(block);
//Make sure that the player gets their misplaced block back.
if (!unlimitedBlocks)
blocksLeft++;
indicator.value = blocksLeft;
}
}
//Remove a block from the player's "inventory"
if (!unlimitedBlocks)
blocksLeft--;
//If the block collides with the player, remove it. We don't want the player to get stuck in their own blocks.
}
}
}
if (Input.GetMouseButtonDown(1))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, 7))
{
BoxCollider bc = hit.collider as BoxCollider;
if (bc != null && bc.gameObject.tag == "Built")
{
Destroy(bc.gameObject);
blocksLeft++;
indicator.value = blocksLeft;
}
}
}
}
//Static adding of blocks. This isn't needed but definately helps a lot
public static void addBlocks(int i = 1)
{
BlockPlacing.obj.blocksLeft += i;
}
}
Answer by zachwuzhere · Jul 06, 2017 at 03:04 AM
From what I can see, you are removing blocks using the camera and mouse position. Why not place them like that too?
This was mostly down to me not knowing how to clamp the coordinates to a grid. I suppose it would be easier to figure that out than troubleshoot my current problem.