Is there a function to call in order to instantiate an object on a surface that will always be pointing along the normal?
I would like it so, no matter on which side of the cube the arrow is instantiated, they always instantiate along the surface.
At the moment the arrows point the correct way on top and bottom and incorrect on the sides.
Thanks
var arrowToggle = false;
var arrow : GameObject;
function OnGUI () {
arrowToggle = GUI.Toggle (Rect (Screen.width - 180, 10, 100, 30), arrowToggle, "ARROW", "button");
if (arrowToggle) {
if (Input.GetMouseButtonDown(0)){
var ray = camera.main.ScreenPointToRay (Input.mousePosition);
var hit : RaycastHit;
if (Physics.Raycast (ray, hit)){
if(hit.collider.gameObject.tag.Contains("collider")) {
Instantiate (arrow, hit.point + (hit.normal * 0.1), Quaternion.FromToRotation (Vector3.up, hit.normal));
}
}
}
}
else
{
var arrows = GameObject.FindGameObjectsWithTag("arrows");
for (var i in arrows) {
Destroy(i);
}
}
}
}
See attachment: Red arrows along the top are correct. The arrows on the side are incorrect beacuse they are lying on their sides, need to rotate 90.
That didn’t change anything, same result as before. I have another bit of code which I think may be causing the problem. Basically I instantiate the arrow at one point, and then can drag with the mouse to set it’s scale and rotation. Only one rotation should not be set. The rotation along the long axis should always correspond to the surface, so the arrow lies flat on it.
The first bit of code in the previous code instantiates the arrow prefab on which I have this bit of code below.
var newScale : float;
function OnMouseDown () {
if (Input.GetKey(KeyCode.LeftAlt)) {
}
else
{
while (Input.GetMouseButton(0)) {
var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
var hit : RaycastHit;
Physics.Raycast (ray, hit);
if(hit.collider.gameObject.tag.Contains("collider")) {
transform.rotation = Quaternion.LookRotation(hit.point + (hit.normal * 0.1) - transform.position);
}
if (Input.GetKey("backspace")) {
Destroy (this.gameObject);
}
newScale = Vector3.Distance(transform.position, hit.point + (hit.normal * 0.1))/10;
yield;
}
}
}
function LateUpdate () {
transform.localScale.x = newScale;
transform.localScale.z = newScale;
}
Quaternion.LookRotation has an optional second parameter that specifies the upward direction. If you set this to the normal of the object’s surface, you should be able to orient it correctly.
I’ve tried this, but same result.
Quaternion.LookRotation(hit.normal + (hit.normal * 0.1) - transform.position);
I have checked that the instantiation is working correctly, so it must be the dragging, setting the rotation and scale that is causing the problem. Because if I just click once (without dragging) the arrows are instantiated correctly, flat on whatever the surface, or side of the cube.
Hi all I am at my wits end. So far the best results are achieved with this. (See attached image). The arrows are placed correctly on the terrain and on top and bottom of the cube. But the sides of the cube are still posing a problem. The arrows are lying on the surface as needed, but they are rotated by 90 degrees, so the arrow head is half embedded in the cube and half sticking out. Is there a conditional statement that can be used to rectify this? Thanks
Sorry. I forgot to mention that I did try Demi180’s solution but the results were not what I needed. The arrows behaved strangely. They did not take into account where I dragged, so pointed in the wrong direction. Perhaps I should clarify what I’m actually doing…
Imagine a war map on a terrain. I need to show troop movements with a variety of symbols. So arrows, cubes lines etc. A first script attached to an empty game object instantiates an “arrow” prefab when I click on the terrain. On the “arrow” prefab is the code which controls the scale and direction of the arrow as I drag. The first script sets the initial point (the tail) and the second script sets the final point (the arrow head).
The first bit of code looks like this.
var arrowToggle = false;
var arrow : GameObject;
function OnGUI () {
arrowToggle = GUI.Toggle (Rect (Screen.width - 180, 10, 100, 30), arrowToggle, "ARROW", "button");
if (Input.GetKey(KeyCode.LeftAlt)) {
}
else
{
if (arrowToggle) {
if (Input.GetMouseButtonDown(0)){
var ray = camera.main.ScreenPointToRay (Input.mousePosition);
var hit : RaycastHit;
if (Physics.Raycast (ray, hit)){
if(hit.collider.gameObject.tag.Contains("collider")) {
Instantiate (arrow, hit.point + (hit.normal * 0.1), Quaternion.FromToRotation (Vector3.up, hit.normal));
}
}
}
}
else
{
var arrows = GameObject.FindGameObjectsWithTag("arrows");
for (var i in arrows) {
(i).layer = 8;
}
}
}
}
The second bit of code on the arrow prefab looks like this.
var newScale : float;
function Start () {
renderer.material.color = GameObject.Find("ColorCube").renderer.material.color;
}
function OnMouseDown () {
if (Input.GetKey(KeyCode.LeftAlt)) {
}
else
{
while (Input.GetMouseButton(0)) {
var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
var hit : RaycastHit;
Physics.Raycast (ray, hit);
if(hit.collider.gameObject.tag.Contains("collider")) {
transform.rotation = Quaternion.LookRotation(hit.point + (hit.normal * 0.1) - transform.position);
}
if (Input.GetKey("backspace")) {
Destroy (this.gameObject);
}
newScale = Vector3.Distance(transform.position, hit.point + (hit.normal * 0.1))/10;
yield;
}
}
}
function LateUpdate () {
transform.localScale.x = newScale;
transform.localScale.z = newScale;
transform.localScale.y = 0.2;
}
The reason I need this to work on the sides of the cube, is because I would like to have a flat map hanging on the wall of a war cabinet, as well as a 3d terrain of the battlefield. Hope that’s a bit clearer. Thanks
Hi all. I wanted to revisit this, because still haven’t got a satisfying solution to the problem. I have been commenting and uncomenting lines of code to find out which bit is causing the undesired results, and I have come to the conclusion that it is this line in the second script.
If the above line is uncomented the arrows instantiate correctly and their scal changes as the mouse is dragged along a surface, however their rotation is not impacted at all. The tricky part seems to affect the arrows rotation so they look at the hit.point, while maintaining their flat side oriented to the surface normal.
Seems so close to a solution but I’m at my wits end. Tried zeroing out local rotation in each of the axis one by one. Tried transform.lookAt. Tried everything. Help, please.
Well, not that anyone has been particularly interested in this thread, but I thought I should report my findings.
I have finally achieved the desired effect, by placing this line of code in the initiated object script. Just in case someone stumbles on a similar problem, here it is…