aid in the development of levels and scenes in Unity3D
.
During the development of my senior capstone game, Sunline, our artists created "Lego blocks" of assets that were meant to be placed next to each other to create larger blocks.
Instead of one large wall for a building, we would place multiple smaller walls, windows, and doors next to each other to create a variety of walls for every building. This allowed us to easily redesign every part of the environment, but soon became tedious to place so many objects together.
ROP was created for designers and artists, not programmers, so all forward facing functionality has to be intuitive and understandable.
It is also important that there are many options, but these options have to be well organized and intuitive.
There are so many possible ways to use ROP, and because of this it can't just have the basic features.
It needs to be customizable, every value can be changed, and every option can be messed with to create varying results.
For ROP to be best used, it needs to work for as many cases as possible.
Ideally it could create lines, grids and curves of all sorts of objects, attach them together, or spread them out, and allow them to rotated in any way.
ROP was not only designed for its users, but with the help of its users. The initial prototype had limited options, could only create lines, and was not nearly as customizable. Since than, many team members have used ROP, and come back to me with their suggestions and ideas of what could be changed to make there lives even easier. All of these changes fit within the already existing list of requirements, the tool needed to be easy to use, be actually useful, and allow as much customization as possible.
Instead of using monobehavior scripts to control the way the line works, I created a custom editor window. This window can be open separately from the inspector, and allows the variables on objects to be modified without the script necessarily existing on the object in the first place
Once users have created a ROP object they can then move the two points that define the line. From there the program automatically calculates how many objects it should spawn, where to place them, and how to rotate them along the line to create seamless tiles.
Users can also modify these values, rotate the object so it fits their needs, space them farther apart, and choose which parts of the line the object should stay closest to.
Repeatable Object Placer uses an objects MeshRender component to find the bounds of the object, and from there calculates the spacing that would allow the objects to be lined up perfectly.
To allow for more customizability you can also change this spacing, to create separation between trees, or maybe place objects closer to each other than their bounding boxes may suggest. This spacing then recalculates how many objects to spawn, and where their correct location is.
By default and object is rotated to follow the line, which may work for many items, but not all. Instead of needing to rotate the original model, there are also rotation options built into ROP. The three cardinal directions, 90 degrees on the X, Y and Z, can be easily accessed through a button, but there are also two other options.
C(ustom) allows you to set any possible rotation of the objects, incase the three cardinal don't fit your use case.
R(andom) will rotate each object "randomly" and can be locked on certain axis, because angled trees don't make for a great sidewalk decoration
I was asked by the artists on my team to allow them a bit more customizability for how the objects are placed on the line. Specifically it was asked if they could choose what part of the object should be on the line, like the top, middle or bottom, even the left versus right. This would allow them to line up objects against walls, in corners, or on the ground easier.
Because these objects need to align in three dimensional space, there are a lot of options dedicated to this purpose
Explanation of each snapping option
This was one of the most difficult parts of the project, because the snapping of an object not only requires finding the point at which it is meant to snap to, but moving all the objects to this line next to each other. It also involves possibly changing the number of objects along the line, to account for any extra space, or removing them to make sure they do not go beyond the line.
For example, if a user selects "Center" for Snapping To Line, and then "Left Bottom" for the object snapping, they would like the bottom left of the object to snap to the center of the line.For this, the program finds the center of the vector connecting the two anchor points, and then also calculates, based off the mesh render, the offset of the object from the point. As the for loop iterates through each object, making sure it places them, it either subtracts or adds to "the center" and then also offsets the position of the object by half its width and height.
Because objects can be easily rotated by ROP, or instead of Left and Right a user wants to modify the Forward and Backward vector of the program there are also options to define the axis. When this is done, instead of offsetting by half the width, we may instead offset by half the length.
While the line function of the tool works in many situations with the Lego set our artists designed, it was hard to create large walls of objects, as many lines would need to be placed on top of each other
To help with this, I also created a grid function, that would connect the two anchor points with a plane of objects instead of a single line. However, technically to define a plane you need three points along it. I was worried that introducing a third point, solely for grids would be difficult to use, so instead I found the third point programmatically using the fact that the user could pick weather the plane was vertical like a wall, or horizontal like a floor.
This was another difficult part of the project, and required many changes to the calculation of spacing and rotation, and uses division to find the point on the plane that the object should be placed. This difficulty was well worth it however, because it greatly expands the possible use cases for ROP.
My next steps include finishing up all the features that my teams artists have requested, like end caps, and slightly more intuitive snapping options. Listening to their advice has been a core pillar of ROP since the beginning, so it is important that every step of development caters to their needs as best as possible.
Because I believe in the value of ROP as a development tool, I have plans to post it on the unity asset store, to allow all designers and artists working with modular assets to create the best environment possible. From placing fences, to trees, and even full walls, ROP makes the process of snapping objects together flawlessly easy at any desired angle.