I'm creating a basic simulator in Unity for my A-level Computer Science project. At the moment the user is able to draw a box (crate) object by selecting the associated tool and clicking and dragging to determine two opposite corners of the box, thus determining its dimensions.
The box consists of a single prefab which is instantiated and has its size changed accordingly. The code for it is as follows:
void Start () {
boxAnim = boxButton.GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
//sets the mouseDown and mouseHeld bools and the mouse position Vector3
mouseDown = Input.GetMouseButtonDown(0);
mouseHeld = Input.GetMouseButton(0);
mousePosition = Input.mousePosition;
//checks if the user has started to draw
if (mouseDown && !draw)
{
draw = true;
originalMousePosition = mousePosition;
}
//checking if the user has released the mouse
if (draw && !mouseHeld)
{
finalMousePosition = mousePosition;
draw = false;
if (boxAnim.GetBool("Pressed") == true) //if the box draw button is pressed
{
boxDraw(originalMousePosition, finalMousePosition); //draws crate
}
}
}
void boxDraw(Vector3 start, Vector3 end)
{
//asigns world coordinates for the start and end mouse positions
worldStart = Camera.main.ScreenToWorldPoint(start);
worldEnd = Camera.main.ScreenToWorldPoint(end);
if (worldStart.y >= -3.2f && worldEnd.y >= -3.2f)
{
//determines the size of box to be drawn
boxSize.x = Mathf.Abs(worldStart.x - worldEnd.x);
boxSize.y = Mathf.Abs(worldStart.y - worldEnd.y);
//crate sprite is 175px wide, 175/50 = 3.5 (50px per unit) so the scale factor must be the size, divided by 3.5
boxScaleFactor.x = boxSize.x / 3.5f;
boxScaleFactor.y = boxSize.y / 3.5f;
//initial scale of the box is 1 (this isn't necessary but makes reading program easier)
boxScale.x = 1 * boxScaleFactor.x;
boxScale.y = 1 * boxScaleFactor.y;
//creates a new crate under the name newBox and alters its size
GameObject newBox = Instantiate(box, normalCoords(start, end), box.transform.rotation) as GameObject;
newBox.transform.localScale = boxScale;
}
}
Vector3 normalCoords(Vector3 start, Vector3 end)
{
//takes start and end coordinates as position coordinates and returns a world coordinate coordinate for the box
if(end.x > start.x)
{
start.x = start.x + (Mathf.Abs(start.x - end.x) / 2f);
}
else
{
start.x = start.x - (Mathf.Abs(start.x - end.x) / 2f);
}
if(end.y > start.y)
{
start.y = start.y + (Mathf.Abs(start.y - end.y) / 2f);
}
else
{
start.y = start.y - (Mathf.Abs(start.y - end.y) / 2f);
}
start = Camera.main.ScreenToWorldPoint(new Vector3(start.x, start.y, 0f));
return start;
}
In a similar manner, I want to be able to have a 'ramp' object be able to be created, so that the user can click and drag to determine the base width, then click again to determine the angle of elevation/ height, (the ramp will always be a right angled triangle.) The problem lies in that I want to have the ramp as a sprite I have created, rather than just a basic block colour. A single sprite however would only have a single angle of elevation, and no transform would be able to alter this (as far as I'm aware.) Obviously I don't want to have to create a different sprite for each angle, so is there anything I can do?
The solution I was thinking was if there was some sort of feature whereby I could alter the nodes of a vector image in the code, but I'm pretty sure this doesn't exist.
EDIT: Just to clarify this is a 2D environment, the code includes Vector3s just because that’s what I’m used to
You mention Sprite which is a 2D object (well, its actually very much alike a Quad which counts as 3D) but you reference full 3D in other parts of your question and in your code, which I think was confusing people, because creating a texture for a sprite is a very different problem. I am assuming you mentioned Sprite by mistake and you actually want a 3D object (Unity is 3D internally most of the time anyways), it can only have one side if you want
You can create 3D shapes from code no problems, although you do need to get familiar with the Mesh class, and mastering creating triangles on the fly takes some practice
Here's a couple of good starting points
https://docs.unity3d.com/Manual/Example-CreatingaBillboardPlane.html https://docs.unity3d.com/ScriptReference/Mesh.html
I have a solution to part of the problem using meshes and a polygon collider. I now have a function that will create a right angled triangle with a given width and height and a collider in the shape of that triangle:
using UnityEngine;
using System.Collections;
public class createMesh : MonoBehaviour {
public float width = 5f;
public float height = 5f;
public PolygonCollider2D polyCollider;
void Start()
{
polyCollider = GetComponent<PolygonCollider2D>();
}
// Update is called once per frame
void Update () {
TriangleMesh(width, height);
}
void TriangleMesh(float width, float height)
{
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mf.mesh = mesh;
//Verticies
Vector3[] verticies = new Vector3[3]
{
new Vector3(0,0,0), new Vector3(width, 0, 0), new Vector3(0,
height, 0)
};
//Triangles
int[] tri = new int[3];
tri[0] = 0;
tri[1] = 2;
tri[2] = 1;
//normals
Vector3[] normals = new Vector3[3];
normals[0] = -Vector3.forward;
normals[1] = -Vector3.forward;
normals[2] = -Vector3.forward;
//UVs
Vector2[] uv = new Vector2[3];
uv[0] = new Vector2(0, 0);
uv[0] = new Vector2(1, 0);
uv[0] = new Vector2(0, 1);
//initialise
mesh.vertices = verticies;
mesh.triangles = tri;
mesh.normals = normals;
mesh.uv = uv;
//setting up collider
polyCollider.pathCount = 1;
Vector2[] path = new Vector2[3]
{
new Vector2(0,0), new Vector2(0, height), new Vector2(width, 0)
};
polyCollider.SetPath(0, path);
}
}
I just need to put this function into code very similar to my code for drawing a box so that the user can specify width and height.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With