I would like a cube that when user clicks one side of the cube, it spawns another cube on that side

As the title states, how would I make it so that if you click on one side of a cube, another cube spawns flush to that cube, similar to the CAD mockup I have in the attached image. I am relatively new to Unity and do not know how to go about this issue.

I know what I need to do, just not how to implement it via Unity. I know that I need to

  1. detect a click and know what side is clicked
  2. spawn a new cube with click detectors on all sides except those which already have cubes
  3. delete the click detectors that overlap placed cubes

I just don’t know what unity classes should be used to add this.

You would need a raycast from camera to mouse position, that gives variables of hitposition and the object clicked. Assuming the (hit)cube prefab has it’s position as the center, you would subtract hitPosition minus (hit)cube position then round that(direction), and Instantiate a new cube prefab at that position times 2 from (hit)cube.

Excuse my poor pseudo code, I’m just thinking aloud… I’ll play around with my thought and see if I can get it to work right.

I’m curious why your screenshot is titled “the root of human idiocy” but I’ll leave that aside for now.

In the general sense, everything @wideeyenow_unity suggests above is exactly what you need.

Anything beyond that is … well, extra features.

Steps to success:

  • detect click on a cube
  • use the RaycastHit info to find what it was (and hence where it was)
  • use the RaycastHit normal to offset by one cube chunk
  • spawn afresh

You don’t even need to “delete click detectors” because the previous cube will be “buried”

Put this on a camera:

using UnityEngine;

public class AddCube : MonoBehaviour
{
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray=Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray,out RaycastHit hit,500f))
            {
                GameObject obj=Instantiate(hit.transform.gameObject,hit.transform.position+hit.normal,hit.transform.rotation);
            }
        }
    }
}
4 Likes

Yup, he’s got it ^^^.

I was still trying to figure how to round the difference yet with negative values. :rage: But yup, normals… lol

Edit: I already told myself, multiply by 2… ::facepalm::

Zulo, Zulo, Zulo!!! Deep respect there, my friend. Very nicely done. WOW!!!

Here was my much more complicated but still sorta easy to use effort:

https://www.youtube.com/watch?v=zSoC3wlw6co

It’s all in my MakeGeo project as ClickToAddCubes.cs

https://github.com/kurtdekker/makegeo/blob/master/makegeo/Assets/ClickToAddCubes/ClickToAddCubes.cs

MakeGeo is presently hosted at these locations:

https://bitbucket.org/kurtdekker/makegeo

2 Likes

Not to steal any thunder from zulo3d, but I wondered myself, what might be the question on this later:

What if the cube was oddly scaled, or more than just (1,1,1)? this:

public class AddCube : MonoBehaviour
{
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray=Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray,out RaycastHit hit,500f))
            {
                Vector3 sideVector = new Vector3(
                    hit.transform.localScale.x * hit.normal.x,
                    hit.transform.localScale.y * hit.normal.y,
                    hit.transform.localScale.z * hit.normal.z);
                Instantiate(hit.transform.gameObject,
                    hit.transform.position + sideVector, hit.transform.rotation);
            }
        }
    }
}
1 Like

I dunno but…

:slight_smile:

1 Like

Exactly what I was looking for, thanks! I will be using this for something larger than 1x1 cubes but I think upscaling this will be a fun learning challenge for me.

I was originally using that cad file to model a collision I was in to show how my idiocy caused an accident, then decided to repurpose it to showcase this.

Modified the code so it works with any rectangular/hexagonal/octagonal

using UnityEngine;

public class AddCube : MonoBehaviour
{
    void Update()
    {
        if (Input.GetMouseButtonDown(0))//if user clicks
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//where user clicks
            bool cast = Physics.Raycast(ray, out RaycastHit hit, 500f);
           
            if (cast && hit.transform.gameObject.CompareTag("Room"))//if user clicks an object, duplicate it along that face
            {
                if (hit.normal.x != 0)
                {
                    Instantiate(hit.transform.gameObject, hit.transform.position + hit.normal * hit.transform.localScale.x, hit.transform.rotation);
                }else if (hit.normal.y != 0)
                {
                    Instantiate(hit.transform.gameObject, hit.transform.position + hit.normal * hit.transform.localScale.y, hit.transform.rotation);
                }
                else
                {
                    Instantiate(hit.transform.gameObject, hit.transform.position + hit.normal * hit.transform.localScale.z, hit.transform.rotation);
                }
            }
        }
    }
}

prisms:

almost certainly a better way than if else chains but it works

lol, I knew that question was going to pop up, that’s why a few posts ago I threw it out there:

public class AddCube : MonoBehaviour
{
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray=Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray,out RaycastHit hit,500f))
            {
                Vector3 sideVector = new Vector3(
                    hit.transform.localScale.x * hit.normal.x,
                    hit.transform.localScale.y * hit.normal.y,
                    hit.transform.localScale.z * hit.normal.z);
                Instantiate(hit.transform.gameObject,
                    hit.transform.position + sideVector, hit.transform.rotation);
            }
        }
    }
}

Because “hitting” the cube will return it’s size, and position. So you only need to change the position, in relevance, as the “Instantiate” will duplicate the cube being hit. Tested this function with a cube scale (2,2,2) and (1,2,3) and saw no issues.

However if you want certain functionality with different size/side hits, than for sure you’ll need “if-else if-else” statements. :slight_smile: