- Home /
How to calculate position of cannon's end
Hi, I am new in Unity3D. Currently in learning stage. I am creating shooting tank - http://pumpshooter.com/sETBSmUH My tank consist of 3 parts: Tank - Cube Turret - Capsule Cannon - Cylinder
I am trying to calculate the position of cannon's end to Instantiate projectile there.
GameObject cannon = GameObject.Find("Cannon");
var x = cannon.transform.position.x;
var y = cannon.transform.position.y;
var z = cannon.transform.position.z+cannon.transform.localScale.y/2;
var cannon_end = new Vector3(x,y,z);
I though the code "cannon.transform.localScale.y/2" will return half of Cannon's Y scale (cannon's total width) so I can plus it to cannon's center position (cannon.transform.position.z). But "cannon.transform.localScale.y/2" doesn't return half of cannon's width.
What should I use instead "cannon.transform.localScale.y/2" to calculate the value of half cannon width?
Answer by aldonaletto · Oct 07, 2012 at 11:39 PM
Actually, the recommended way is to create an empty object - let's name it "SpawnPoint" - and child it to the cannon: this way, you can adjust its position AND rotation in the Editor, which allows a lot of flexibility. You could then add the shooting script directly to the SpawnPoint object, what makes things easier.
Anyway, if the cannon is an Unity cylinder, it's probably rotated so that its local Y axis points the direction to shoot. If this is true, use cannon.transform.up to get the shooting direction, and offset it by localScale.y/2:
var tipOffset: float = cannon.transform.localScale.y/2;
var tipPoint: Vector3 = cannon.transform.position + cannon.transform.up * tipOffset;
Notice that this code will find the cylinder's tip, and probably any projectile instantiated at that position will collide with the cylinder. You should then use an offset bigger than localScale.y/2, or remove the cannon collider. That's why it's preferable to use a spawn point empty object - you can set it to any position you want, and it will follow the cannon movements because it's a cannon's child.
Aldo, I have few additional newbie questions because I don't understand something.
cannon.transform.localScale.y/2 returns half of cannon's total length (Y value of Scale). cannon.transform.position returns coordinates (Vector3(x,y,z)) of cannon's center location in the world space.
What value returns cannon.transform.up? Unity docs says "The green axis of the transform in world space." but I don't understand the description. UP is Y value represented by Vector3 but of what transform value (position||rotation||scale)? Is it the same as Vector3(0,1,0)?
Why do you multiply cannon.transform.up by tipOffset? How does work summarization of Vector3? (x+x, y+y, z+z)?
transform.up is a vector that points in the object's Y direction. When the object has no rotation, it's the same as Vector3(0,1,0). When the object is rotated, transform.up follows it, pointing to whatever direction the object's "head" is aligned to.
transform.up is an unit vector (length = 1); in order to find a point in the object's local up direction, multiply transform.up by the desired distance and add the result to the object position (vector addition adds x to x, y to y and z to z).
Think of a vector as an "arrow" pointing to some direction. When you add a vector to a point (a position), you get a new point at the arrow's tip (the arrow base is sit at the first point).
Aldo, thank you for the answer. If I am not mistaken in mathematics the length of the vector depends on X,Y,Z coordinates. It means that length isn't separate unique value which can be configured separately from x,y,z of the vector. Length is the distance from 0,0,0 to x,y,z point. So my transform.up isn't Vector(0,1,0). Right? I don't understand why it is "cannon.transform.position + cannon.transform.up * tipOffset" but not "cannon.transform.position + tipOffset".
you can normalize a vector just dividing each component by the vector length - and transform.up is a normalized vector (as well as transform.forward and transform.right). You can't just add tipOffset (a float) to transform.position (a point): you must define in which direction tipOffset must be added - that's why it's multiplied by transform.up: we want to find a point at tipOffset distance from transform.position, and in the object's up direction. Since transform.up is normalized, we just multiply it by the distance, what produces a vector in the desired direction and with the desired length - adding it to transform.position defines the point we want.
Another alternative is to create the vector in local space and convert it to world space with TransformPoint:
var tipPoint = cannon.transform.TransformPoint(Vector3(0, 1, 0));
This may be easier because you can visualize the point in local space, then apply the current rotation/position/scale transformation, positioning it in the correct world point. Notice that the local point has Y = 1: the standard cylinder primitive has height = 2, thus its top and bottom are at Y = 1 and Y = -1 in local space (TransformPoint takes the current scale into account, scaling the local point to the actual world size)
Your answer
Follow this Question
Related Questions
players positions when race ends. 4 Answers
How to stop a script in c# 2 Answers
Position to pixel coords from 2 points 0 Answers
Camera rotation around player while following. 6 Answers
Transform position only working correctly on one axis? 1 Answer