- Home /
How to create Arrows Between Two objects and Animate them
I want to create arrows as displayed in the image, i want to click one circle and then click another circle to dynamically create the arrows,, if one of the circles is moved, the arrows should still connect them.
(The arrows will be in the prefabs)
orTo create the connection i can either click the first circle and then click the second one for the arrows to appear
Ican click and hold on one of the circles and then be prompted to click the other circle.
Also i want to make some kind of animation that gives the impression that something is flowing from one end to the other.
I would really appreciate if you guys can guide me on how to do these two tasks. Thank you
Answer by AlwaysSunny · Jul 02, 2015 at 07:26 PM
The best approach will depend upon the aesthetic end result you desire.
My instinct is to recommend a line-drawing solution which builds and draws stretched, billboarded quads (lines) on the fly. This is what I use to draw lines and arrows in my project, and it's very nice to work with once you get the generator written. (My arrow heads are just two lines that describe a small acute shape at the end of the arrow).
Using prefabs and models for your arrows is viable too. (Note that if you need to billboard these arrows, you'll be in for quite a headache; not true of the custom line drawing method.) If a custom line drawer solution (you could do basic shapes too with the same logic) doesn't strike your fancy, I recommend the following basic structure:
A quad for the shaft of the arrow. The quad's origin should be located at the butt-end of the arrow. Scaling the correct axis of this quad should produce a nice line of arbitrary length, and rotating the transform to "look at" the correct point in space will make the line point where you want it.
A mesh for the head of the arrow. This mesh should not scale. Instead, its placement should be informed by the business-end of the stretched-quad shaft. Its rotation will be identical to the line quad's.
Another alternative involves a rigged mesh of an arrow whose shaft can stretch via bone animation, leaving the arrowhead's shape unaffected.
Once you can create this dynamic arrow, then you can get clever with animating it however you wish.
This sound TOO complex. I a semi Beginner at scripting. and I haven't used billboards or Quads much. Your solution sounds like it will work, but i have no idea how i will implement it programmatically. The solution that is co$$anonymous$$g in my own small head is that. What if i find the distance between the two objects as a vector. Then at the one end of the vector i instantiate the prefab of the arrow and then stretch it with the length of the vector? How i will do THIS is ALSO out of my abilities, hence i need help with the script somehow.
Unless you use one of the solutions I mentioned above or something similar, any arrowhead shape that's part of your mesh will skew and distort when the arrow is stretched beyond its native size. @samfarha's solution looks okay otherwise, but will not address the arrowhead distortion issue.
These goals aren't too awfully complicated, honest. They make a pretty good example for learning about vector math concepts and 3D problem solving in general.
If you're cool with the idea that arrows must always be the same size or they'll distort, then you can use a simplified method like samfarha's. If you want arrows of arbitrary size that avoid any distortion, you have to account for this in your solution.
In case it's helpful...
// Here's a vector whose direction points from A to B,
// and whose magnitude is the distance between A and B:
Vector3 difference = B - A;
// Here's the length of that vector, or the distance from A to B
float distance = difference.magnitude;
// Here's a version of that vector with a length of one,
// aka a "unit vector", which is a concept used a lot in 3D math.
// It can be thought of as "just the direction"
Vector3 direction = difference.normalized;
// Here's a completely redundant operation that just
// demonstrates how these two things go together
Vector3 originalDifferenceVector = direction * distance;
// Here's a vector that points from A to B,
// But whose length is exactly halfway between A and B,
Vector3 halfDifference = direction * (distance * 0.5f);
// Here's the actual position halfway between A and B,
Vector3 halfwayPoint = A + halfDifference;
Wow this is actually helpful, Ahh i remember one of my school classes,,so A and B are themselves vector 3s right?. Yes i understand the math now.. This will help me in all kinds of situtaions.. Thank you..
Answer by samfarha · Jul 03, 2015 at 12:41 PM
I just did this for my game too, Replace my anchorPos and currrentPos by the position of your 2 game objects. This works in 2d, not sure about 3d. Put this code in your script for your arrow game object.
Vector3 anchorPos = new Vector3(1,1,0);
Vector3 currentPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
currentPos.z = 0;
Vector3 midPointVector = (currentPos + anchorPos)/2;
transform.position = midPointVector;
Vector3 relative = currentPos - anchorPos;
float maggy = relative.magnitude;
transform.localScale = new Vector3(maggy/2,1,0);
Quaternion rotationVector = Quaternion.LookRotation(relative);
rotationVector.z = 0;
rotationVector.w = 0;
transform.rotation = rotationVector;
Awesome, let me try it, yes,2D would work fine as this will be part of GUI.Let me try it.
This worked. I dont understand the code in the end tho, the Tan stuff
public Transform A;
public Transform B;
public Vector3 anchorPos;
public Vector3 currentPos;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
anchorPos = new Vector3 (A.transform.position.x, A.transform.position.y, 0);
currentPos = new Vector3 (B.transform.position.x, B.transform.position.y, 0);
Vector3 midPointVector = (currentPos + anchorPos) / 2;
transform.position = midPointVector;
Vector3 relative = currentPos - anchorPos;
float maggy = relative.magnitude;
transform.localScale = new Vector3 (maggy / 2, 1, 0);
// Quaternion rotationVector = Quaternion.LookRotation (relative);
// rotationVector.z = 0;
// rotationVector.w = 0;
// transform.rotation = rotationVector - 90;
float angle = $$anonymous$$athf.Atan2 (relative.y, relative.x) * $$anonymous$$athf.Rad2Deg - 90;
Quaternion q = Quaternion.AngleAxis (angle, Vector3.forward);
transform.rotation = q;
}